Changeset c532847
- Timestamp:
- Oct 24, 2020, 9:42:38 AM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- a3f36dc
- Parents:
- 76d73fc (diff), e7d6968 (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:
-
- 1 added
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r76d73fc rc532847 47 47 48 48 //================================================================================================ 49 namespace {49 namespace ast { 50 50 51 51 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 52 52 // allow us to use the same stratagy in the new ast. 53 // xxx - since convert back pass works, this concern seems to be unnecessary. 54 55 // these need to be accessed in new FixInit now 53 56 ast::Type * sizeType = nullptr; 54 57 ast::FunctionDecl * dereferenceOperator = nullptr; … … 63 66 using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >; 64 67 Cache cache; 68 69 // Statements can no longer be shared. 70 // however, since StmtExprResult is now implemented, need to still maintain 71 // readonly references. 72 Cache readonlyCache; 65 73 66 74 template<typename T> … … 154 162 } 155 163 156 const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final { 157 auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth ); 158 auto&& type = get<Type>().accept1( node->type ); 159 auto&& init = get<Initializer>().accept1( node->init ); 160 auto&& attr = get<Attribute>().acceptL( node->attributes ); 164 const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final { 161 165 if ( inCache( node ) ) { 162 166 return nullptr; 163 167 } 168 auto bfwd = get<Expression>().accept1( node->bitfieldWidth ); 169 auto type = get<Type>().accept1( node->type ); 170 auto attr = get<Attribute>().acceptL( node->attributes ); 171 164 172 auto decl = new ObjectDecl( 165 173 node->name, … … 168 176 bfwd, 169 177 type->clone(), 170 init,178 nullptr, // prevent infinite loop 171 179 attr, 172 180 Type::FuncSpecifiers( node->funcSpec.val ) 173 181 ); 174 return declWithTypePostamble( decl, node ); 182 183 // handles the case where node->init references itself 184 // xxx - does it really happen? 185 declWithTypePostamble(decl, node); 186 auto init = get<Initializer>().accept1( node->init ); 187 decl->init = init; 188 189 this->node = decl; 190 return nullptr; 175 191 } 176 192 … … 205 221 decl->statements = get<CompoundStmt>().accept1( node->stmts ); 206 222 decl->withExprs = get<Expression>().acceptL( node->withExprs ); 207 if ( dereferenceOperator == node ) {223 if ( ast::dereferenceOperator == node ) { 208 224 Validate::dereferenceOperator = decl; 209 225 } 210 if ( dtorStructDestroy == node ) {226 if ( ast::dtorStructDestroy == node ) { 211 227 Validate::dtorStructDestroy = decl; 212 228 } … … 267 283 ); 268 284 269 if ( dtorStruct == node ) {285 if ( ast::dtorStruct == node ) { 270 286 Validate::dtorStruct = decl; 271 287 } … … 320 336 321 337 const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) { 322 cache.emplace( node, stmt ); 338 // force statements in old tree to be unique. 339 // cache.emplace( node, stmt ); 340 readonlyCache.emplace( node, stmt ); 323 341 stmt->location = node->location; 324 342 stmt->labels = makeLabelL( stmt, node->labels ); … … 337 355 if ( inCache( node ) ) return nullptr; 338 356 auto stmt = new ExprStmt( nullptr ); 339 cache.emplace( node, stmt );340 357 stmt->expr = get<Expression>().accept1( node->expr ); 341 358 return stmtPostamble( stmt, node ); … … 1011 1028 auto stmts = node->stmts; 1012 1029 // disable sharing between multiple StmtExprs explicitly. 1013 if (inCache(stmts)) { 1014 stmts = ast::deepCopy(stmts.get()); 1015 } 1030 // this should no longer be true. 1031 1016 1032 auto rslt = new StmtExpr( 1017 1033 get<CompoundStmt>().accept1(stmts) … … 1020 1036 rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls); 1021 1037 rslt->dtors = get<Expression>().acceptL(node->dtors); 1038 if (node->resultExpr) { 1039 // this MUST be found by children visit 1040 rslt->resultExpr = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr)); 1041 } 1022 1042 1023 1043 auto expr = visitBaseExpr( node, rslt ); … … 1036 1056 1037 1057 auto expr = visitBaseExpr( node, rslt ); 1038 this->node = expr ;1058 this->node = expr->clone(); 1039 1059 return nullptr; 1040 1060 } … … 1126 1146 auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind }; 1127 1147 // I believe this should always be a BasicType. 1128 if ( sizeType == node ) {1148 if ( ast::sizeType == node ) { 1129 1149 Validate::SizeType = type; 1130 1150 } … … 1529 1549 1530 1550 // function type is now derived from parameter decls instead of storing them 1551 1552 /* 1531 1553 auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type)); 1532 1554 ftype->params.reserve(paramVars.size()); … … 1540 1562 } 1541 1563 ftype->forall = std::move(forall); 1542 visitType(old->type, ftype); 1564 */ 1565 1566 // can function type have attributes? seems not to be the case. 1567 // visitType(old->type, ftype); 1543 1568 1544 1569 auto decl = new ast::FunctionDecl{ … … 1546 1571 old->name, 1547 1572 // GET_ACCEPT_1(type, FunctionType), 1573 std::move(forall), 1548 1574 std::move(paramVars), 1549 1575 std::move(returnVars), … … 1552 1578 { old->linkage.val }, 1553 1579 GET_ACCEPT_V(attributes, Attribute), 1554 { old->get_funcSpec().val } 1580 { old->get_funcSpec().val }, 1581 old->type->isVarArgs 1555 1582 }; 1556 1583 1557 decl->type = ftype;1584 // decl->type = ftype; 1558 1585 cache.emplace( old, decl ); 1559 1586 … … 1570 1597 1571 1598 if ( Validate::dereferenceOperator == old ) { 1572 dereferenceOperator = decl;1599 ast::dereferenceOperator = decl; 1573 1600 } 1574 1601 1575 1602 if ( Validate::dtorStructDestroy == old ) { 1576 dtorStructDestroy = decl;1603 ast::dtorStructDestroy = decl; 1577 1604 } 1578 1605 } … … 1599 1626 1600 1627 if ( Validate::dtorStruct == old ) { 1601 dtorStruct = decl;1628 ast::dtorStruct = decl; 1602 1629 } 1603 1630 } … … 2531 2558 // I believe this should always be a BasicType. 2532 2559 if ( Validate::SizeType == old ) { 2533 sizeType = type;2560 ast::sizeType = type; 2534 2561 } 2535 2562 visitType( old, type ); -
src/AST/Decl.cpp
r76d73fc rc532847 48 48 49 49 // --- FunctionDecl 50 51 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 52 std::vector<ptr<TypeDecl>>&& forall, 53 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 54 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 55 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs) 56 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 57 stmts( stmts ) { 58 FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs)); 59 for (auto & param : this->params) { 60 ftype->params.emplace_back(param->get_type()); 61 } 62 for (auto & ret : this->returns) { 63 ftype->returns.emplace_back(ret->get_type()); 64 } 65 ftype->forall = std::move(forall); 66 this->type = ftype; 67 } 68 50 69 51 70 const Type * FunctionDecl::get_type() const { return type.get(); } -
src/AST/Decl.hpp
r76d73fc rc532847 131 131 std::vector< ptr<Expr> > withExprs; 132 132 133 FunctionDecl( const CodeLocation & loc, const std::string & name, 133 FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall, 134 134 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 135 135 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 136 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {} )137 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),138 stmts( stmts ) {}136 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 137 // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 138 // stmts( stmts ) {} 139 139 140 140 const Type * get_type() const override; -
src/AST/DeclReplacer.cpp
r76d73fc rc532847 38 38 const ast::TypeInstType * previsit( const ast::TypeInstType * ); 39 39 }; 40 41 struct VarExprReplacer { 42 private: 43 const ExprMap & exprMap; 44 45 public: 46 VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {} 47 48 const Expr * postvisit (const VariableExpr *); 49 }; 40 50 } 41 51 … … 54 64 DeclMap declMap; 55 65 return replace( node, declMap, typeMap, debug ); 66 } 67 68 const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) { 69 Pass<VarExprReplacer> replacer = {exprMap}; 70 return node->accept( replacer ); 56 71 } 57 72 … … 88 103 return ninst; 89 104 } 105 106 const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) { 107 if (!exprMap.count(expr->var)) return expr; 108 109 return exprMap.at(expr->var); 110 } 111 90 112 } 91 113 } -
src/AST/DeclReplacer.hpp
r76d73fc rc532847 23 23 class DeclWithType; 24 24 class TypeDecl; 25 class Expr; 25 26 26 27 namespace DeclReplacer { 27 28 using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >; 28 29 using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >; 30 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >; 29 31 30 32 const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false ); 31 33 const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false ); 32 34 const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false ); 35 const Node * replace( const Node * node, const ExprMap & exprMap); 33 36 } 34 37 } -
src/AST/Expr.cpp
r76d73fc rc532847 67 67 // --- UntypedExpr 68 68 69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) { 70 70 assert( arg ); 71 71 … … 92 92 } 93 93 94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs,Expr * rhs ) {94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) { 95 95 assert( lhs && rhs ); 96 96 -
src/AST/Expr.hpp
r76d73fc rc532847 226 226 227 227 /// Creates a new dereference expression 228 static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );228 static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg ); 229 229 /// Creates a new assignment expression 230 static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs,Expr * rhs );230 static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ); 231 231 232 232 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 422 422 const CodeLocation & loc, const Type * ty, const std::string & r, 423 423 std::optional<unsigned long long> i ) 424 : Expr( loc, ty ), rep( r ), ival( i ) {}424 : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {} 425 425 426 426 /// Gets the integer value of this constant, if one is appropriate to its type. … … 617 617 618 618 ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call ) 619 : Expr( loc, call->result ) { assert( call); }619 : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); } 620 620 621 621 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 742 742 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s) 743 743 744 readonly<ExprStmt> resultExpr; 745 744 746 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss ); 745 747 -
src/AST/Fwd.hpp
r76d73fc rc532847 137 137 typedef unsigned int UniqueId; 138 138 139 extern Type * sizeType; 140 extern FunctionDecl * dereferenceOperator; 141 extern StructDecl * dtorStruct; 142 extern FunctionDecl * dtorStructDestroy; 143 139 144 } -
src/AST/Node.hpp
r76d73fc rc532847 49 49 50 50 bool unique() const { return strong_count == 1; } 51 bool isManaged() const {return strong_count > 0; } 51 52 52 53 private: -
src/AST/Pass.hpp
r76d73fc rc532847 236 236 const ast::Expr * call_accept( const ast::Expr * ); 237 237 238 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 239 240 const ast::Stmt * call_accept_as_compound(const ast::Stmt *); 241 238 242 template< typename node_t > 239 243 auto call_accept( const node_t * node ) -> typename std::enable_if< … … 257 261 template<typename node_t, typename parent_t, typename child_t> 258 262 void maybe_accept(const node_t * &, child_t parent_t::* child); 263 264 template<typename node_t, typename parent_t, typename child_t> 265 void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child); 259 266 260 267 private: -
src/AST/Pass.impl.hpp
r76d73fc rc532847 167 167 __pedantic_pass_assert( stmt ); 168 168 169 return stmt->accept( *this ); 170 } 171 172 template< typename core_t > 173 const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 174 __pedantic_pass_assert( __visit_children() ); 175 __pedantic_pass_assert( stmt ); 176 169 177 // add a few useful symbols to the scope 170 178 using __pass::empty; … … 324 332 325 333 auto new_val = call_accept( old_val ); 334 335 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); 336 337 if( __pass::differs(old_val, new_val) ) { 338 auto new_parent = __pass::mutate<core_t>(parent); 339 new_parent->*child = new_val; 340 parent = new_parent; 341 } 342 } 343 344 template< typename core_t > 345 template<typename node_t, typename parent_t, typename child_t> 346 void ast::Pass< core_t >::maybe_accept_as_compound( 347 const node_t * & parent, 348 child_t parent_t::*child 349 ) { 350 static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" ); 351 352 if(__pass::skip(parent->*child)) return; 353 const auto & old_val = __pass::get(parent->*child, 0); 354 355 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); 356 357 auto new_val = call_accept_as_compound( old_val ); 326 358 327 359 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); … … 703 735 maybe_accept( node, &IfStmt::inits ); 704 736 maybe_accept( node, &IfStmt::cond ); 705 maybe_accept ( node, &IfStmt::thenPart );706 maybe_accept ( node, &IfStmt::elsePart );737 maybe_accept_as_compound( node, &IfStmt::thenPart ); 738 maybe_accept_as_compound( node, &IfStmt::elsePart ); 707 739 }) 708 740 … … 721 753 maybe_accept( node, &WhileStmt::inits ); 722 754 maybe_accept( node, &WhileStmt::cond ); 723 maybe_accept ( node, &WhileStmt::body );755 maybe_accept_as_compound( node, &WhileStmt::body ); 724 756 }) 725 757 … … 736 768 // for statements introduce a level of scope (for the initialization) 737 769 guard_symtab guard { *this }; 770 // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later. 738 771 maybe_accept( node, &ForStmt::inits ); 739 772 maybe_accept( node, &ForStmt::cond ); 740 773 maybe_accept( node, &ForStmt::inc ); 741 maybe_accept ( node, &ForStmt::body );774 maybe_accept_as_compound( node, &ForStmt::body ); 742 775 }) 743 776 … … 834 867 maybe_accept( node, &CatchStmt::decl ); 835 868 maybe_accept( node, &CatchStmt::cond ); 836 maybe_accept ( node, &CatchStmt::body );869 maybe_accept_as_compound( node, &CatchStmt::body ); 837 870 }) 838 871 -
src/AST/SymbolTable.cpp
r76d73fc rc532847 335 335 } 336 336 337 /* 338 void SymbolTable::addFunction Type( const FunctionType * ftype) {339 addTypes( f type->forall );340 addIds( f type->returns );341 addIds( f type->params );342 } 343 */ 337 338 void SymbolTable::addFunction( const FunctionDecl * func ) { 339 addTypes( func->type->forall ); 340 addIds( func->returns ); 341 addIds( func->params ); 342 } 343 344 344 345 345 void SymbolTable::lazyInitScope() { -
src/AST/SymbolTable.hpp
r76d73fc rc532847 145 145 146 146 /// convenience function for adding all of the declarations in a function type to the indexer 147 // void addFunctionType( const FunctionType * ftype);147 void addFunction( const FunctionDecl * ); 148 148 149 149 private: -
src/Common/utility.h
r76d73fc rc532847 360 360 reverse_iterate_t( T & ref ) : ref(ref) {} 361 361 362 typedef typename T::reverse_iterator iterator; 363 iterator begin() { return ref.rbegin(); } 364 iterator end() { return ref.rend(); } 362 // this does NOT work on const T!!! 363 // typedef typename T::reverse_iterator iterator; 364 auto begin() { return ref.rbegin(); } 365 auto end() { return ref.rend(); } 365 366 }; 366 367 -
src/GenPoly/GenPoly.cc
r76d73fc rc532847 46 46 } 47 47 48 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env) { 49 for (auto ¶m : params) { 50 auto paramType = param.strict_as<ast::TypeExpr>(); 51 if (isPolyType(paramType->type, env)) return true; 52 } 53 return false; 54 } 55 48 56 /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present 49 57 bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { … … 56 64 } 57 65 66 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap & tyVars, const ast::TypeSubstitution * env) { 67 for (auto ¶m : params) { 68 auto paramType = param.strict_as<ast::TypeExpr>(); 69 if (isPolyType(paramType->type, tyVars, env)) return true; 70 } 71 return false; 72 } 73 58 74 /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present 59 75 bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { … … 92 108 Type *newType = env->lookup( typeInst->get_name() ); 93 109 if ( newType ) return newType; 110 } 111 return type; 112 } 113 114 const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) { 115 if (!env) return type; 116 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) { 117 auto newType = env->lookup(typeInst->name); 118 if (newType) return newType; 94 119 } 95 120 return type; … … 111 136 } 112 137 138 const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env) { 139 type = replaceTypeInst( type, env ); 140 141 if ( dynamic_cast< const ast::TypeInstType * >( type ) ) { 142 return type; 143 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { 144 return isPolyType( arrayType->base, env ); 145 } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) { 146 if ( hasPolyParams( structType->params, env ) ) return type; 147 } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) { 148 if ( hasPolyParams( unionType->params, env ) ) return type; 149 } 150 return 0; 151 } 152 113 153 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { 114 154 type = replaceTypeInst( type, env ); … … 126 166 } 127 167 return 0; 168 } 169 170 const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env) { 171 type = replaceTypeInst( type, env ); 172 173 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) { 174 return tyVars.find(typeInst->name) != tyVars.end() ? type : nullptr; 175 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { 176 return isPolyType( arrayType->base, env ); 177 } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) { 178 if ( hasPolyParams( structType->params, env ) ) return type; 179 } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) { 180 if ( hasPolyParams( unionType->params, env ) ) return type; 181 } 182 return nullptr; 128 183 } 129 184 … … 449 504 } 450 505 506 namespace { 507 // temporary hack to avoid re-implementing anything related to TyVarMap 508 // does this work? these two structs have identical definitions. 509 inline TypeDecl::Data convData(const ast::TypeDecl::Data & data) { 510 return *reinterpret_cast<const TypeDecl::Data *>(&data); 511 } 512 } 513 451 514 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) { 452 515 // is parameter is not polymorphic, don't need to box … … 459 522 } 460 523 524 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env) { 525 // is parameter is not polymorphic, don't need to box 526 if ( ! isPolyType( param, exprTyVars ) ) return false; 527 ast::ptr<ast::Type> newType = arg; 528 if ( env ) env->apply( newType ); 529 // if the argument's type is polymorphic, we don't need to box again! 530 return ! isPolyType( newType ); 531 } 532 461 533 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) { 462 534 FunctionType * function = getFunctionType( appExpr->function->result ); … … 467 539 } 468 540 541 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env) { 542 const ast::FunctionType * function = getFunctionType(appExpr->func->result); 543 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->func->result ).c_str() ); 544 TyVarMap exprTyVars(TypeDecl::Data{}); 545 makeTyVarMap(function, exprTyVars); 546 return needsBoxing(param, arg, exprTyVars, env); 547 548 } 549 469 550 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) { 470 551 tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } ); 552 } 553 554 void addToTyVarMap( const ast::TypeDecl * tyVar, TyVarMap & tyVarMap) { 555 tyVarMap.insert(tyVar->name, convData(ast::TypeDecl::Data{tyVar})); 471 556 } 472 557 … … 478 563 if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) { 479 564 makeTyVarMap( pointer->get_base(), tyVarMap ); 565 } 566 } 567 568 void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) { 569 if (auto ptype = dynamic_cast<const ast::ParameterizedType *>(type)) { 570 for (auto & tyVar : ptype->forall) { 571 assert (tyVar); 572 addToTyVarMap(tyVar, tyVarMap); 573 } 574 } 575 if (auto pointer = dynamic_cast<const ast::PointerType *>(type)) { 576 makeTyVarMap(pointer->base, tyVarMap); 480 577 } 481 578 } -
src/GenPoly/GenPoly.h
r76d73fc rc532847 26 26 27 27 namespace GenPoly { 28 28 29 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap; 29 30 30 /// Replaces a TypeInstType by its referrent in the environment, if applicable 31 31 Type* replaceTypeInst( Type* type, const TypeSubstitution* env ); … … 33 33 /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided 34 34 Type *isPolyType( Type *type, const TypeSubstitution *env = 0 ); 35 const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr); 35 36 36 37 /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 37 38 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 ); 39 const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env = nullptr); 38 40 39 41 /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided … … 84 86 /// true if arg requires boxing given exprTyVars 85 87 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ); 88 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env); 86 89 87 90 /// true if arg requires boxing in the call to appExpr 88 91 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ); 92 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env); 89 93 90 94 /// Adds the type variable `tyVar` to `tyVarMap` … … 93 97 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 94 98 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ); 99 void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap); 95 100 96 101 /// Prints type variable map -
src/InitTweak/FixGlobalInit.cc
r76d73fc rc532847 34 34 #include "SynTree/Visitor.h" // for acceptAll, Visitor 35 35 36 #include "AST/Expr.hpp" 37 #include "AST/Node.hpp" 38 #include "AST/Pass.hpp" 39 36 40 namespace InitTweak { 37 41 class GlobalFixer : public WithShortCircuiting { … … 50 54 FunctionDecl * initFunction; 51 55 FunctionDecl * destroyFunction; 56 }; 57 58 class GlobalFixer_new : public ast::WithShortCircuiting { 59 public: 60 void previsit (const ast::ObjectDecl *); 61 void previsit (const ast::FunctionDecl *) { visit_children = false; } 62 void previsit (const ast::StructDecl *) { visit_children = false; } 63 void previsit (const ast::UnionDecl *) { visit_children = false; } 64 void previsit (const ast::EnumDecl *) { visit_children = false; } 65 void previsit (const ast::TraitDecl *) { visit_children = false; } 66 void previsit (const ast::TypeDecl *) { visit_children = false; } 67 68 std::list< ast::ptr<ast::Stmt> > initStmts; 69 std::list< ast::ptr<ast::Stmt> > destroyStmts; 52 70 }; 53 71 … … 91 109 } 92 110 111 void fixGlobalInit(std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary) { 112 ast::Pass<GlobalFixer_new> fixer; 113 accept_all(translationUnit, fixer); 114 115 if ( !fixer.core.initStmts.empty() ) { 116 std::vector<ast::ptr<ast::Expr>> ctorParams; 117 if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200)); 118 auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)), 119 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))}); 120 121 translationUnit.emplace_back( initFunction ); 122 } // if 123 124 if ( !fixer.core.destroyStmts.empty() ) { 125 std::vector<ast::ptr<ast::Expr>> dtorParams; 126 if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200)); 127 auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)), 128 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))}); 129 130 translationUnit.emplace_back(destroyFunction); 131 } // if 132 } 133 93 134 void GlobalFixer::previsit( ObjectDecl *objDecl ) { 94 135 std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids(); … … 127 168 } 128 169 170 void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) { 171 auto mutDecl = mutate(objDecl); 172 assertf(mutDecl == objDecl, "Global object decl must be unique"); 173 if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) { 174 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 175 assert( ! ctorInit->ctor || ! ctorInit->init ); 176 177 const ast::Stmt * dtor = ctorInit->dtor; 178 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 179 // don't need to call intrinsic dtor, because it does nothing, but 180 // non-intrinsic dtors must be called 181 destroyStmts.push_front( dtor ); 182 // ctorInit->dtor = nullptr; 183 } // if 184 if ( const ast::Stmt * ctor = ctorInit->ctor ) { 185 initStmts.push_back( ctor ); 186 mutDecl->init = nullptr; 187 // ctorInit->ctor = nullptr; 188 } else if ( const ast::Init * init = ctorInit->init ) { 189 mutDecl->init = init; 190 // ctorInit->init = nullptr; 191 } else { 192 // no constructor and no initializer, which is okay 193 mutDecl->init = nullptr; 194 } // if 195 // delete ctorInit; 196 } // if 197 } 198 129 199 // only modify global variables 130 200 void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; } -
src/InitTweak/FixGlobalInit.h
r76d73fc rc532847 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp> 22 23 21 24 class Declaration; 22 25 … … 26 29 /// function is for library code. 27 30 void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ); 31 void fixGlobalInit( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary ); 28 32 } // namespace 29 33 -
src/InitTweak/FixInit.cc
r76d73fc rc532847 219 219 }; 220 220 221 struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution,public WithStmtsToAdd {221 struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd { 222 222 /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places. 223 223 static void split( std::list< Declaration * > &translationUnit ); -
src/InitTweak/FixInit.h
r76d73fc rc532847 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp> 22 21 23 class Declaration; 22 24 … … 24 26 /// replace constructor initializers with expression statements and unwrap basic C-style initializers 25 27 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 28 29 void fix( std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary); 26 30 } // namespace 27 31 -
src/InitTweak/GenInit.cc
r76d73fc rc532847 283 283 assert( stmts.size() <= 1 ); 284 284 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr; 285 286 } 287 288 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) { 289 assertf(objDecl, "genCtorDtor passed null objDecl"); 290 InitExpander_new srcParam(arg); 291 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl); 285 292 } 286 293 -
src/InitTweak/GenInit.h
r76d73fc rc532847 33 33 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 34 34 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr ); 35 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr); 35 36 36 37 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer -
src/InitTweak/InitTweak.cc
r76d73fc rc532847 498 498 } 499 499 500 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) { 501 assertf( func, "getParamThis: nullptr ftype" ); 502 auto & params = func->params; 503 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str()); 504 return params.front().strict_as<ast::ObjectDecl>(); 505 } 506 500 507 bool tryConstruct( DeclarationWithType * dwt ) { 501 508 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); … … 511 518 } 512 519 520 bool tryConstruct( const ast::DeclWithType * dwt ) { 521 auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt ); 522 if ( ! objDecl ) return false; 523 return (objDecl->init == nullptr || 524 ( objDecl->init != nullptr && objDecl->init->maybeConstructed )) 525 && ! objDecl->storage.is_extern 526 && isConstructable( objDecl->type ); 527 } 528 529 bool isConstructable( const ast::Type * type ) { 530 return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type ) 531 && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type ); 532 } 533 513 534 struct CallFinder_old { 514 535 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} … … 536 557 537 558 struct CallFinder_new final { 538 std::vector< ast::ptr< ast::Expr >> matches;559 std::vector< const ast::Expr * > matches; 539 560 const std::vector< std::string > names; 540 561 … … 558 579 } 559 580 560 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt ) {581 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) { 561 582 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 562 583 maybe_accept( stmt, finder ); … … 696 717 template <typename Predicate> 697 718 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) { 698 std::vector< ast::ptr< ast::Expr >> callExprs = collectCtorDtorCalls( stmt );719 std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt ); 699 720 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 700 721 } … … 939 960 } 940 961 962 // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards 963 // following passes may accidentally resolve this expression if returned as untyped... 964 ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) { 965 static ast::ptr<ast::FunctionDecl> assign = nullptr; 966 if (!assign) { 967 auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true); 968 assign = new ast::FunctionDecl({}, "?=?", {}, 969 { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))), 970 new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))}, 971 { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic); 972 } 973 if (dst->result.as<ast::ReferenceType>()) { 974 for (int depth = dst->result->referenceDepth(); depth > 0; depth--) { 975 dst = new ast::AddressExpr(dst); 976 } 977 } 978 else { 979 dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {})); 980 } 981 if (src->result.as<ast::ReferenceType>()) { 982 for (int depth = src->result->referenceDepth(); depth > 0; depth--) { 983 src = new ast::AddressExpr(src); 984 } 985 } 986 return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src}); 987 } 988 941 989 struct ConstExprChecker : public WithShortCircuiting { 942 990 // most expressions are not const expr -
src/InitTweak/InitTweak.h
r76d73fc rc532847 38 38 /// returns the first parameter of a constructor/destructor/assignment function 39 39 ObjectDecl * getParamThis( FunctionType * ftype ); 40 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func); 40 41 41 42 /// generate a bitwise assignment operation. 42 43 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ); 44 45 ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src); 43 46 44 47 /// transform Initializer into an argument list that can be passed to a call expression … … 48 51 /// True if the resolver should try to construct dwt 49 52 bool tryConstruct( DeclarationWithType * dwt ); 53 bool tryConstruct( const ast::DeclWithType * dwt ); 50 54 51 55 /// True if the type can have a user-defined constructor 52 56 bool isConstructable( Type * t ); 57 bool isConstructable( const ast::Type * t ); 53 58 54 59 /// True if the Initializer contains designations … … 79 84 /// get all Ctor/Dtor call expressions from a Statement 80 85 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 81 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt );86 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ); 82 87 83 88 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call -
src/InitTweak/module.mk
r76d73fc rc532847 23 23 InitTweak/GenInit.h \ 24 24 InitTweak/InitTweak.cc \ 25 InitTweak/InitTweak.h 25 InitTweak/InitTweak.h \ 26 InitTweak/FixInitNew.cpp 26 27 27 28 SRCDEMANGLE += \ -
src/ResolvExpr/Resolver.cc
r76d73fc rc532847 1105 1105 } 1106 1106 1107 /// Establish post-resolver invariants for expressions 1107 1108 } // anonymous namespace 1109 /// Establish post-resolver invariants for expressions 1108 1110 void finishExpr( 1109 1111 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, … … 1118 1120 StripCasts_new::strip( expr ); 1119 1121 } 1120 } // anonymous namespace1121 1122 1122 1123 1123 ast::ptr< ast::Expr > resolveInVoidContext( … … 1139 1139 } 1140 1140 1141 namespace { 1142 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1141 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1143 1142 /// context. 1144 1143 ast::ptr< ast::Expr > findVoidExpression( … … 1151 1150 return newExpr; 1152 1151 } 1152 1153 namespace { 1154 1153 1155 1154 1156 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the … … 1162 1164 CandidateRef choice = 1163 1165 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode ); 1164 finishExpr( choice->expr, choice->env, untyped->env );1166 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env ); 1165 1167 return std::move( choice->expr ); 1166 1168 } -
src/ResolvExpr/Resolver.h
r76d73fc rc532847 66 66 ast::ptr< ast::Expr > findSingleExpression( 67 67 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab ); 68 ast::ptr< ast::Expr > findVoidExpression( 69 const ast::Expr * untyped, const ast::SymbolTable & symtab); 68 70 /// Resolves a constructor init expression 69 71 ast::ptr< ast::Init > resolveCtorInit( -
src/SymTab/Autogen.cc
r76d73fc rc532847 233 233 } 234 234 235 // shallow copy the pointer list for return 236 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) { 237 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) { 238 return structInst->base->params; 239 } 240 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) { 241 return unionInst->base->params; 242 } 243 return {}; 244 } 245 235 246 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 236 247 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 244 255 ftype->parameters.push_back( dstParam ); 245 256 return ftype; 257 } 258 259 /// 260 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) { 261 std::vector<ast::ptr<ast::TypeDecl>> typeParams; 262 if (maybePolymorphic) typeParams = getGenericParams(paramType); 263 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall); 264 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc)); 246 265 } 247 266 -
src/SymTab/Autogen.h
r76d73fc rc532847 55 55 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 56 56 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 57 58 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true); 57 59 58 60 /// generate the type of a copy constructor for paramType. -
src/main.cc
r76d73fc rc532847 343 343 auto transUnit = convert( move( translationUnit ) ); 344 344 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 345 if ( exprp ) { 346 translationUnit = convert( move( transUnit ) ); 347 dump( translationUnit ); 348 return EXIT_SUCCESS; 349 } // if 350 351 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary())); 345 352 translationUnit = convert( move( transUnit ) ); 346 353 } else { 347 354 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 355 if ( exprp ) { 356 dump( translationUnit ); 357 return EXIT_SUCCESS; 358 } 359 360 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) ); 348 361 } 349 362 350 if ( exprp ) {351 dump( translationUnit );352 return EXIT_SUCCESS;353 } // if354 355 363 // fix ObjectDecl - replaces ConstructorInit nodes 356 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );357 364 if ( ctorinitp ) { 358 365 dump ( translationUnit );
Note: See TracChangeset
for help on using the changeset viewer.