- Timestamp:
- Oct 17, 2023, 8:50:05 AM (2 years ago)
- Branches:
- master
- Children:
- 37ceccb
- Parents:
- 2bf46a5 (diff), d85141f (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. - Location:
- src
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeTools/DeclStats.cc
r2bf46a5 r1b41219 25 25 #include "Common/PassVisitor.h" 26 26 #include "Common/VectorMap.h" // for VectorMap 27 #include "GenPoly/GenPoly.h" // for hasPolyBase28 27 #include "SynTree/LinkageSpec.h" // for ::NoOfSpecs, Spec 29 28 #include "SynTree/Declaration.h" // for FunctionDecl, TypeDecl, Declaration -
src/GenPoly/BoxNew.cpp
r2bf46a5 r1b41219 39 39 40 40 namespace { 41 42 /// Common field of several sub-passes of box.43 struct BoxPass {44 TypeVarMap scopeTypeVars;45 BoxPass() : scopeTypeVars( ast::TypeData() ) {}46 };47 41 48 42 // TODO: Could this be a common helper somewhere? … … 359 353 /// * Adds appropriate type variables to the function calls. 360 354 struct CallAdapter final : 361 public BoxPass,362 355 public ast::WithConstTypeSubstitution, 363 356 public ast::WithGuards, … … 376 369 ast::Expr const * postvisit( ast::AddressExpr const * expr ); 377 370 ast::ReturnStmt const * previsit( ast::ReturnStmt const * stmt ); 378 void previsit( ast::PointerType const * type );379 void previsit( ast::FunctionType const * type );380 371 381 372 void beginScope(); … … 386 377 // return value. 387 378 388 /// Pass the extra type parameters from polymorphic generic arguments or 389 /// return types into a function application. 390 ast::vector<ast::Expr>::iterator passArgTypeVars( 391 ast::ApplicationExpr * expr, ast::Type const * parmType, 392 ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg, 393 const TypeVarMap & exprTyVars, std::set<std::string> & seenTypes ); 394 /// Passes extra type parameters into a polymorphic function application. 379 /// Passes extra layout arguments for sized polymorphic type parameters. 395 380 ast::vector<ast::Expr>::iterator passTypeVars( 396 381 ast::ApplicationExpr * expr, 397 ast::Type const * polyRetType, 398 ast::FunctionType const * funcType, 399 const TypeVarMap & exprTyVars ); 382 ast::FunctionType const * funcType ); 400 383 /// Wraps a function application with a new temporary for the 401 384 /// out-parameter return value. … … 448 431 CodeLocation const & location, ast::Type const * type ); 449 432 450 /// Set of adapter functions in the current scope.433 TypeVarMap scopeTypeVars; 451 434 ScopedMap< std::string, ast::DeclWithType const * > adapters; 452 435 std::map< ast::ApplicationExpr const *, ast::Expr const * > retVals; … … 561 544 562 545 ast::FunctionDecl const * CallAdapter::previsit( ast::FunctionDecl const * decl ) { 546 // Prevent type declaration information from leaking out. 547 GuardScope( scopeTypeVars ); 548 563 549 if ( nullptr == decl->stmts ) { 564 // This may keep TypeDecls we don't ever want from sneaking in.565 // Not visiting child nodes might just be faster.566 GuardScope( scopeTypeVars );567 550 return decl; 568 551 } 569 552 570 GuardScope( scopeTypeVars );571 553 GuardValue( retval ); 572 554 … … 670 652 ptrdiff_t initArgCount = mutExpr->args.size(); 671 653 672 TypeVarMap exprTypeVars = { ast::TypeData() };654 TypeVarMap exprTypeVars; 673 655 // TODO: Should this take into account the variables already bound in 674 656 // scopeTypeVars ([ex] remove them from exprTypeVars)? … … 695 677 696 678 assert( typeSubs ); 697 ast::Type const * concRetType = replaceWithConcrete( dynRetType, *typeSubs );698 // Used to use dynRetType instead of concRetType; this changed so that699 // the correct type parameters are passed for return types (it should be700 // the concrete type's parameters, not the formal type's).701 679 ast::vector<ast::Expr>::iterator argIt = 702 passTypeVars( mutExpr, concRetType, function, exprTypeVars);680 passTypeVars( mutExpr, function ); 703 681 addInferredParams( mutExpr, argIt, function, exprTypeVars ); 704 682 … … 778 756 } 779 757 780 void CallAdapter::previsit( ast::PointerType const * type ) {781 GuardScope( scopeTypeVars );782 makeTypeVarMap( type, scopeTypeVars );783 }784 785 void CallAdapter::previsit( ast::FunctionType const * type ) {786 GuardScope( scopeTypeVars );787 makeTypeVarMap( type, scopeTypeVars );788 }789 790 758 void CallAdapter::beginScope() { 791 759 adapters.beginScope(); … … 812 780 } 813 781 814 // arg is an in/out parameter that matches the return value.815 ast::vector<ast::Expr>::iterator CallAdapter::passArgTypeVars(816 ast::ApplicationExpr * expr, ast::Type const * paramType,817 ast::Type const * argBaseType, ast::vector<ast::Expr>::iterator arg,818 const TypeVarMap & exprTypeVars, std::set<std::string> & seenTypes ) {819 ast::Type const * polyType = isPolyType( paramType, exprTypeVars );820 if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {821 return arg;822 }823 824 std::string typeName = Mangle::mangleType( polyType );825 if ( seenTypes.count( typeName ) ) return arg;826 827 arg = expr->args.insert( arg,828 new ast::SizeofExpr( expr->location, ast::deepCopy( argBaseType ) )829 );830 arg++;831 arg = expr->args.insert( arg,832 new ast::AlignofExpr( expr->location, ast::deepCopy( argBaseType ) )833 );834 arg++;835 if ( dynamic_cast<ast::StructInstType const *>( polyType ) ) {836 auto argBaseStructType =837 dynamic_cast<ast::StructInstType const *>( argBaseType );838 if ( nullptr == argBaseStructType ) {839 SemanticError( expr,840 "Cannot pass non-structure type for generic struct: " );841 }842 843 // Zero-length arrays are forbidden by C, so don't pass844 // offset for empty structure.845 if ( !argBaseStructType->base->members.empty() ) {846 arg = expr->args.insert( arg,847 new ast::OffsetPackExpr(848 expr->location,849 ast::deepCopy( argBaseStructType ) )850 );851 arg++;852 }853 }854 855 seenTypes.insert( typeName );856 return arg;857 }858 859 782 ast::vector<ast::Expr>::iterator CallAdapter::passTypeVars( 860 783 ast::ApplicationExpr * expr, 861 ast::Type const * polyRetType, 862 ast::FunctionType const * function, 863 const TypeVarMap & exprTypeVars ) { 784 ast::FunctionType const * function ) { 864 785 assert( typeSubs ); 865 786 ast::vector<ast::Expr>::iterator arg = expr->args.begin(); … … 880 801 new ast::AlignofExpr( expr->location, ast::deepCopy( concrete ) ) ); 881 802 arg++; 882 }883 884 // Add size/align for generic types to parameter list.885 if ( !expr->func->result ) return arg;886 ast::FunctionType const * funcType = getFunctionType( expr->func->result );887 assert( funcType );888 889 // This iterator points at first original argument.890 ast::vector<ast::Expr>::const_iterator funcArg;891 // Names for generic types we've seen.892 std::set<std::string> seenTypes;893 894 // A polymorphic return type may need to be added to the argument list.895 if ( polyRetType ) {896 assert( typeSubs );897 auto concRetType = replaceWithConcrete( polyRetType, *typeSubs );898 // TODO: This write-back may not be correct.899 arg = passArgTypeVars( expr, polyRetType, concRetType,900 arg, exprTypeVars, seenTypes );901 // Skip the return parameter in the argument list.902 funcArg = arg + 1;903 } else {904 funcArg = arg;905 }906 907 // TODO:908 // I believe this is (starts as) the number of original arguments to the909 // function with the args before funcArg all being inserted.910 ptrdiff_t argsToPass = std::distance( funcArg, expr->args.cend() );911 912 // Add type information args for presently unseen types in parameter list.913 ast::vector<ast::Type>::const_iterator funcParam = funcType->params.begin();914 // assert( funcType->params.size() == argsToPass );915 for ( ; funcParam != funcType->params.end() && 0 < argsToPass916 ; ++funcParam, --argsToPass ) {917 assert( 0 < argsToPass );918 assert( argsToPass <= (ptrdiff_t)expr->args.size() );919 ptrdiff_t index = expr->args.size() - argsToPass;920 ast::Type const * argType = expr->args[index]->result;921 if ( nullptr == argType ) continue;922 arg = passArgTypeVars( expr, *funcParam, argType,923 arg, exprTypeVars, seenTypes );924 803 } 925 804 return arg; … … 1523 1402 } 1524 1403 1525 ast::ObjectDecl * makePtr(1526 CodeLocation const & location, std::string const & name ) {1527 return new ast::ObjectDecl( location, name,1528 new ast::PointerType( makeSizeAlignType() ),1529 nullptr, ast::Storage::Classes(), ast::Linkage::C, nullptr );1530 }1531 1532 1404 ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) { 1533 TypeVarMap localTypeVars = { ast::TypeData() };1405 TypeVarMap localTypeVars; 1534 1406 makeTypeVarMap( decl, localTypeVars ); 1535 1407 … … 1584 1456 mutDecl->assertions.clear(); 1585 1457 1586 // Add size/align for generic parameter types to parameter list.1587 std::set<std::string> seenTypes;1588 ast::vector<ast::DeclWithType> otypeParams;1589 for ( ast::ptr<ast::DeclWithType> & funcParam : mutDecl->params ) {1590 ast::Type const * polyType = isPolyType( funcParam->get_type(), localTypeVars );1591 if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1592 continue;1593 }1594 std::string typeName = Mangle::mangleType( polyType );1595 if ( seenTypes.count( typeName ) ) continue;1596 seenTypes.insert( typeName );1597 1598 auto sizeParam = makeObj( funcParam->location, sizeofName( typeName ) );1599 otypeParams.emplace_back( sizeParam );1600 1601 auto alignParam = makeObj( funcParam->location, alignofName( typeName ) );1602 otypeParams.emplace_back( alignParam );1603 1604 // Zero-length arrays are illegal in C, so empty structs have no1605 // offset array.1606 if ( auto * polyStruct =1607 dynamic_cast<ast::StructInstType const *>( polyType ) ;1608 polyStruct && !polyStruct->base->members.empty() ) {1609 auto offsetParam = makePtr( funcParam->location, offsetofName( typeName ) );1610 otypeParams.emplace_back( offsetParam );1611 }1612 }1613 1614 1458 // Prepend each argument group. From last group to first. addAdapters 1615 1459 // does do the same, it just does it itself and see all other parameters. 1616 1460 spliceBegin( mutDecl->params, inferredParams ); 1617 spliceBegin( mutDecl->params, otypeParams );1618 1461 spliceBegin( mutDecl->params, layoutParams ); 1619 1462 addAdapters( mutDecl, localTypeVars ); … … 1708 1551 assertf( it != adapters.end(), "Could not correct floating node." ); 1709 1552 return ast::mutate_field( expr, &ast::VariableExpr::var, it->second ); 1710 1711 1553 } 1712 1554 … … 1720 1562 /// * Inserts dynamic calculation of polymorphic type layouts where needed. 1721 1563 struct PolyGenericCalculator final : 1722 public BoxPass,1723 1564 public ast::WithConstTypeSubstitution, 1724 1565 public ast::WithDeclsToAdd<>, … … 1728 1569 PolyGenericCalculator(); 1729 1570 1730 void previsit( ast::ObjectDecl const * decl );1731 1571 void previsit( ast::FunctionDecl const * decl ); 1732 1572 void previsit( ast::TypedefDecl const * decl ); … … 1735 1575 ast::StructDecl const * previsit( ast::StructDecl const * decl ); 1736 1576 ast::UnionDecl const * previsit( ast::UnionDecl const * decl ); 1737 void previsit( ast::PointerType const * type );1738 void previsit( ast::FunctionType const * type );1739 1577 ast::DeclStmt const * previsit( ast::DeclStmt const * stmt ); 1740 1578 ast::Expr const * postvisit( ast::MemberExpr const * expr ); … … 1768 1606 /// C sizeof(). 1769 1607 ast::Expr const * genSizeof( CodeLocation const &, ast::Type const * ); 1770 1771 1608 /// Enters a new scope for type-variables, 1772 1609 /// adding the type variables from the provided type. 1773 1610 void beginTypeScope( ast::Type const * ); 1774 /// Enters a new scope for known layouts and offsets, and queues exit calls. 1775 void beginGenericScope();1776 1611 1612 /// The type variables and polymorphic parameters currently in scope. 1613 TypeVarMap scopeTypeVars; 1777 1614 /// Set of generic type layouts known in the current scope, 1778 1615 /// indexed by sizeofName. … … 1785 1622 /// If the argument of an AddressExpr is MemberExpr, it is stored here. 1786 1623 ast::MemberExpr const * addrMember = nullptr; 1787 /// Used to avoid recursing too deep in type declarations.1788 bool expect_func_type = false;1789 1624 }; 1790 1625 … … 1808 1643 } 1809 1644 1810 void PolyGenericCalculator::previsit( ast::ObjectDecl const * decl ) { 1645 void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) { 1646 GuardScope( *this ); 1811 1647 beginTypeScope( decl->type ); 1812 }1813 1814 void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) {1815 beginGenericScope();1816 beginTypeScope( decl->type );1817 1818 // TODO: Going though dec->params does not work for some reason.1819 for ( ast::ptr<ast::Type> const & funcParam : decl->type->params ) {1820 // Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`1821 ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );1822 if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1823 knownLayouts.insert( Mangle::mangleType( polyType ) );1824 }1825 }1826 1648 } 1827 1649 … … 1838 1660 ast::TypeDecl const * decl ) { 1839 1661 ast::Type const * base = decl->base; 1840 if ( nullptr == base ) return decl;1662 if ( nullptr == base ) return decl; 1841 1663 1842 1664 // Add size/align variables for opaque type declarations. … … 1863 1685 alignDecl->accept( *visitor ); 1864 1686 1865 // Can't use [makeVar], because it inserts into stmtsToAdd and TypeDecls1866 // can occur at global scope.1687 // A little trick to replace this with two declarations. 1688 // Adding after makes sure that there is no conflict with adding stmts. 1867 1689 declsToAddAfter.push_back( alignDecl ); 1868 // replace with sizeDecl.1869 1690 return sizeDecl; 1870 1691 } … … 1884 1705 } 1885 1706 1886 void PolyGenericCalculator::previsit( ast::PointerType const * type ) {1887 beginTypeScope( type );1888 }1889 1890 void PolyGenericCalculator::previsit( ast::FunctionType const * type ) {1891 beginTypeScope( type );1892 1893 GuardValue( expect_func_type );1894 GuardScope( *this );1895 1896 // The other functions type we will see in this scope are probably1897 // function parameters they don't help us with the layout and offsets so1898 // don't mark them as known in this scope.1899 expect_func_type = false;1900 1901 // Make sure that any type information passed into the function is1902 // accounted for.1903 for ( ast::ptr<ast::Type> const & funcParam : type->params ) {1904 // Condition here duplicates that in `DeclAdapter::previsit( FunctionDecl const * )`1905 ast::Type const * polyType = isPolyType( funcParam, scopeTypeVars );1906 if ( polyType && !dynamic_cast<ast::TypeInstType const *>( polyType ) ) {1907 knownLayouts.insert( Mangle::mangleType( polyType ) );1908 }1909 }1910 }1911 1912 //void PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) {1913 1707 ast::DeclStmt const * PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) { 1914 1708 ast::ObjectDecl const * decl = stmt->decl.as<ast::ObjectDecl>(); … … 1918 1712 1919 1713 // Change initialization of a polymorphic value object to allocate via a 1920 // variable-length-array (alloca was previouly used, but it cannot be 1921 // safely used in loops). 1714 // variable-length-array (alloca cannot be safely used in loops). 1922 1715 ast::ObjectDecl * newBuf = new ast::ObjectDecl( decl->location, 1923 1716 bufNamer.newName(), … … 2400 2193 } 2401 2194 2402 void PolyGenericCalculator::beginGenericScope() {2403 GuardScope( *this );2404 // We expect the first function type see to be the type relating to this2405 // scope but any further type is probably some unrelated function pointer2406 // keep track of whrich is the first.2407 GuardValue( expect_func_type ) = true;2408 }2409 2410 2195 // -------------------------------------------------------------------------- 2411 /// No common theme found.2196 /// Removes unneeded or incorrect type information. 2412 2197 /// * Replaces initialization of polymorphic values with alloca. 2413 2198 /// * Replaces declaration of dtype/ftype with appropriate void expression. … … 2415 2200 /// * Strips fields from generic structure declarations. 2416 2201 struct Eraser final : 2417 public BoxPass,2418 2202 public ast::WithGuards { 2419 2203 void guardTypeVarMap( ast::Type const * type ) { … … 2430 2214 void previsit( ast::PointerType const * type ); 2431 2215 void previsit( ast::FunctionType const * type ); 2216 public: 2217 TypeVarMap scopeTypeVars; 2432 2218 }; 2433 2219 -
src/GenPoly/GenPoly.cc
r2bf46a5 r1b41219 273 273 if ( func->returns.empty() ) return nullptr; 274 274 275 TypeVarMap forallTypes = { ast::TypeData() };275 TypeVarMap forallTypes; 276 276 makeTypeVarMap( func, forallTypes ); 277 277 return isDynType( func->returns.front(), forallTypes ); … … 801 801 const ast::FunctionType * function = getFunctionType( expr->func->result ); 802 802 assertf( function, "ApplicationExpr has non-function type: %s", toString( expr->func->result ).c_str() ); 803 TypeVarMap exprTyVars = { ast::TypeData() };803 TypeVarMap exprTyVars; 804 804 makeTypeVarMap( function, exprTyVars ); 805 805 return needsBoxing( param, arg, exprTyVars, subst ); -
src/GenPoly/GenPoly.h
r2bf46a5 r1b41219 33 33 34 34 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap; 35 using TypeVarMap = ErasableScopedMap< ast::TypeEnvKey, ast::TypeData >; 35 struct TypeVarMap : public ErasableScopedMap<ast::TypeEnvKey, ast::TypeData> { 36 TypeVarMap() : ErasableScopedMap( ast::TypeData() ) {} 37 }; 36 38 37 39 /// Replaces a TypeInstType by its referrent in the environment, if applicable -
src/GenPoly/SpecializeNew.cpp
r2bf46a5 r1b41219 81 81 } 82 82 83 // The number of elements in a type if it is a flattened tuple.84 size_t flatT upleSize( const ast::Type * type) {85 if ( auto tuple = dynamic_cast<const ast::TupleType *>( type ) ) {86 size_t sum = 0;87 for ( auto t : *tuple) {88 sum += flatT upleSize( t);89 } 90 return sum;91 } else {92 return 1;93 }83 // The number of elements in a list, if all tuples had been flattened. 84 size_t flatTypeListSize( const std::vector<ast::ptr<ast::Type>> & types ) { 85 size_t sum = 0; 86 for ( const ast::ptr<ast::Type> & type : types ) { 87 if ( const ast::TupleType * tuple = type.as<ast::TupleType>() ) { 88 sum += flatTypeListSize( tuple->types ); 89 } else { 90 sum += 1; 91 } 92 } 93 return sum; 94 94 } 95 95 96 96 // Find the total number of components in a parameter list. 97 97 size_t functionParameterSize( const ast::FunctionType * type ) { 98 size_t sum = 0; 99 for ( auto param : type->params ) { 100 sum += flatTupleSize( param ); 101 } 102 return sum; 98 return flatTypeListSize( type->params ); 103 99 } 104 100
Note:
See TracChangeset
for help on using the changeset viewer.