- Timestamp:
- Mar 21, 2022, 1:44:06 PM (4 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- a76202d
- Parents:
- ef3c383 (diff), dbe2533 (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:
-
- 4 added
- 2 deleted
- 33 edited
-
AST/AssertAcyclic.cpp (deleted)
-
AST/AssertAcyclic.hpp (deleted)
-
AST/Convert.cpp (modified) (2 diffs)
-
AST/Decl.cpp (modified) (1 diff)
-
AST/Fwd.hpp (modified) (1 diff)
-
AST/GenericSubstitution.cpp (modified) (1 diff)
-
AST/TranslationUnit.hpp (modified) (2 diffs)
-
AST/TypeSubstitution.hpp (modified) (4 diffs)
-
AST/Util.cpp (added)
-
AST/Util.hpp (added)
-
AST/module.mk (modified) (2 diffs)
-
Common/CodeLocationTools.cpp (modified) (3 diffs)
-
Common/CodeLocationTools.hpp (modified) (2 diffs)
-
Common/Examine.cc (modified) (4 diffs)
-
Common/Examine.h (modified) (1 diff)
-
Concurrency/Keywords.cc (modified) (4 diffs)
-
Concurrency/KeywordsNew.cpp (modified) (14 diffs)
-
ControlStruct/ExceptTranslateNew.cpp (modified) (24 diffs)
-
InitTweak/FixGlobalInit.cc (modified) (2 diffs)
-
InitTweak/FixInitNew.cpp (modified) (16 diffs)
-
Parser/parser.yy (modified) (11 diffs)
-
ResolvExpr/CandidateFinder.cpp (modified) (24 diffs)
-
ResolvExpr/CandidateFinder.hpp (modified) (3 diffs)
-
ResolvExpr/CandidatePrinter.cpp (modified) (4 diffs)
-
ResolvExpr/ResolveTypeof.cc (modified) (7 diffs)
-
ResolvExpr/ResolveTypeof.h (modified) (2 diffs)
-
ResolvExpr/Resolver.cc (modified) (39 diffs)
-
ResolvExpr/Resolver.h (modified) (5 diffs)
-
ResolvExpr/Unify.cc (modified) (1 diff)
-
SymTab/Validate.cc (modified) (7 diffs)
-
SymTab/Validate.h (modified) (1 diff)
-
Tuples/TupleAssignment.cc (modified) (7 diffs)
-
Validate/FindSpecialDeclsNew.cpp (modified) (2 diffs)
-
Validate/ForallPointerDecay.cpp (added)
-
Validate/ForallPointerDecay.hpp (added)
-
Validate/module.mk (modified) (1 diff)
-
Virtual/Tables.cc (modified) (7 diffs)
-
Virtual/Tables.h (modified) (6 diffs)
-
main.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
ref3c383 rd672350 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 13:19:22202213 // Update Count : 4 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 15:01:00 2022 13 // Update Count : 42 14 14 // 15 15 … … 49 49 //================================================================================================ 50 50 namespace ast { 51 52 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 53 // allow us to use the same stratagy in the new ast. 54 // xxx - since convert back pass works, this concern seems to be unnecessary. 55 56 // these need to be accessed in new FixInit now 57 ast::ptr<ast::Type> sizeType = nullptr; 58 const ast::FunctionDecl * dereferenceOperator = nullptr; 59 const ast::StructDecl * dtorStruct = nullptr; 60 const ast::FunctionDecl * dtorStructDestroy = nullptr; 51 // These are the shared local information used by ConverterNewToOld and 52 // ConverterOldToNew to update the global information in the two versions. 53 54 static ast::ptr<ast::Type> sizeType = nullptr; 55 static const ast::FunctionDecl * dereferenceOperator = nullptr; 56 static const ast::StructDecl * dtorStruct = nullptr; 57 static const ast::FunctionDecl * dtorStructDestroy = nullptr; 61 58 62 59 } -
src/AST/Decl.cpp
ref3c383 rd672350 39 39 if ( uniqueId ) return; // ensure only set once 40 40 uniqueId = ++lastUniqueId; 41 idMap[ uniqueId ] = this; 41 // The extra readonly pointer is causing some reference counting issues. 42 // idMap[ uniqueId ] = this; 42 43 } 43 44 44 45 readonly<Decl> Decl::fromId( UniqueId id ) { 46 // Right now this map is always empty, so don't use it. 47 assert( false ); 45 48 IdMapType::const_iterator i = idMap.find( id ); 46 49 if ( i != idMap.end() ) return i->second; -
src/AST/Fwd.hpp
ref3c383 rd672350 141 141 142 142 class TranslationUnit; 143 // TODO: Get from the TranslationUnit: 144 extern ptr<Type> sizeType; 145 extern const FunctionDecl * dereferenceOperator; 146 extern const StructDecl * dtorStruct; 147 extern const FunctionDecl * dtorStructDestroy; 143 class TranslationGlobal; 148 144 149 145 } -
src/AST/GenericSubstitution.cpp
ref3c383 rd672350 45 45 visit_children = false; 46 46 const AggregateDecl * aggr = ty->aggr(); 47 sub = TypeSubstitution { aggr->params.begin(), aggr->params.end(), ty->params.begin() };47 sub = TypeSubstitution( aggr->params, ty->params ); 48 48 } 49 49 -
src/AST/TranslationUnit.hpp
ref3c383 rd672350 10 10 // Created On : Tue Jun 11 15:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Jun 11 15:42:00 201913 // Update Count : 012 // Last Modified On : Tue Mar 11 11:19:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 23 23 namespace ast { 24 24 25 class TranslationGlobal { 26 public: 27 std::map< UniqueId, Decl * > idMap; 28 29 ptr<Type> sizeType; 30 const FunctionDecl * dereference; 31 const StructDecl * dtorStruct; 32 const FunctionDecl * dtorDestroy; 33 }; 34 25 35 class TranslationUnit { 26 36 public: 27 37 std::list< ptr< Decl > > decls; 28 29 struct Global { 30 std::map< UniqueId, Decl * > idMap; 31 32 ptr<Type> sizeType; 33 const FunctionDecl * dereference; 34 const StructDecl * dtorStruct; 35 const FunctionDecl * dtorDestroy; 36 } global; 38 TranslationGlobal global; 37 39 }; 38 40 -
src/AST/TypeSubstitution.hpp
ref3c383 rd672350 37 37 public: 38 38 TypeSubstitution(); 39 template< typename FormalContainer, typename ActualContainer > 40 TypeSubstitution( FormalContainer formals, ActualContainer actuals ); 39 41 template< typename FormalIterator, typename ActualIterator > 40 42 TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ); … … 76 78 bool empty() const; 77 79 80 template< typename FormalContainer, typename ActualContainer > 81 void addAll( FormalContainer formals, ActualContainer actuals ); 78 82 template< typename FormalIterator, typename ActualIterator > 79 void add ( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );83 void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ); 80 84 81 85 /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr … … 112 116 }; 113 117 118 template< typename FormalContainer, typename ActualContainer > 119 TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) { 120 assert( formals.size() == actuals.size() ); 121 addAll( formals.begin(), formals.end(), actuals.begin() ); 122 } 123 124 template< typename FormalIterator, typename ActualIterator > 125 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { 126 addAll( formalBegin, formalEnd, actualBegin ); 127 } 128 129 template< typename FormalContainer, typename ActualContainer > 130 void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) { 131 assert( formals.size() == actuals.size() ); 132 addAll( formals.begin(), formals.end(), actuals.begin() ); 133 } 134 114 135 // this is the only place where type parameters outside a function formal may be substituted. 115 136 template< typename FormalIterator, typename ActualIterator > 116 void TypeSubstitution::add ( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {137 void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { 117 138 // FormalIterator points to a TypeDecl 118 139 // ActualIterator points to a Type … … 129 150 } // if 130 151 } else { 131 152 // Is this an error? 132 153 } // if 133 154 } // for 134 155 } 135 136 137 138 template< typename FormalIterator, typename ActualIterator >139 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {140 add( formalBegin, formalEnd, actualBegin );141 }142 143 156 144 157 } // namespace ast -
src/AST/module.mk
ref3c383 rd672350 16 16 17 17 SRC_AST = \ 18 AST/AssertAcyclic.cpp \19 AST/AssertAcyclic.hpp \20 18 AST/Attribute.cpp \ 21 19 AST/Attribute.hpp \ … … 64 62 AST/TypeSubstitution.cpp \ 65 63 AST/TypeSubstitution.hpp \ 64 AST/Util.cpp \ 65 AST/Util.hpp \ 66 66 AST/Visitor.hpp 67 67 -
src/Common/CodeLocationTools.cpp
ref3c383 rd672350 9 9 // Author : Andrew Beach 10 10 // Created On : Fri Dec 4 15:42:00 2020 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 1 09:14:39202213 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 14 15:14:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 239 239 }; 240 240 241 class LocalFillCore : public ast::WithGuards { 242 CodeLocation const * parent; 243 public: 244 LocalFillCore( CodeLocation const & location ) : parent( &location ) { 245 assert( location.isSet() ); 246 } 247 248 template<typename node_t> 249 auto previsit( node_t const * node ) 250 -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type { 251 if ( node->location.isSet() ) { 252 GuardValue( parent ) = &node->location; 253 return node; 254 } else { 255 node_t * mut = ast::mutate( node ); 256 mut->location = *parent; 257 return mut; 258 } 259 } 260 }; 261 241 262 } // namespace 242 263 … … 278 299 ast::Pass<FillCore>::run( unit ); 279 300 } 301 302 ast::Node const * localFillCodeLocations( 303 CodeLocation const & location , ast::Node const * node ) { 304 ast::Pass<LocalFillCore> visitor( location ); 305 return node->accept( visitor ); 306 } -
src/Common/CodeLocationTools.hpp
ref3c383 rd672350 10 10 // Created On : Fri Dec 4 15:35:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Dec 9 9:53:00 202013 // Update Count : 112 // Last Modified On : Mon Mar 14 15:14:00 2022 13 // Update Count : 2 14 14 // 15 15 16 16 #pragma once 17 17 18 struct CodeLocation; 18 19 namespace ast { 20 class Node; 19 21 class TranslationUnit; 20 22 } … … 28 30 // Assign a nearby code-location to any unset code locations in the forest. 29 31 void forceFillCodeLocations( ast::TranslationUnit & unit ); 32 33 // Fill in code-locations with a parent code location, 34 // using the provided CodeLocation as the base. 35 ast::Node const * 36 localFillCodeLocations( CodeLocation const &, ast::Node const * ); -
src/Common/Examine.cc
ref3c383 rd672350 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Examine. h --7 // Examine.cc -- Helpers for examining AST code. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Sept 2 14:02 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 8 12:15 202013 // Update Count : 012 // Last Modified On : Fri Dec 10 10:27 2021 13 // Update Count : 1 14 14 // 15 15 16 16 #include "Common/Examine.h" 17 17 18 #include "AST/Type.hpp" 18 19 #include "CodeGen/OperatorTable.h" 20 #include "InitTweak/InitTweak.h" 19 21 20 22 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) { … … 36 38 37 39 namespace { 40 41 // getTypeofThis but does some extra checks used in this module. 42 const ast::Type * getTypeofThisSolo( const ast::FunctionDecl * func ) { 43 if ( 1 != func->params.size() ) { 44 return nullptr; 45 } 46 auto ref = func->type->params.front().as<ast::ReferenceType>(); 47 return (ref) ? ref->base : nullptr; 48 } 49 50 } 51 52 const ast::DeclWithType * isMainFor( 53 const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ) { 54 if ( "main" != func->name ) return nullptr; 55 if ( 1 != func->params.size() ) return nullptr; 56 57 auto param = func->params.front(); 58 59 auto type = dynamic_cast<const ast::ReferenceType *>( param->get_type() ); 60 if ( !type ) return nullptr; 61 62 auto obj = type->base.as<ast::StructInstType>(); 63 if ( !obj ) return nullptr; 64 65 if ( kind != obj->base->kind ) return nullptr; 66 67 return param; 68 } 69 70 namespace { 38 71 Type * getDestructorParam( FunctionDecl * func ) { 39 72 if ( !CodeGen::isDestructor( func->name ) ) return nullptr; … … 48 81 return nullptr; 49 82 } 83 84 const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) { 85 if ( !CodeGen::isDestructor( func->name ) ) return nullptr; 86 //return InitTweak::getParamThis( func )->type; 87 return getTypeofThisSolo( func ); 88 } 89 50 90 } 51 91 … … 57 97 return false; 58 98 } 99 100 bool isDestructorFor( 101 const ast::FunctionDecl * func, const ast::StructDecl * type_decl ) { 102 if ( const ast::Type * type = getDestructorParam( func ) ) { 103 auto stype = dynamic_cast<const ast::StructInstType *>( type ); 104 return stype && stype->base.get() == type_decl; 105 } 106 return false; 107 } -
src/Common/Examine.h
ref3c383 rd672350 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Examine.h -- 7 // Examine.h -- Helpers for examining AST code. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Sept 2 13:57 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 8 12:08 202013 // Update Count : 012 // Last Modified On : Fri Dec 10 10:28 2021 13 // Update Count : 1 14 14 // 15 15 16 #include "AST/Decl.hpp" 16 17 #include "SynTree/Declaration.h" 17 18 18 19 /// Check if this is a main function for a type of an aggregate kind. 19 20 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ); 21 const ast::DeclWithType * isMainFor( 22 const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ); 20 23 // Returns a pointer to the parameter if true, nullptr otherwise. 21 24 22 25 /// Check if this function is a destructor for the given structure. 23 26 bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl ); 27 bool isDestructorFor( 28 const ast::FunctionDecl * func, const ast::StructDecl * type ); -
src/Concurrency/Keywords.cc
ref3c383 rd672350 422 422 ; 423 423 else if ( auto param = isMainFor( decl, cast_target ) ) { 424 // This should never trigger. 425 assert( vtable_decl ); 424 if ( !vtable_decl ) { 425 SemanticError( decl, context_error ); 426 } 426 427 // Should be safe because of isMainFor. 427 428 StructInstType * struct_type = static_cast<StructInstType *>( … … 1203 1204 //new TypeofType( noQualifiers, args.front()->clone() ) 1204 1205 new TypeofType( noQualifiers, new UntypedExpr( 1205 new NameExpr( "__get_ type" ),1206 new NameExpr( "__get_mutexstmt_lock_type" ), 1206 1207 { args.front()->clone() } 1207 1208 ) … … 1215 1216 map_range < std::list<Initializer*> > ( args, [](Expression * var ){ 1216 1217 return new SingleInit( new UntypedExpr( 1217 new NameExpr( "__get_ ptr" ),1218 new NameExpr( "__get_mutexstmt_lock_ptr" ), 1218 1219 { var } 1219 1220 ) ); … … 1226 1227 TypeExpr * lock_type_expr = new TypeExpr( 1227 1228 new TypeofType( noQualifiers, new UntypedExpr( 1228 new NameExpr( "__get_ type" ),1229 new NameExpr( "__get_mutexstmt_lock_type" ), 1229 1230 { args.front()->clone() } 1230 1231 ) -
src/Concurrency/KeywordsNew.cpp
ref3c383 rd672350 10 10 // Created On : Tue Nov 16 9:53:00 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Dec 1 11:24:00 202113 // Update Count : 112 // Last Modified On : Fri Mar 11 10:40:00 2022 13 // Update Count : 2 14 14 // 15 16 #include <iostream> 15 17 16 18 #include "Concurrency/Keywords.h" … … 18 20 #include "AST/Copy.hpp" 19 21 #include "AST/Decl.hpp" 22 #include "AST/Expr.hpp" 20 23 #include "AST/Pass.hpp" 21 24 #include "AST/Stmt.hpp" 25 #include "AST/DeclReplacer.hpp" 22 26 #include "AST/TranslationUnit.hpp" 23 27 #include "CodeGen/OperatorTable.h" 28 #include "Common/Examine.h" 24 29 #include "Common/utility.h" 30 #include "Common/UniqueName.h" 31 #include "ControlStruct/LabelGeneratorNew.hpp" 25 32 #include "InitTweak/InitTweak.h" 33 #include "Virtual/Tables.h" 26 34 27 35 namespace Concurrency { … … 29 37 namespace { 30 38 31 inline static bool isThread( const ast::DeclWithType * decl ) { 39 // -------------------------------------------------------------------------- 40 // Loose Helper Functions: 41 42 /// Detect threads constructed with the keyword thread. 43 bool isThread( const ast::DeclWithType * decl ) { 32 44 auto baseType = decl->get_type()->stripDeclarator(); 33 45 auto instType = dynamic_cast<const ast::StructInstType *>( baseType ); … … 36 48 } 37 49 50 /// Get the virtual type id if given a type name. 51 std::string typeIdType( std::string const & exception_name ) { 52 return exception_name.empty() ? std::string() 53 : Virtual::typeIdType( exception_name ); 54 } 55 56 /// Get the vtable type name if given a type name. 57 std::string vtableTypeName( std::string const & exception_name ) { 58 return exception_name.empty() ? std::string() 59 : Virtual::vtableTypeName( exception_name ); 60 } 61 62 static ast::Type * mutate_under_references( ast::ptr<ast::Type>& type ) { 63 ast::Type * mutType = type.get_and_mutate(); 64 for ( ast::ReferenceType * mutRef 65 ; (mutRef = dynamic_cast<ast::ReferenceType *>( mutType )) 66 ; mutType = mutRef->base.get_and_mutate() ); 67 return mutType; 68 } 69 70 // Describe that it adds the generic parameters and the uses of the generic 71 // parameters on the function and first "this" argument. 72 ast::FunctionDecl * fixupGenerics( 73 const ast::FunctionDecl * func, const ast::StructDecl * decl ) { 74 const CodeLocation & location = decl->location; 75 // We have to update both the declaration 76 auto mutFunc = ast::mutate( func ); 77 auto mutType = mutFunc->type.get_and_mutate(); 78 79 if ( decl->params.empty() ) { 80 return mutFunc; 81 } 82 83 assert( 0 != mutFunc->params.size() ); 84 assert( 0 != mutType->params.size() ); 85 86 // Add the "forall" clause information. 87 for ( const ast::ptr<ast::TypeDecl> & typeParam : decl->params ) { 88 auto typeDecl = ast::deepCopy( typeParam ); 89 mutFunc->type_params.push_back( typeDecl ); 90 mutType->forall.push_back( 91 new ast::TypeInstType( typeDecl->name, typeDecl ) ); 92 for ( auto & assertion : typeDecl->assertions ) { 93 mutFunc->assertions.push_back( assertion ); 94 mutType->assertions.emplace_back( 95 new ast::VariableExpr( location, assertion ) ); 96 } 97 typeDecl->assertions.clear(); 98 } 99 100 // Even chain_mutate is not powerful enough for this: 101 ast::ptr<ast::Type>& paramType = strict_dynamic_cast<ast::ObjectDecl *>( 102 mutFunc->params[0].get_and_mutate() )->type; 103 auto paramTypeInst = strict_dynamic_cast<ast::StructInstType *>( 104 mutate_under_references( paramType ) ); 105 auto typeParamInst = strict_dynamic_cast<ast::StructInstType *>( 106 mutate_under_references( mutType->params[0] ) ); 107 108 for ( const ast::ptr<ast::TypeDecl> & typeDecl : mutFunc->type_params ) { 109 paramTypeInst->params.push_back( 110 new ast::TypeExpr( location, 111 new ast::TypeInstType( typeDecl->name, typeDecl ) ) ); 112 typeParamInst->params.push_back( 113 new ast::TypeExpr( location, 114 new ast::TypeInstType( typeDecl->name, typeDecl ) ) ); 115 } 116 117 return mutFunc; 118 } 119 38 120 // -------------------------------------------------------------------------- 39 struct MutexKeyword final { 121 struct ConcurrentSueKeyword : public ast::WithDeclsToAdd<> { 122 ConcurrentSueKeyword( 123 std::string&& type_name, std::string&& field_name, 124 std::string&& getter_name, std::string&& context_error, 125 std::string&& exception_name, 126 bool needs_main, ast::AggregateDecl::Aggregate cast_target 127 ) : 128 type_name( type_name ), field_name( field_name ), 129 getter_name( getter_name ), context_error( context_error ), 130 exception_name( exception_name ), 131 typeid_name( typeIdType( exception_name ) ), 132 vtable_name( vtableTypeName( exception_name ) ), 133 needs_main( needs_main ), cast_target( cast_target ) 134 {} 135 136 virtual ~ConcurrentSueKeyword() {} 137 138 const ast::Decl * postvisit( const ast::StructDecl * decl ); 139 const ast::DeclWithType * postvisit( const ast::FunctionDecl * decl ); 140 const ast::Expr * postvisit( const ast::KeywordCastExpr * expr ); 141 142 struct StructAndField { 143 const ast::StructDecl * decl; 144 const ast::ObjectDecl * field; 145 }; 146 147 const ast::StructDecl * handleStruct( const ast::StructDecl * ); 148 void handleMain( const ast::FunctionDecl *, const ast::StructInstType * ); 149 void addTypeId( const ast::StructDecl * ); 150 void addVtableForward( const ast::StructDecl * ); 151 const ast::FunctionDecl * forwardDeclare( const ast::StructDecl * ); 152 StructAndField addField( const ast::StructDecl * ); 153 void addGetRoutines( const ast::ObjectDecl *, const ast::FunctionDecl * ); 154 void addLockUnlockRoutines( const ast::StructDecl * ); 155 156 private: 157 const std::string type_name; 158 const std::string field_name; 159 const std::string getter_name; 160 const std::string context_error; 161 const std::string exception_name; 162 const std::string typeid_name; 163 const std::string vtable_name; 164 const bool needs_main; 165 const ast::AggregateDecl::Aggregate cast_target; 166 167 const ast::StructDecl * type_decl = nullptr; 168 const ast::FunctionDecl * dtor_decl = nullptr; 169 const ast::StructDecl * except_decl = nullptr; 170 const ast::StructDecl * typeid_decl = nullptr; 171 const ast::StructDecl * vtable_decl = nullptr; 172 173 }; 174 175 // Handles thread type declarations: 176 // 177 // thread Mythread { struct MyThread { 178 // int data; int data; 179 // a_struct_t more_data; a_struct_t more_data; 180 // => thread$ __thrd_d; 181 // }; }; 182 // static inline thread$ * get_thread( MyThread * this ) { return &this->__thrd_d; } 183 // 184 struct ThreadKeyword final : public ConcurrentSueKeyword { 185 ThreadKeyword() : ConcurrentSueKeyword( 186 "thread$", 187 "__thrd", 188 "get_thread", 189 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 190 "ThreadCancelled", 191 true, 192 ast::AggregateDecl::Thread ) 193 {} 194 195 virtual ~ThreadKeyword() {} 196 }; 197 198 // Handles coroutine type declarations: 199 // 200 // coroutine MyCoroutine { struct MyCoroutine { 201 // int data; int data; 202 // a_struct_t more_data; a_struct_t more_data; 203 // => coroutine$ __cor_d; 204 // }; }; 205 // static inline coroutine$ * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; } 206 // 207 struct CoroutineKeyword final : public ConcurrentSueKeyword { 208 CoroutineKeyword() : ConcurrentSueKeyword( 209 "coroutine$", 210 "__cor", 211 "get_coroutine", 212 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n", 213 "CoroutineCancelled", 214 true, 215 ast::AggregateDecl::Coroutine ) 216 {} 217 218 virtual ~CoroutineKeyword() {} 219 }; 220 221 // Handles monitor type declarations: 222 // 223 // monitor MyMonitor { struct MyMonitor { 224 // int data; int data; 225 // a_struct_t more_data; a_struct_t more_data; 226 // => monitor$ __mon_d; 227 // }; }; 228 // static inline monitor$ * get_coroutine( MyMonitor * this ) { 229 // return &this->__cor_d; 230 // } 231 // void lock(MyMonitor & this) { 232 // lock(get_monitor(this)); 233 // } 234 // void unlock(MyMonitor & this) { 235 // unlock(get_monitor(this)); 236 // } 237 // 238 struct MonitorKeyword final : public ConcurrentSueKeyword { 239 MonitorKeyword() : ConcurrentSueKeyword( 240 "monitor$", 241 "__mon", 242 "get_monitor", 243 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n", 244 "", 245 false, 246 ast::AggregateDecl::Monitor ) 247 {} 248 249 virtual ~MonitorKeyword() {} 250 }; 251 252 // Handles generator type declarations: 253 // 254 // generator MyGenerator { struct MyGenerator { 255 // int data; int data; 256 // a_struct_t more_data; a_struct_t more_data; 257 // => int __generator_state; 258 // }; }; 259 // 260 struct GeneratorKeyword final : public ConcurrentSueKeyword { 261 GeneratorKeyword() : ConcurrentSueKeyword( 262 "generator$", 263 "__generator_state", 264 "get_generator", 265 "Unable to find builtin type generator$\n", 266 "", 267 true, 268 ast::AggregateDecl::Generator ) 269 {} 270 271 virtual ~GeneratorKeyword() {} 272 }; 273 274 const ast::Decl * ConcurrentSueKeyword::postvisit( 275 const ast::StructDecl * decl ) { 276 if ( !decl->body ) { 277 return decl; 278 } else if ( cast_target == decl->kind ) { 279 return handleStruct( decl ); 280 } else if ( type_name == decl->name ) { 281 assert( !type_decl ); 282 type_decl = decl; 283 } else if ( exception_name == decl->name ) { 284 assert( !except_decl ); 285 except_decl = decl; 286 } else if ( typeid_name == decl->name ) { 287 assert( !typeid_decl ); 288 typeid_decl = decl; 289 } else if ( vtable_name == decl->name ) { 290 assert( !vtable_decl ); 291 vtable_decl = decl; 292 } 293 return decl; 294 } 295 296 // Try to get the full definition, but raise an error on conflicts. 297 const ast::FunctionDecl * getDefinition( 298 const ast::FunctionDecl * old_decl, 299 const ast::FunctionDecl * new_decl ) { 300 if ( !new_decl->stmts ) { 301 return old_decl; 302 } else if ( !old_decl->stmts ) { 303 return new_decl; 304 } else { 305 assert( !old_decl->stmts || !new_decl->stmts ); 306 return nullptr; 307 } 308 } 309 310 const ast::DeclWithType * ConcurrentSueKeyword::postvisit( 311 const ast::FunctionDecl * decl ) { 312 if ( type_decl && isDestructorFor( decl, type_decl ) ) { 313 // Check for forward declarations, try to get the full definition. 314 dtor_decl = (dtor_decl) ? getDefinition( dtor_decl, decl ) : decl; 315 } else if ( !vtable_name.empty() && decl->has_body() ) { 316 if (const ast::DeclWithType * param = isMainFor( decl, cast_target )) { 317 if ( !vtable_decl ) { 318 SemanticError( decl, context_error ); 319 } 320 // Should be safe because of isMainFor. 321 const ast::StructInstType * struct_type = 322 static_cast<const ast::StructInstType *>( 323 static_cast<const ast::ReferenceType *>( 324 param->get_type() )->base.get() ); 325 326 handleMain( decl, struct_type ); 327 } 328 } 329 return decl; 330 } 331 332 const ast::Expr * ConcurrentSueKeyword::postvisit( 333 const ast::KeywordCastExpr * expr ) { 334 if ( cast_target == expr->target ) { 335 // Convert `(thread &)ex` to `(thread$ &)*get_thread(ex)`, etc. 336 if ( !type_decl || !dtor_decl ) { 337 SemanticError( expr, context_error ); 338 } 339 assert( nullptr == expr->result ); 340 auto cast = ast::mutate( expr ); 341 cast->result = new ast::ReferenceType( new ast::StructInstType( type_decl ) ); 342 cast->concrete_target.field = field_name; 343 cast->concrete_target.getter = getter_name; 344 return cast; 345 } 346 return expr; 347 } 348 349 const ast::StructDecl * ConcurrentSueKeyword::handleStruct( 350 const ast::StructDecl * decl ) { 351 assert( decl->body ); 352 353 if ( !type_decl || !dtor_decl ) { 354 SemanticError( decl, context_error ); 355 } 356 357 if ( !exception_name.empty() ) { 358 if( !typeid_decl || !vtable_decl ) { 359 SemanticError( decl, context_error ); 360 } 361 addTypeId( decl ); 362 addVtableForward( decl ); 363 } 364 365 const ast::FunctionDecl * func = forwardDeclare( decl ); 366 StructAndField addFieldRet = addField( decl ); 367 decl = addFieldRet.decl; 368 const ast::ObjectDecl * field = addFieldRet.field; 369 370 addGetRoutines( field, func ); 371 // Add routines to monitors for use by mutex stmt. 372 if ( ast::AggregateDecl::Monitor == cast_target ) { 373 addLockUnlockRoutines( decl ); 374 } 375 376 return decl; 377 } 378 379 void ConcurrentSueKeyword::handleMain( 380 const ast::FunctionDecl * decl, const ast::StructInstType * type ) { 381 assert( vtable_decl ); 382 assert( except_decl ); 383 384 const CodeLocation & location = decl->location; 385 386 std::vector<ast::ptr<ast::Expr>> poly_args = { 387 new ast::TypeExpr( location, type ), 388 }; 389 ast::ObjectDecl * vtable_object = Virtual::makeVtableInstance( 390 location, 391 "_default_vtable_object_declaration", 392 new ast::StructInstType( vtable_decl, copy( poly_args ) ), 393 type, 394 nullptr 395 ); 396 declsToAddAfter.push_back( vtable_object ); 397 declsToAddAfter.push_back( 398 new ast::ObjectDecl( 399 location, 400 Virtual::concurrentDefaultVTableName(), 401 new ast::ReferenceType( vtable_object->type, ast::CV::Const ), 402 new ast::SingleInit( location, 403 new ast::VariableExpr( location, vtable_object ) ), 404 ast::Storage::Classes(), 405 ast::Linkage::Cforall 406 ) 407 ); 408 declsToAddAfter.push_back( Virtual::makeGetExceptionFunction( 409 location, 410 vtable_object, 411 new ast::StructInstType( except_decl, copy( poly_args ) ) 412 ) ); 413 } 414 415 void ConcurrentSueKeyword::addTypeId( const ast::StructDecl * decl ) { 416 assert( typeid_decl ); 417 const CodeLocation & location = decl->location; 418 419 ast::StructInstType * typeid_type = 420 new ast::StructInstType( typeid_decl, ast::CV::Const ); 421 typeid_type->params.push_back( 422 new ast::TypeExpr( location, new ast::StructInstType( decl ) ) ); 423 declsToAddBefore.push_back( 424 Virtual::makeTypeIdInstance( location, typeid_type ) ); 425 // If the typeid_type is going to be kept, the other reference will have 426 // been made by now, but we also get to avoid extra mutates. 427 ast::ptr<ast::StructInstType> typeid_cleanup = typeid_type; 428 } 429 430 void ConcurrentSueKeyword::addVtableForward( const ast::StructDecl * decl ) { 431 assert( vtable_decl ); 432 const CodeLocation& location = decl->location; 433 434 std::vector<ast::ptr<ast::Expr>> poly_args = { 435 new ast::TypeExpr( location, new ast::StructInstType( decl ) ), 436 }; 437 declsToAddBefore.push_back( Virtual::makeGetExceptionForward( 438 location, 439 new ast::StructInstType( vtable_decl, copy( poly_args ) ), 440 new ast::StructInstType( except_decl, copy( poly_args ) ) 441 ) ); 442 ast::ObjectDecl * vtable_object = Virtual::makeVtableForward( 443 location, 444 "_default_vtable_object_declaration", 445 new ast::StructInstType( vtable_decl, std::move( poly_args ) ) 446 ); 447 declsToAddBefore.push_back( vtable_object ); 448 declsToAddBefore.push_back( 449 new ast::ObjectDecl( 450 location, 451 Virtual::concurrentDefaultVTableName(), 452 new ast::ReferenceType( vtable_object->type, ast::CV::Const ), 453 nullptr, 454 ast::Storage::Extern, 455 ast::Linkage::Cforall 456 ) 457 ); 458 } 459 460 const ast::FunctionDecl * ConcurrentSueKeyword::forwardDeclare( 461 const ast::StructDecl * decl ) { 462 const CodeLocation & location = decl->location; 463 464 ast::StructDecl * forward = ast::deepCopy( decl ); 465 { 466 // If removing members makes ref-count go to zero, do not free. 467 ast::ptr<ast::StructDecl> forward_ptr = forward; 468 forward->body = false; 469 forward->members.clear(); 470 forward_ptr.release(); 471 } 472 473 ast::ObjectDecl * this_decl = new ast::ObjectDecl( 474 location, 475 "this", 476 new ast::ReferenceType( new ast::StructInstType( decl ) ), 477 nullptr, 478 ast::Storage::Classes(), 479 ast::Linkage::Cforall 480 ); 481 482 ast::ObjectDecl * ret_decl = new ast::ObjectDecl( 483 location, 484 "ret", 485 new ast::PointerType( new ast::StructInstType( type_decl ) ), 486 nullptr, 487 ast::Storage::Classes(), 488 ast::Linkage::Cforall 489 ); 490 491 ast::FunctionDecl * get_decl = new ast::FunctionDecl( 492 location, 493 getter_name, 494 {}, // forall 495 { this_decl }, // params 496 { ret_decl }, // returns 497 nullptr, // stmts 498 ast::Storage::Static, 499 ast::Linkage::Cforall, 500 { new ast::Attribute( "const" ) }, 501 ast::Function::Inline 502 ); 503 get_decl = fixupGenerics( get_decl, decl ); 504 505 ast::FunctionDecl * main_decl = nullptr; 506 if ( needs_main ) { 507 // `this_decl` is copied here because the original was used above. 508 main_decl = new ast::FunctionDecl( 509 location, 510 "main", 511 {}, 512 { ast::deepCopy( this_decl ) }, 513 {}, 514 nullptr, 515 ast::Storage::Classes(), 516 ast::Linkage::Cforall 517 ); 518 main_decl = fixupGenerics( main_decl, decl ); 519 } 520 521 declsToAddBefore.push_back( forward ); 522 if ( needs_main ) declsToAddBefore.push_back( main_decl ); 523 declsToAddBefore.push_back( get_decl ); 524 525 return get_decl; 526 } 527 528 ConcurrentSueKeyword::StructAndField ConcurrentSueKeyword::addField( 529 const ast::StructDecl * decl ) { 530 const CodeLocation & location = decl->location; 531 532 ast::ObjectDecl * field = new ast::ObjectDecl( 533 location, 534 field_name, 535 new ast::StructInstType( type_decl ), 536 nullptr, 537 ast::Storage::Classes(), 538 ast::Linkage::Cforall 539 ); 540 541 auto mutDecl = ast::mutate( decl ); 542 mutDecl->members.push_back( field ); 543 544 return {mutDecl, field}; 545 } 546 547 void ConcurrentSueKeyword::addGetRoutines( 548 const ast::ObjectDecl * field, const ast::FunctionDecl * forward ) { 549 // Say it is generated at the "same" places as the forward declaration. 550 const CodeLocation & location = forward->location; 551 552 const ast::DeclWithType * param = forward->params.front(); 553 ast::Stmt * stmt = new ast::ReturnStmt( location, 554 new ast::AddressExpr( location, 555 new ast::MemberExpr( location, 556 field, 557 new ast::CastExpr( location, 558 new ast::VariableExpr( location, param ), 559 ast::deepCopy( param->get_type()->stripReferences() ), 560 ast::ExplicitCast 561 ) 562 ) 563 ) 564 ); 565 566 ast::FunctionDecl * decl = ast::deepCopy( forward ); 567 decl->stmts = new ast::CompoundStmt( location, { stmt } ); 568 declsToAddAfter.push_back( decl ); 569 } 570 571 void ConcurrentSueKeyword::addLockUnlockRoutines( 572 const ast::StructDecl * decl ) { 573 // This should only be used on monitors. 574 assert( ast::AggregateDecl::Monitor == cast_target ); 575 576 const CodeLocation & location = decl->location; 577 578 // The parameter for both routines. 579 ast::ObjectDecl * this_decl = new ast::ObjectDecl( 580 location, 581 "this", 582 new ast::ReferenceType( new ast::StructInstType( decl ) ), 583 nullptr, 584 ast::Storage::Classes(), 585 ast::Linkage::Cforall 586 ); 587 588 ast::FunctionDecl * lock_decl = new ast::FunctionDecl( 589 location, 590 "lock", 591 { /* forall */ }, 592 { 593 // Copy the declaration of this. 594 ast::deepCopy( this_decl ), 595 }, 596 { /* returns */ }, 597 nullptr, 598 ast::Storage::Static, 599 ast::Linkage::Cforall, 600 { /* attributes */ }, 601 ast::Function::Inline 602 ); 603 lock_decl = fixupGenerics( lock_decl, decl ); 604 605 lock_decl->stmts = new ast::CompoundStmt( location, { 606 new ast::ExprStmt( location, 607 new ast::UntypedExpr( location, 608 new ast::NameExpr( location, "lock" ), 609 { 610 new ast::UntypedExpr( location, 611 new ast::NameExpr( location, "get_monitor" ), 612 { new ast::VariableExpr( location, 613 InitTweak::getParamThis( lock_decl ) ) } 614 ) 615 } 616 ) 617 ) 618 } ); 619 620 ast::FunctionDecl * unlock_decl = new ast::FunctionDecl( 621 location, 622 "unlock", 623 { /* forall */ }, 624 { 625 // Last use, consume the declaration of this. 626 this_decl, 627 }, 628 { /* returns */ }, 629 nullptr, 630 ast::Storage::Static, 631 ast::Linkage::Cforall, 632 { /* attributes */ }, 633 ast::Function::Inline 634 ); 635 unlock_decl = fixupGenerics( unlock_decl, decl ); 636 637 unlock_decl->stmts = new ast::CompoundStmt( location, { 638 new ast::ExprStmt( location, 639 new ast::UntypedExpr( location, 640 new ast::NameExpr( location, "unlock" ), 641 { 642 new ast::UntypedExpr( location, 643 new ast::NameExpr( location, "get_monitor" ), 644 { new ast::VariableExpr( location, 645 InitTweak::getParamThis( unlock_decl ) ) } 646 ) 647 } 648 ) 649 ) 650 } ); 651 652 declsToAddAfter.push_back( lock_decl ); 653 declsToAddAfter.push_back( unlock_decl ); 654 } 655 656 657 // -------------------------------------------------------------------------- 658 struct SuspendKeyword final : 659 public ast::WithStmtsToAdd<>, public ast::WithGuards { 660 SuspendKeyword() = default; 661 virtual ~SuspendKeyword() = default; 662 663 void previsit( const ast::FunctionDecl * ); 664 const ast::DeclWithType * postvisit( const ast::FunctionDecl * ); 665 const ast::Stmt * postvisit( const ast::SuspendStmt * ); 666 667 private: 668 bool is_real_suspend( const ast::FunctionDecl * ); 669 670 const ast::Stmt * make_generator_suspend( const ast::SuspendStmt * ); 671 const ast::Stmt * make_coroutine_suspend( const ast::SuspendStmt * ); 672 673 struct LabelPair { 674 ast::Label obj; 675 int idx; 676 }; 677 678 LabelPair make_label(const ast::Stmt * stmt ) { 679 labels.push_back( ControlStruct::newLabel( "generator", stmt ) ); 680 return { labels.back(), int(labels.size()) }; 681 } 682 683 const ast::DeclWithType * in_generator = nullptr; 684 const ast::FunctionDecl * decl_suspend = nullptr; 685 std::vector<ast::Label> labels; 686 }; 687 688 void SuspendKeyword::previsit( const ast::FunctionDecl * decl ) { 689 GuardValue( in_generator ); in_generator = nullptr; 690 691 // If it is the real suspend, grab it if we don't have one already. 692 if ( is_real_suspend( decl ) ) { 693 decl_suspend = decl_suspend ? decl_suspend : decl; 694 return; 695 } 696 697 // Otherwise check if this is a generator main and, if so, handle it. 698 auto param = isMainFor( decl, ast::AggregateDecl::Generator ); 699 if ( !param ) return; 700 701 if ( 0 != decl->returns.size() ) { 702 SemanticError( decl->location, "Generator main must return void" ); 703 } 704 705 in_generator = param; 706 GuardValue( labels ); labels.clear(); 707 } 708 709 const ast::DeclWithType * SuspendKeyword::postvisit( 710 const ast::FunctionDecl * decl ) { 711 // Only modify a full definition of a generator with states. 712 if ( !decl->stmts || !in_generator || labels.empty() ) return decl; 713 714 const CodeLocation & location = decl->location; 715 716 // Create a new function body: 717 // static void * __generator_labels[] = {&&s0, &&s1, ...}; 718 // void * __generator_label = __generator_labels[GEN.__generator_state]; 719 // goto * __generator_label; 720 // s0: ; 721 // OLD_BODY 722 723 // This is the null statement inserted right before the body. 724 ast::NullStmt * noop = new ast::NullStmt( location ); 725 noop->labels.push_back( ControlStruct::newLabel( "generator", noop ) ); 726 const ast::Label & first_label = noop->labels.back(); 727 728 // Add each label to the init, starting with the first label. 729 std::vector<ast::ptr<ast::Init>> inits = { 730 new ast::SingleInit( location, 731 new ast::LabelAddressExpr( location, copy( first_label ) ) ) }; 732 // Then go through all the stored labels, and clear the store. 733 for ( auto && label : labels ) { 734 inits.push_back( new ast::SingleInit( label.location, 735 new ast::LabelAddressExpr( label.location, std::move( label ) 736 ) ) ); 737 } 738 labels.clear(); 739 // Then construct the initializer itself. 740 auto init = new ast::ListInit( location, std::move( inits ) ); 741 742 ast::ObjectDecl * generatorLabels = new ast::ObjectDecl( 743 location, 744 "__generator_labels", 745 new ast::ArrayType( 746 new ast::PointerType( new ast::VoidType() ), 747 nullptr, 748 ast::FixedLen, 749 ast::DynamicDim 750 ), 751 init, 752 ast::Storage::Classes(), 753 ast::Linkage::AutoGen 754 ); 755 756 ast::ObjectDecl * generatorLabel = new ast::ObjectDecl( 757 location, 758 "__generator_label", 759 new ast::PointerType( new ast::VoidType() ), 760 new ast::SingleInit( location, 761 new ast::UntypedExpr( location, 762 new ast::NameExpr( location, "?[?]" ), 763 { 764 // TODO: Could be a variable expr. 765 new ast::NameExpr( location, "__generator_labels" ), 766 new ast::UntypedMemberExpr( location, 767 new ast::NameExpr( location, "__generator_state" ), 768 new ast::VariableExpr( location, in_generator ) 769 ) 770 } 771 ) 772 ), 773 ast::Storage::Classes(), 774 ast::Linkage::AutoGen 775 ); 776 777 ast::BranchStmt * theGoTo = new ast::BranchStmt( 778 location, new ast::VariableExpr( location, generatorLabel ) 779 ); 780 781 // The noop goes here in order. 782 783 ast::CompoundStmt * body = new ast::CompoundStmt( location, { 784 { new ast::DeclStmt( location, generatorLabels ) }, 785 { new ast::DeclStmt( location, generatorLabel ) }, 786 { theGoTo }, 787 { noop }, 788 { decl->stmts }, 789 } ); 790 791 auto mutDecl = ast::mutate( decl ); 792 mutDecl->stmts = body; 793 return mutDecl; 794 } 795 796 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 797 switch ( stmt->type ) { 798 case ast::SuspendStmt::None: 799 // Use the context to determain the implicit target. 800 if ( in_generator ) { 801 return make_generator_suspend( stmt ); 802 } else { 803 return make_coroutine_suspend( stmt ); 804 } 805 case ast::SuspendStmt::Coroutine: 806 return make_coroutine_suspend( stmt ); 807 case ast::SuspendStmt::Generator: 808 // Generator suspends must be directly in a generator. 809 if ( !in_generator ) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type." ); 810 return make_generator_suspend( stmt ); 811 } 812 assert( false ); 813 return stmt; 814 } 815 816 /// Find the real/official suspend declaration. 817 bool SuspendKeyword::is_real_suspend( const ast::FunctionDecl * decl ) { 818 return ( !decl->linkage.is_mangled 819 && 0 == decl->params.size() 820 && 0 == decl->returns.size() 821 && "__cfactx_suspend" == decl->name ); 822 } 823 824 const ast::Stmt * SuspendKeyword::make_generator_suspend( 825 const ast::SuspendStmt * stmt ) { 826 assert( in_generator ); 827 // Target code is: 828 // GEN.__generator_state = X; 829 // THEN 830 // return; 831 // __gen_X:; 832 833 const CodeLocation & location = stmt->location; 834 835 LabelPair label = make_label( stmt ); 836 837 // This is the context saving statement. 838 stmtsToAddBefore.push_back( new ast::ExprStmt( location, 839 new ast::UntypedExpr( location, 840 new ast::NameExpr( location, "?=?" ), 841 { 842 new ast::UntypedMemberExpr( location, 843 new ast::NameExpr( location, "__generator_state" ), 844 new ast::VariableExpr( location, in_generator ) 845 ), 846 ast::ConstantExpr::from_int( location, label.idx ), 847 } 848 ) 849 ) ); 850 851 // The THEN component is conditional (return is not). 852 if ( stmt->then ) { 853 stmtsToAddBefore.push_back( stmt->then.get() ); 854 } 855 stmtsToAddBefore.push_back( new ast::ReturnStmt( location, nullptr ) ); 856 857 // The null statement replaces the old suspend statement. 858 return new ast::NullStmt( location, { label.obj } ); 859 } 860 861 const ast::Stmt * SuspendKeyword::make_coroutine_suspend( 862 const ast::SuspendStmt * stmt ) { 863 // The only thing we need from the old statement is the location. 864 const CodeLocation & location = stmt->location; 865 866 if ( !decl_suspend ) { 867 SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n" ); 868 } 869 if ( stmt->then ) { 870 SemanticError( location, "Compound statement following coroutines is not implemented." ); 871 } 872 873 return new ast::ExprStmt( location, 874 new ast::UntypedExpr( location, 875 ast::VariableExpr::functionPointer( location, decl_suspend ) ) 876 ); 877 } 878 879 // -------------------------------------------------------------------------- 880 struct MutexKeyword final : public ast::WithDeclsToAdd<> { 40 881 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl ); 41 882 void postvisit( const ast::StructDecl * decl ); … … 50 891 ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args ); 51 892 ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args ); 52 893 ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param); 894 ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ); 53 895 private: 54 896 const ast::StructDecl * monitor_decl = nullptr; … … 59 901 60 902 static ast::ptr<ast::Type> generic_func; 903 904 UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr"); 61 905 }; 62 906 … … 160 1004 161 1005 const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) { 1006 if ( !lock_guard_decl ) { 1007 SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" ); 1008 } 162 1009 ast::CompoundStmt * body = 163 1010 new ast::CompoundStmt( stmt->location, { stmt->stmt } ); 164 addStatements( body, stmt->mutexObjs );165 return body;1011 1012 return addStatements( body, stmt->mutexObjs );; 166 1013 } 167 1014 … … 251 1098 { 252 1099 new ast::SingleInit( location, 253 new ast::AddressExpr( 1100 new ast::AddressExpr( location, 254 1101 new ast::VariableExpr( location, monitor ) ) ), 255 1102 new ast::SingleInit( location, … … 358 1205 } 359 1206 1207 // generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it 1208 // used to undo the type erasure done by storing all the lock pointers as void 1209 ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) { 1210 return new ast::ExprStmt( location, 1211 new ast::UntypedExpr( location, 1212 new ast::NameExpr( location, fnName ), { 1213 ast::UntypedExpr::createDeref( 1214 location, 1215 new ast::CastExpr( location, 1216 param, 1217 new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr( 1218 expr->location, 1219 new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ), 1220 { expr } 1221 ) ) ), 1222 ast::GeneratedFlag::ExplicitCast 1223 ) 1224 ) 1225 } 1226 ) 1227 ); 1228 } 1229 1230 ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) { 1231 ast::IfStmt * outerLockIf = nullptr; 1232 ast::IfStmt * lastLockIf = nullptr; 1233 1234 //adds an if/elif clause for each lock to assign type from void ptr based on ptr address 1235 for ( long unsigned int i = 0; i < args.size(); i++ ) { 1236 1237 ast::UntypedExpr * ifCond = new ast::UntypedExpr( location, 1238 new ast::NameExpr( location, "?==?" ), { 1239 ast::deepCopy( thisParam ), 1240 new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() )) 1241 } 1242 ); 1243 1244 ast::IfStmt * currLockIf = new ast::IfStmt( 1245 location, 1246 ifCond, 1247 genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) ) 1248 ); 1249 1250 if ( i == 0 ) { 1251 outerLockIf = currLockIf; 1252 } else { 1253 // add ifstmt to else of previous stmt 1254 lastLockIf->else_ = currLockIf; 1255 } 1256 1257 lastLockIf = currLockIf; 1258 } 1259 return outerLockIf; 1260 } 1261 360 1262 ast::CompoundStmt * MutexKeyword::addStatements( 361 1263 const ast::CompoundStmt * body, 362 1264 const std::vector<ast::ptr<ast::Expr>> & args ) { 363 ast::CompoundStmt * mutBody = ast::mutate( body );364 1265 365 1266 // Code is generated near the beginning of the compound statement. 366 const CodeLocation & location = mutBody->location; 1267 const CodeLocation & location = body->location; 1268 1269 // final body to return 1270 ast::CompoundStmt * newBody = new ast::CompoundStmt( location ); 1271 1272 // std::string lockFnName = mutex_func_namer.newName(); 1273 // std::string unlockFnName = mutex_func_namer.newName(); 367 1274 368 1275 // Make pointer to the monitors. … … 372 1279 new ast::ArrayType( 373 1280 new ast::PointerType( 374 new ast::TypeofType( 375 new ast::UntypedExpr( 376 location, 377 new ast::NameExpr( location, "__get_type" ), 378 { args.front() } 379 ) 380 ) 1281 new ast::VoidType() 381 1282 ), 382 1283 ast::ConstantExpr::from_ulong( location, args.size() ), … … 392 1293 new ast::UntypedExpr( 393 1294 expr->location, 394 new ast::NameExpr( expr->location, "__get_ ptr" ),1295 new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ), 395 1296 { expr } 396 1297 ) … … 405 1306 ast::StructInstType * lock_guard_struct = 406 1307 new ast::StructInstType( lock_guard_decl ); 407 ast::TypeExpr * lock_type_expr = new ast::TypeExpr( 408 location, 409 new ast::TypeofType( 410 new ast::UntypedExpr( 411 location, 412 new ast::NameExpr( location, "__get_type" ), 413 { args.front() } 414 ) 415 ) 416 ); 417 418 lock_guard_struct->params.push_back( lock_type_expr ); 419 420 // In reverse order: 1308 1309 // use try stmts to lock and finally to unlock 1310 ast::TryStmt * outerTry = nullptr; 1311 ast::TryStmt * currentTry; 1312 ast::CompoundStmt * lastBody = nullptr; 1313 1314 // adds a nested try stmt for each lock we are locking 1315 for ( long unsigned int i = 0; i < args.size(); i++ ) { 1316 ast::UntypedExpr * innerAccess = new ast::UntypedExpr( 1317 location, 1318 new ast::NameExpr( location,"?[?]" ), { 1319 new ast::NameExpr( location, "__monitors" ), 1320 ast::ConstantExpr::from_int( location, i ) 1321 } 1322 ); 1323 1324 // make the try body 1325 ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location ); 1326 ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess ); 1327 currTryBody->push_back( lockCall ); 1328 1329 // make the finally stmt 1330 ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location ); 1331 ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess ); 1332 currFinallyBody->push_back( unlockCall ); 1333 1334 // construct the current try 1335 currentTry = new ast::TryStmt( 1336 location, 1337 currTryBody, 1338 {}, 1339 new ast::FinallyStmt( location, currFinallyBody ) 1340 ); 1341 if ( i == 0 ) outerTry = currentTry; 1342 else { 1343 // pushback try into the body of the outer try 1344 lastBody->push_back( currentTry ); 1345 } 1346 lastBody = currTryBody; 1347 } 1348 1349 // push body into innermost try body 1350 if ( lastBody != nullptr ) { 1351 lastBody->push_back( body ); 1352 newBody->push_front( outerTry ); 1353 } 1354 421 1355 // monitor_guard_t __guard = { __monitors, # }; 422 mutBody->push_front(1356 newBody->push_front( 423 1357 new ast::DeclStmt( 424 1358 location, … … 447 1381 448 1382 // monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) }; 449 mutBody->push_front( new ast::DeclStmt( location, monitors ) ); 450 451 return mutBody; 1383 newBody->push_front( new ast::DeclStmt( location, monitors ) ); 1384 1385 // // The parameter for both __lock_curr/__unlock_curr routines. 1386 // ast::ObjectDecl * this_decl = new ast::ObjectDecl( 1387 // location, 1388 // "this", 1389 // new ast::PointerType( new ast::VoidType() ), 1390 // nullptr, 1391 // {}, 1392 // ast::Linkage::Cforall 1393 // ); 1394 1395 // ast::FunctionDecl * lock_decl = new ast::FunctionDecl( 1396 // location, 1397 // lockFnName, 1398 // { /* forall */ }, 1399 // { 1400 // // Copy the declaration of this. 1401 // this_decl, 1402 // }, 1403 // { /* returns */ }, 1404 // nullptr, 1405 // 0, 1406 // ast::Linkage::Cforall, 1407 // { /* attributes */ }, 1408 // ast::Function::Inline 1409 // ); 1410 1411 // ast::FunctionDecl * unlock_decl = new ast::FunctionDecl( 1412 // location, 1413 // unlockFnName, 1414 // { /* forall */ }, 1415 // { 1416 // // Copy the declaration of this. 1417 // ast::deepCopy( this_decl ), 1418 // }, 1419 // { /* returns */ }, 1420 // nullptr, 1421 // 0, 1422 // ast::Linkage::Cforall, 1423 // { /* attributes */ }, 1424 // ast::Function::Inline 1425 // ); 1426 1427 // ast::IfStmt * outerLockIf = nullptr; 1428 // ast::IfStmt * outerUnlockIf = nullptr; 1429 // ast::IfStmt * lastLockIf = nullptr; 1430 // ast::IfStmt * lastUnlockIf = nullptr; 1431 1432 // //adds an if/elif clause for each lock to assign type from void ptr based on ptr address 1433 // for ( long unsigned int i = 0; i < args.size(); i++ ) { 1434 // ast::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) ); 1435 // ast::UntypedExpr * ifCond = new ast::UntypedExpr( location, 1436 // new ast::NameExpr( location, "?==?" ), { 1437 // thisParam, 1438 // new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() )) 1439 // } 1440 // ); 1441 1442 // ast::IfStmt * currLockIf = new ast::IfStmt( 1443 // location, 1444 // ast::deepCopy( ifCond ), 1445 // genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) ) 1446 // ); 1447 1448 // ast::IfStmt * currUnlockIf = new ast::IfStmt( 1449 // location, 1450 // ifCond, 1451 // genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) ) 1452 // ); 1453 1454 // if ( i == 0 ) { 1455 // outerLockIf = currLockIf; 1456 // outerUnlockIf = currUnlockIf; 1457 // } else { 1458 // // add ifstmt to else of previous stmt 1459 // lastLockIf->else_ = currLockIf; 1460 // lastUnlockIf->else_ = currUnlockIf; 1461 // } 1462 1463 // lastLockIf = currLockIf; 1464 // lastUnlockIf = currUnlockIf; 1465 // } 1466 1467 // // add pointer typing if/elifs to body of routines 1468 // lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } ); 1469 // unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } ); 1470 1471 // // add routines to scope 1472 // declsToAddBefore.push_back( lock_decl ); 1473 // declsToAddBefore.push_back( unlock_decl ); 1474 1475 // newBody->push_front(new ast::DeclStmt( location, lock_decl )); 1476 // newBody->push_front(new ast::DeclStmt( location, unlock_decl )); 1477 1478 return newBody; 452 1479 } 453 1480 … … 564 1591 565 1592 // -------------------------------------------------------------------------- 1593 // Interface Functions: 566 1594 567 1595 void implementKeywords( ast::TranslationUnit & translationUnit ) { 568 (void)translationUnit; 569 assertf(false, "Apply Keywords not implemented." ); 1596 ast::Pass<ThreadKeyword>::run( translationUnit ); 1597 ast::Pass<CoroutineKeyword>::run( translationUnit ); 1598 ast::Pass<MonitorKeyword>::run( translationUnit ); 1599 ast::Pass<GeneratorKeyword>::run( translationUnit ); 1600 ast::Pass<SuspendKeyword>::run( translationUnit ); 570 1601 } 571 1602 -
src/ControlStruct/ExceptTranslateNew.cpp
ref3c383 rd672350 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Nov 8 11:53:00 2021 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Jan 31 18:49:58202213 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 11 17:51:00 2022 13 // Update Count : 2 14 14 // 15 15 … … 27 27 28 28 typedef std::list<ast::CatchStmt*> CatchList; 29 30 void split( CatchList& allHandlers, CatchList& terHandlers,31 CatchList& resHandlers ) {32 while ( !allHandlers.empty() ) {33 ast::CatchStmt * stmt = allHandlers.front();34 allHandlers.pop_front();35 if (stmt->kind == ast::ExceptionKind::Terminate) {36 terHandlers.push_back(stmt);37 } else {38 resHandlers.push_back(stmt);39 }40 }41 }42 29 43 30 void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) { … … 171 158 ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt ); 172 159 173 // Types used in translation, make sure to use clone. 160 // Types used in translation, first group are internal. 161 ast::ObjectDecl * make_index_object( CodeLocation const & ) const; 162 ast::ObjectDecl * make_exception_object( CodeLocation const & ) const; 163 ast::ObjectDecl * make_bool_object( CodeLocation const & ) const; 164 ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const; 165 ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const; 174 166 // void (*function)(); 175 ast::FunctionDecl * try_func_t;167 ast::FunctionDecl * make_try_function( CodeLocation const & ) const; 176 168 // void (*function)(int, exception); 177 ast::FunctionDecl * catch_func_t;169 ast::FunctionDecl * make_catch_function( CodeLocation const & ) const; 178 170 // int (*function)(exception); 179 ast::FunctionDecl * ma tch_func_t;171 ast::FunctionDecl * make_match_function( CodeLocation const & ) const; 180 172 // bool (*function)(exception); 181 ast::FunctionDecl * handle_func_t;173 ast::FunctionDecl * make_handle_function( CodeLocation const & ) const; 182 174 // void (*function)(__attribute__((unused)) void *); 183 ast::FunctionDecl * finally_func_t; 184 185 ast::StructInstType * create_except_type() { 186 assert( except_decl ); 187 return new ast::StructInstType( except_decl ); 188 } 189 void init_func_types(); 175 ast::FunctionDecl * make_finally_function( CodeLocation const & ) const; 190 176 191 177 public: … … 199 185 }; 200 186 201 void TryMutatorCore::init_func_types() { 187 ast::ObjectDecl * TryMutatorCore::make_index_object( 188 CodeLocation const & location ) const { 189 return new ast::ObjectDecl( 190 location, 191 "__handler_index", 192 new ast::BasicType(ast::BasicType::SignedInt), 193 nullptr, //init 194 ast::Storage::Classes{}, 195 ast::Linkage::Cforall 196 ); 197 } 198 199 ast::ObjectDecl * TryMutatorCore::make_exception_object( 200 CodeLocation const & location ) const { 202 201 assert( except_decl ); 203 204 ast::ObjectDecl index_obj( 205 {}, 206 "__handler_index", 207 new ast::BasicType(ast::BasicType::SignedInt) 208 ); 209 ast::ObjectDecl exception_obj( 210 {}, 202 return new ast::ObjectDecl( 203 location, 211 204 "__exception_inst", 212 205 new ast::PointerType( 213 206 new ast::StructInstType( except_decl ) 214 207 ), 215 NULL 216 ); 217 ast::ObjectDecl bool_obj( 218 {}, 208 nullptr, //init 209 ast::Storage::Classes{}, 210 ast::Linkage::Cforall 211 ); 212 } 213 214 ast::ObjectDecl * TryMutatorCore::make_bool_object( 215 CodeLocation const & location ) const { 216 return new ast::ObjectDecl( 217 location, 219 218 "__ret_bool", 220 219 new ast::BasicType( ast::BasicType::Bool ), … … 225 224 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 226 225 ); 227 ast::ObjectDecl voidptr_obj( 228 {}, 226 } 227 228 ast::ObjectDecl * TryMutatorCore::make_voidptr_object( 229 CodeLocation const & location ) const { 230 return new ast::ObjectDecl( 231 location, 229 232 "__hook", 230 233 new ast::PointerType( … … 237 240 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 238 241 ); 239 240 ast::ObjectDecl unused_index_obj( 241 {}, 242 } 243 244 ast::ObjectDecl * TryMutatorCore::make_unused_index_object( 245 CodeLocation const & location ) const { 246 return new ast::ObjectDecl( 247 location, 242 248 "__handler_index", 243 249 new ast::BasicType(ast::BasicType::SignedInt), … … 248 254 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 249 255 ); 250 //unused_index_obj->attributes.push_back( new Attribute( "unused" ) ); 251 252 try_func_t = new ast::FunctionDecl( 253 {}, 256 } 257 258 ast::FunctionDecl * TryMutatorCore::make_try_function( 259 CodeLocation const & location ) const { 260 return new ast::FunctionDecl( 261 location, 254 262 "try", 255 263 {}, //forall … … 260 268 ast::Linkage::Cforall 261 269 ); 262 263 catch_func_t = new ast::FunctionDecl( 264 {}, 270 } 271 272 ast::FunctionDecl * TryMutatorCore::make_catch_function( 273 CodeLocation const & location ) const { 274 return new ast::FunctionDecl( 275 location, 265 276 "catch", 266 277 {}, //forall 267 { ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param278 { make_index_object( location ), make_exception_object( location ) }, 268 279 {}, //return void 269 280 nullptr, … … 271 282 ast::Linkage::Cforall 272 283 ); 273 274 match_func_t = new ast::FunctionDecl( 275 {}, 284 } 285 286 ast::FunctionDecl * TryMutatorCore::make_match_function( 287 CodeLocation const & location ) const { 288 return new ast::FunctionDecl( 289 location, 276 290 "match", 277 291 {}, //forall 278 { ast::deepCopy(&exception_obj)},279 { ast::deepCopy(&unused_index_obj)},292 { make_exception_object( location ) }, 293 { make_unused_index_object( location ) }, 280 294 nullptr, 281 295 ast::Storage::Classes{}, 282 296 ast::Linkage::Cforall 283 297 ); 284 285 handle_func_t = new ast::FunctionDecl( 286 {}, 298 } 299 300 ast::FunctionDecl * TryMutatorCore::make_handle_function( 301 CodeLocation const & location ) const { 302 return new ast::FunctionDecl( 303 location, 287 304 "handle", 288 305 {}, //forall 289 { ast::deepCopy(&exception_obj)},290 { ast::deepCopy(&bool_obj)},306 { make_exception_object( location ) }, 307 { make_bool_object( location ) }, 291 308 nullptr, 292 309 ast::Storage::Classes{}, 293 310 ast::Linkage::Cforall 294 311 ); 295 296 finally_func_t = new ast::FunctionDecl( 297 {}, 312 } 313 314 ast::FunctionDecl * TryMutatorCore::make_finally_function( 315 CodeLocation const & location ) const { 316 return new ast::FunctionDecl( 317 location, 298 318 "finally", 299 319 {}, //forall 300 { ast::deepCopy(&voidptr_obj)},320 { make_voidptr_object( location ) }, 301 321 {}, //return void 302 322 nullptr, … … 304 324 ast::Linkage::Cforall 305 325 ); 306 307 //catch_func_t.get_parameters().push_back( index_obj.clone() );308 //catch_func_t.get_parameters().push_back( exception_obj.clone() );309 //match_func_t.get_returnVals().push_back( unused_index_obj );310 //match_func_t.get_parameters().push_back( exception_obj.clone() );311 //handle_func_t.get_returnVals().push_back( bool_obj.clone() );312 //handle_func_t.get_parameters().push_back( exception_obj.clone() );313 //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );314 326 } 315 327 316 328 // TryStmt Mutation Helpers 317 318 /*319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {320 ast::CompoundStmt * block = tryStmt->body;321 tryStmt->body = nullptr;322 return block;323 }324 */325 329 326 330 ast::FunctionDecl * TryMutatorCore::create_try_wrapper( 327 331 const ast::CompoundStmt *body ) { 328 332 329 ast::FunctionDecl * ret = ast::deepCopy(try_func_t);333 ast::FunctionDecl * ret = make_try_function( body->location ); 330 334 ret->stmts = body; 331 335 return ret; … … 339 343 const CodeLocation loc = handlers.front()->location; 340 344 341 ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);345 ast::FunctionDecl * func_t = make_catch_function( loc ); 342 346 const ast::DeclWithType * index_obj = func_t->params.front(); 343 347 const ast::DeclWithType * except_obj = func_t->params.back(); … … 386 390 // handler->body = nullptr; 387 391 388 handler_wrappers.push_back( new ast::CaseStmt(loc, 392 handler_wrappers.push_back( new ast::CaseStmt(loc, 389 393 ast::ConstantExpr::from_int(loc, index) , 390 394 { block, new ast::ReturnStmt( loc, nullptr ) } … … 393 397 // TODO: Some sort of meaningful error on default perhaps? 394 398 395 /* 396 std::list<Statement*> stmt_handlers; 397 while ( !handler_wrappers.empty() ) { 398 stmt_handlers.push_back( handler_wrappers.front() ); 399 handler_wrappers.pop_front(); 400 } 401 */ 402 403 ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc, 399 ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc, 404 400 new ast::VariableExpr( loc, index_obj ), 405 401 std::move(handler_wrappers) 406 402 ); 407 ast::CompoundStmt * body = new ast::CompoundStmt(loc, 408 {handler_lookup}); 403 ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} ); 409 404 410 405 func_t->stmts = body; … … 433 428 434 429 // Check for type match. 435 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 430 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 436 431 new ast::VariableExpr(loc, except_obj ), 437 432 local_except->get_type() … … 445 440 } 446 441 // Construct the match condition. 447 block->push_back( new ast::IfStmt(loc, 442 block->push_back( new ast::IfStmt(loc, 448 443 cond, modded_handler->body, nullptr ) ); 449 444 450 // xxx - how does this work in new ast451 //modded_handler->set_decl( nullptr );452 //modded_handler->set_cond( nullptr );453 //modded_handler->set_body( nullptr );454 //delete modded_handler;455 445 return block; 456 446 } … … 467 457 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 468 458 469 ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);459 ast::FunctionDecl * func_t = make_match_function( loc ); 470 460 const ast::DeclWithType * except_obj = func_t->params.back(); 471 461 … … 490 480 } 491 481 492 body->push_back( new ast::ReturnStmt(loc, 482 body->push_back( new ast::ReturnStmt(loc, 493 483 ast::ConstantExpr::from_int( loc, 0 ) )); 494 484 … … 525 515 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 526 516 527 ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);517 ast::FunctionDecl * func_t = make_handle_function( loc ); 528 518 const ast::DeclWithType * except_obj = func_t->params.back(); 529 519 … … 535 525 ast::CompoundStmt * handling_code; 536 526 if (handler->body.as<ast::CompoundStmt>()) { 537 handling_code = 538 strict_dynamic_cast<ast::CompoundStmt*>(handler->body.get_and_mutate() );527 handling_code = strict_dynamic_cast<ast::CompoundStmt*>( 528 handler->body.get_and_mutate() ); 539 529 } else { 540 530 handling_code = new ast::CompoundStmt(loc); … … 600 590 const ast::CompoundStmt * body = finally->body; 601 591 602 ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);592 ast::FunctionDecl * func_t = make_finally_function( tryStmt->location ); 603 593 func_t->stmts = body; 604 594 605 // finally->set_block( nullptr );606 // delete finally;607 595 tryStmt->finally = nullptr; 608 609 596 610 597 return func_t; … … 617 604 618 605 const CodeLocation loc = finally_wrapper->location; 619 // Make Cleanup Attribute.620 /*621 std::list< ast::Attribute * > attributes;622 {623 std::list< > attr_params;624 attr_params.push_back( nameOf( finally_wrapper ) );625 attributes.push_back( new Attribute( "cleanup", attr_params ) );626 }627 */628 629 606 return new ast::ObjectDecl( 630 607 loc, … … 644 621 // return false; 645 622 const CodeLocation loc = throwStmt->location; 646 ast::Stmt * result = new ast::ReturnStmt(loc, 623 ast::Stmt * result = new ast::ReturnStmt(loc, 647 624 ast::ConstantExpr::from_bool( loc, false ) 648 625 ); 649 626 result->labels = throwStmt->labels; 650 // delete throwStmt; done by postvisit651 627 return result; 652 628 } … … 660 636 assert( nullptr == except_decl ); 661 637 except_decl = structDecl; 662 init_func_types();663 638 } else if ( structDecl->name == "__cfaehm_try_resume_node" ) { 664 639 assert( nullptr == node_decl ); … … 706 681 } 707 682 } 708 // split( mutStmt->handlers,709 // termination_handlers, resumption_handlers );710 683 711 684 if ( resumption_handlers.size() ) { -
src/InitTweak/FixGlobalInit.cc
ref3c383 rd672350 113 113 accept_all(translationUnit, fixer); 114 114 115 // Say these magic declarations come at the end of the file. 116 CodeLocation const & location = translationUnit.decls.back()->location; 117 115 118 if ( !fixer.core.initStmts.empty() ) { 116 119 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 if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200)); 121 auto initFunction = new ast::FunctionDecl(location, 122 "__global_init__", {}, {}, {}, 123 new ast::CompoundStmt(location, std::move(fixer.core.initStmts)), 124 ast::Storage::Static, ast::Linkage::C, 125 {new ast::Attribute("constructor", std::move(ctorParams))}); 120 126 121 127 translationUnit.decls.emplace_back( initFunction ); … … 124 130 if ( !fixer.core.destroyStmts.empty() ) { 125 131 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))}); 132 if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200)); 133 auto destroyFunction = new ast::FunctionDecl( location, 134 "__global_destroy__", {}, {}, {}, 135 new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)), 136 ast::Storage::Static, ast::Linkage::C, 137 {new ast::Attribute("destructor", std::move(dtorParams))}); 129 138 130 139 translationUnit.decls.emplace_back(destroyFunction); -
src/InitTweak/FixInitNew.cpp
ref3c383 rd672350 16 16 #include "CodeGen/GenType.h" // for genPrettyType 17 17 #include "CodeGen/OperatorTable.h" 18 #include "Common/CodeLocationTools.hpp" 18 19 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 19 20 #include "Common/SemanticError.h" // for SemanticError … … 85 86 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 86 87 /// arguments and return value temporaries 87 struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors> {88 struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors>, public ast::WithConstTranslationUnit { 88 89 const ast::Expr * postvisit( const ast::ImplicitCopyCtorExpr * impCpCtorExpr ); 89 90 const ast::StmtExpr * previsit( const ast::StmtExpr * stmtExpr ); … … 189 190 /// for any member that is missing a corresponding ctor/dtor call. 190 191 /// error if a member is used before constructed 191 struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls> {192 struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls>, public ast::WithConstTranslationUnit { 192 193 void previsit( const ast::FunctionDecl * funcDecl ); 193 194 const ast::DeclWithType * postvisit( const ast::FunctionDecl * funcDecl ); … … 214 215 215 216 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 216 struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting {217 struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithConstTranslationUnit { 217 218 const ast::Expr * postvisit( const ast::ConstructorExpr * ctorExpr ); 218 219 }; … … 509 510 // (VariableExpr and already resolved expression) 510 511 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 511 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, symtab);512 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, { symtab, transUnit().global } ); 512 513 assert( resolved ); 513 514 if ( resolved->env ) { … … 553 554 ast::ptr<ast::Expr> guard = mutArg; 554 555 555 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl( {}, "__tmp", mutResult, nullptr );556 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl(loc, "__tmp", mutResult, nullptr ); 556 557 557 558 // create and resolve copy constructor … … 587 588 588 589 ast::Expr * ResolveCopyCtors::destructRet( const ast::ObjectDecl * ret, const ast::Expr * arg ) { 590 auto global = transUnit().global; 589 591 // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places 590 592 // check for existing cleanup attribute before adding another(?) 591 593 // need to add __Destructor for _tmp_cp variables as well 592 594 593 assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );594 assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );595 assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );595 assertf( global.dtorStruct, "Destructor generation requires __Destructor definition." ); 596 assertf( global.dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." ); 597 assertf( global.dtorDestroy, "Destructor generation requires __destroy_Destructor." ); 596 598 597 599 const CodeLocation loc = ret->location; … … 610 612 auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore ); 611 613 612 auto dtorStructType = new ast::StructInstType( ast::dtorStruct);614 auto dtorStructType = new ast::StructInstType( global.dtorStruct ); 613 615 614 616 // what does this do??? … … 622 624 static UniqueName namer( "_ret_dtor" ); 623 625 auto retDtor = new ast::ObjectDecl(loc, namer.newName(), dtorStructType, new ast::ListInit(loc, { new ast::SingleInit(loc, ast::ConstantExpr::null(loc) ), new ast::SingleInit(loc, new ast::CastExpr( new ast::VariableExpr(loc, dtorFunc ), dtorType ) ) } ) ); 624 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, ast::dtorStructDestroy ) } ) );626 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, global.dtorDestroy ) } ) ); 625 627 stmtsToAddBefore.push_back( new ast::DeclStmt(loc, retDtor ) ); 626 628 627 629 if ( arg ) { 628 auto member = new ast::MemberExpr(loc, ast::dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );630 auto member = new ast::MemberExpr(loc, global.dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) ); 629 631 auto object = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, ret ) ), new ast::PointerType(new ast::VoidType() ) ); 630 632 ast::Expr * assign = createBitwiseAssignment( member, object ); … … 799 801 // to prevent warnings ('_unq0' may be used uninitialized in this function), 800 802 // insert an appropriate zero initializer for UniqueExpr temporaries. 801 ast::Init * makeInit( const ast::Type * t ) {803 ast::Init * makeInit( const ast::Type * t, CodeLocation const & loc ) { 802 804 if ( auto inst = dynamic_cast< const ast::StructInstType * >( t ) ) { 803 805 // initizer for empty struct must be empty 804 if ( inst->base->members.empty() ) return new ast::ListInit({}, {}); 806 if ( inst->base->members.empty() ) { 807 return new ast::ListInit( loc, {} ); 808 } 805 809 } else if ( auto inst = dynamic_cast< const ast::UnionInstType * >( t ) ) { 806 810 // initizer for empty union must be empty 807 if ( inst->base->members.empty() ) return new ast::ListInit({}, {}); 808 } 809 810 return new ast::ListInit( {}, { new ast::SingleInit( {}, ast::ConstantExpr::from_int({}, 0) ) } ); 811 if ( inst->base->members.empty() ) { 812 return new ast::ListInit( loc, {} ); 813 } 814 } 815 816 return new ast::ListInit( loc, { 817 new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ) 818 } ); 811 819 } 812 820 … … 832 840 } else { 833 841 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 834 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result ) );842 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result, mutExpr->location ) ); 835 843 mutExpr->var = new ast::VariableExpr( mutExpr->location, mutExpr->object ); 836 844 } … … 1172 1180 auto guard = makeFuncGuard( [this]() { symtab.enterScope(); }, [this]() { symtab.leaveScope(); } ); 1173 1181 symtab.addFunction( function ); 1182 auto global = transUnit().global; 1174 1183 1175 1184 // need to iterate through members in reverse in order for … … 1217 1226 1218 1227 static UniqueName memberDtorNamer = { "__memberDtor" }; 1219 assertf( ast::dtorStruct, "builtin __Destructor not found." );1220 assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );1228 assertf( global.dtorStruct, "builtin __Destructor not found." ); 1229 assertf( global.dtorDestroy, "builtin __destroy_Destructor not found." ); 1221 1230 1222 1231 ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) ); … … 1228 1237 auto dtorType = new ast::PointerType( dtorFtype ); 1229 1238 1230 auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( ast::dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );1231 destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( {}, ast::dtorStructDestroy ) } ) );1239 auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( global.dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) ); 1240 destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, global.dtorDestroy ) } ) ); 1232 1241 mutStmts->push_front( new ast::DeclStmt(loc, destructor ) ); 1233 1242 mutStmts->kids.splice( mutStmts->kids.begin(), stmtsToAdd ); … … 1323 1332 1324 1333 const ast::Expr * GenStructMemberCalls::postvisit( const ast::UntypedExpr * untypedExpr ) { 1325 // Expression * newExpr = untypedExpr;1326 1334 // xxx - functions returning ast::ptr seems wrong... 1327 auto res = ResolvExpr::findVoidExpression( untypedExpr, symtab ); 1328 return res.release(); 1329 // return newExpr; 1335 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1336 // Fix CodeLocation (at least until resolver is fixed). 1337 auto fix = localFillCodeLocations( untypedExpr->location, res.release() ); 1338 return strict_dynamic_cast<const ast::Expr *>( fix ); 1330 1339 } 1331 1340 … … 1361 1370 1362 1371 // resolve assignment and dispose of new env 1363 auto resolved = ResolvExpr::findVoidExpression( assign, symtab);1372 auto resolved = ResolvExpr::findVoidExpression( assign, { symtab, transUnit().global } ); 1364 1373 auto mut = resolved.get_and_mutate(); 1365 1374 assertf(resolved.get() == mut, "newly resolved expression must be unique"); -
src/Parser/parser.yy
ref3c383 rd672350 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 11 14:26:15202213 // Update Count : 5 17412 // Last Modified On : Mon Mar 14 16:35:29 2022 13 // Update Count : 5276 14 14 // 15 15 … … 610 610 // | RESUME '(' comma_expression ')' compound_statement 611 611 // { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; } 612 | IDENTIFIER IDENTIFIER // syntax error 613 { 614 SemanticError( yylloc, ::toString( "Adjacent identifiers are not meaningful in an expression. " 615 "Possible problem is identifier \"", *$1.str, 616 "\" is a misspelled typename or an incorrectly specified type name, " 617 "e.g., missing generic parameter or missing struct/union/enum before typename." ) ); 618 $$ = nullptr; 619 } 620 | IDENTIFIER direct_type // syntax error 621 { 622 SemanticError( yylloc, ::toString( "Identifier \"", *$1.str, "\" cannot appear before a type. " 623 "Possible problem is misspelled storage or CV qualifier." ) ); 624 $$ = nullptr; 625 } 612 626 ; 613 627 … … 638 652 // Historic, transitional: Disallow commas in subscripts. 639 653 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts. 640 // { SemanticError( yylloc, "New array subscript is currently unimplemented." ); $$ = nullptr; }641 654 // Current: Commas in subscripts make tuples. 642 655 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); } … … 647 660 // equivalent to the old x[i,j]. 648 661 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 662 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a] 663 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 664 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 665 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); } 649 666 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 650 667 { … … 1052 1069 identifier_or_type_name ':' attribute_list_opt statement 1053 1070 { $$ = $4->add_label( $1, $3 ); } 1071 | identifier_or_type_name ':' attribute_list_opt error // syntax error 1072 { 1073 SemanticError( yylloc, ::toString( "Label \"", *$1.str, "\" must be associated with a statement, " 1074 "where a declaration, case, or default is not a statement. " 1075 "Move the label or terminate with a semi-colon." ) ); 1076 $$ = nullptr; 1077 } 1054 1078 ; 1055 1079 … … 1086 1110 | statement_list_nodecl statement 1087 1111 { assert( $1 ); $1->set_last( $2 ); $$ = $1; } 1112 | statement_list_nodecl error // syntax error 1113 { SemanticError( yylloc, "Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; } 1088 1114 ; 1089 1115 … … 1093 1119 | MUTEX '(' ')' comma_expression ';' 1094 1120 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); } 1095 // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }1096 1121 ; 1097 1122 … … 1113 1138 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1114 1139 } 1140 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntax error 1141 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1115 1142 | CHOOSE '(' comma_expression ')' case_clause // CFA 1116 1143 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); } … … 1120 1147 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1121 1148 } 1149 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error 1150 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1122 1151 ; 1123 1152 … … 1158 1187 1159 1188 case_label: // CFA 1160 CASE case_value_list ':' { $$ = $2; } 1189 CASE error // syntax error 1190 { SemanticError( yylloc, "Missing case list after case." ); $$ = nullptr; } 1191 | CASE case_value_list ':' { $$ = $2; } 1192 | CASE case_value_list error // syntax error 1193 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1161 1194 | DEFAULT ':' { $$ = new StatementNode( build_default() ); } 1162 1195 // A semantic check is required to ensure only one default clause per switch/choose statement. 1163 ; 1164 1165 //label_list_opt: 1166 // // empty 1167 // | identifier_or_type_name ':' 1168 // | label_list_opt identifier_or_type_name ':' 1169 // ; 1196 | DEFAULT error // syntax error 1197 { SemanticError( yylloc, "Missing colon after default." ); $$ = nullptr; } 1198 ; 1170 1199 1171 1200 case_label_list: // CFA … … 1403 1432 | when_clause_opt ELSE statement 1404 1433 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); } 1405 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)1406 | when_clause_opt timeout statement WOR ELSE statement 1434 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1435 | when_clause_opt timeout statement WOR ELSE statement // syntax error 1407 1436 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1408 1437 | when_clause_opt timeout statement WOR when_clause ELSE statement -
src/ResolvExpr/CandidateFinder.cpp
ref3c383 rd672350 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 14:55:00 201913 // Update Count : 212 // Last Modified On : Wed Mar 16 11:58:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 595 595 /// Actually visits expressions to find their candidate interpretations 596 596 class Finder final : public ast::WithShortCircuiting { 597 const ResolveContext & context; 597 598 const ast::SymbolTable & symtab; 598 599 public: … … 618 619 619 620 Finder( CandidateFinder & f ) 620 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env),621 targetType( f.targetType ) {}621 : context( f.context ), symtab( context.symtab ), selfFinder( f ), 622 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {} 622 623 623 624 void previsit( const ast::Node * ) { visit_children = false; } … … 872 873 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 873 874 874 CandidateFinder funcFinder { symtab, tenv };875 CandidateFinder funcFinder( context, tenv ); 875 876 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 876 877 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); … … 918 919 // find function operators 919 920 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; 920 CandidateFinder opFinder { symtab, tenv };921 CandidateFinder opFinder( context, tenv ); 921 922 // okay if there aren't any function operations 922 923 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); … … 1059 1060 1060 1061 void postvisit( const ast::AddressExpr * addressExpr ) { 1061 CandidateFinder finder { symtab, tenv };1062 CandidateFinder finder( context, tenv ); 1062 1063 finder.find( addressExpr->arg ); 1063 1064 … … 1079 1080 ast::ptr< ast::Type > toType = castExpr->result; 1080 1081 assert( toType ); 1081 toType = resolveTypeof( toType, symtab);1082 toType = resolveTypeof( toType, context ); 1082 1083 // toType = SymTab::validateType( castExpr->location, toType, symtab ); 1083 1084 toType = adjustExprType( toType, tenv, symtab ); 1084 1085 1085 CandidateFinder finder { symtab, tenv, toType };1086 CandidateFinder finder( context, tenv, toType ); 1086 1087 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1087 1088 … … 1136 1137 void postvisit( const ast::VirtualCastExpr * castExpr ) { 1137 1138 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 1138 CandidateFinder finder { symtab, tenv };1139 CandidateFinder finder( context, tenv ); 1139 1140 // don't prune here, all alternatives guaranteed to have same type 1140 1141 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); … … 1153 1154 auto target = inst->base.get(); 1154 1155 1155 CandidateFinder finder { symtab, tenv };1156 CandidateFinder finder( context, tenv ); 1156 1157 1157 1158 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) { … … 1202 1203 1203 1204 void postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1204 CandidateFinder aggFinder { symtab, tenv };1205 CandidateFinder aggFinder( context, tenv ); 1205 1206 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1206 1207 for ( CandidateRef & agg : aggFinder.candidates ) { … … 1287 1288 addCandidate( 1288 1289 new ast::SizeofExpr{ 1289 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab) },1290 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) }, 1290 1291 tenv ); 1291 1292 } else { 1292 1293 // find all candidates for the argument to sizeof 1293 CandidateFinder finder { symtab, tenv };1294 CandidateFinder finder( context, tenv ); 1294 1295 finder.find( sizeofExpr->expr ); 1295 1296 // find the lowest-cost candidate, otherwise ambiguous … … 1311 1312 addCandidate( 1312 1313 new ast::AlignofExpr{ 1313 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab) },1314 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) }, 1314 1315 tenv ); 1315 1316 } else { 1316 1317 // find all candidates for the argument to alignof 1317 CandidateFinder finder { symtab, tenv };1318 CandidateFinder finder( context, tenv ); 1318 1319 finder.find( alignofExpr->expr ); 1319 1320 // find the lowest-cost candidate, otherwise ambiguous … … 1354 1355 1355 1356 void postvisit( const ast::LogicalExpr * logicalExpr ) { 1356 CandidateFinder finder1 { symtab, tenv };1357 CandidateFinder finder1( context, tenv ); 1357 1358 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 1358 1359 if ( finder1.candidates.empty() ) return; 1359 1360 1360 CandidateFinder finder2 { symtab, tenv };1361 CandidateFinder finder2( context, tenv ); 1361 1362 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1362 1363 if ( finder2.candidates.empty() ) return; … … 1384 1385 void postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1385 1386 // candidates for condition 1386 CandidateFinder finder1 { symtab, tenv };1387 CandidateFinder finder1( context, tenv ); 1387 1388 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1388 1389 if ( finder1.candidates.empty() ) return; 1389 1390 1390 1391 // candidates for true result 1391 CandidateFinder finder2 { symtab, tenv };1392 CandidateFinder finder2( context, tenv ); 1392 1393 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1393 1394 if ( finder2.candidates.empty() ) return; 1394 1395 1395 1396 // candidates for false result 1396 CandidateFinder finder3 { symtab, tenv };1397 CandidateFinder finder3( context, tenv ); 1397 1398 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1398 1399 if ( finder3.candidates.empty() ) return; … … 1445 1446 void postvisit( const ast::CommaExpr * commaExpr ) { 1446 1447 ast::TypeEnvironment env{ tenv }; 1447 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );1448 1449 CandidateFinder finder2 { symtab, env };1448 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env ); 1449 1450 CandidateFinder finder2( context, env ); 1450 1451 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 1451 1452 … … 1460 1461 1461 1462 void postvisit( const ast::ConstructorExpr * ctorExpr ) { 1462 CandidateFinder finder { symtab, tenv };1463 CandidateFinder finder( context, tenv ); 1463 1464 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1464 1465 for ( CandidateRef & r : finder.candidates ) { … … 1469 1470 void postvisit( const ast::RangeExpr * rangeExpr ) { 1470 1471 // resolve low and high, accept candidates where low and high types unify 1471 CandidateFinder finder1 { symtab, tenv };1472 CandidateFinder finder1( context, tenv ); 1472 1473 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 1473 1474 if ( finder1.candidates.empty() ) return; 1474 1475 1475 CandidateFinder finder2 { symtab, tenv };1476 CandidateFinder finder2( context, tenv ); 1476 1477 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1477 1478 if ( finder2.candidates.empty() ) return; … … 1549 1550 1550 1551 void postvisit( const ast::UniqueExpr * unqExpr ) { 1551 CandidateFinder finder { symtab, tenv };1552 CandidateFinder finder( context, tenv ); 1552 1553 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 1553 1554 for ( CandidateRef & r : finder.candidates ) { … … 1558 1559 1559 1560 void postvisit( const ast::StmtExpr * stmtExpr ) { 1560 addCandidate( resolveStmtExpr( stmtExpr, symtab), tenv );1561 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv ); 1561 1562 } 1562 1563 … … 1570 1571 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1571 1572 // calculate target type 1572 const ast::Type * toType = resolveTypeof( initAlt.type, symtab);1573 const ast::Type * toType = resolveTypeof( initAlt.type, context ); 1573 1574 // toType = SymTab::validateType( initExpr->location, toType, symtab ); 1574 1575 toType = adjustExprType( toType, tenv, symtab ); … … 1576 1577 // types are not bound to the initialization type, since return type variables are 1577 1578 // only open for the duration of resolving the UntypedExpr. 1578 CandidateFinder finder { symtab, tenv, toType };1579 CandidateFinder finder( context, tenv, toType ); 1579 1580 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1580 1581 for ( CandidateRef & cand : finder.candidates ) { … … 1693 1694 } 1694 1695 else { 1695 satisfyAssertions(candidate, localSyms, satisfied, errors);1696 satisfyAssertions(candidate, context.symtab, satisfied, errors); 1696 1697 needRecomputeKey = true; 1697 1698 } … … 1855 1856 r->expr = ast::mutate_field( 1856 1857 r->expr.get(), &ast::Expr::result, 1857 adjustExprType( r->expr->result, r->env, localSyms) );1858 adjustExprType( r->expr->result, r->env, context.symtab ) ); 1858 1859 } 1859 1860 } … … 1873 1874 1874 1875 for ( const auto & x : xs ) { 1875 out.emplace_back( localSyms, env );1876 out.emplace_back( context, env ); 1876 1877 out.back().find( x, ResolvMode::withAdjustment() ); 1877 1878 -
src/ResolvExpr/CandidateFinder.hpp
ref3c383 rd672350 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 9:51:00 201913 // Update Count : 212 // Last Modified On : Wed Mar 16 15:22:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 25 25 namespace ResolvExpr { 26 26 27 struct ResolveContext; 28 27 29 /// Data to perform expression resolution 28 30 struct CandidateFinder { 29 31 CandidateList candidates; ///< List of candidate resolutions 30 const ast::SymbolTable & localSyms; ///< Symbol table to lookup candidates32 const ResolveContext & context; ///< Information about where the canditates are being found. 31 33 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 34 ast::ptr< ast::Type > targetType; ///< Target type for resolution … … 34 36 35 37 CandidateFinder( 36 const ast::SymbolTable & syms, const ast::TypeEnvironment & env,38 const ResolveContext & context, const ast::TypeEnvironment & env, 37 39 const ast::Type * tt = nullptr ) 38 : candidates(), localSyms( syms), env( env ), targetType( tt ) {}40 : candidates(), context( context ), env( env ), targetType( tt ) {} 39 41 40 42 /// Fill candidates with feasible resolutions for `expr` -
src/ResolvExpr/CandidatePrinter.cpp
ref3c383 rd672350 10 10 // Created On : Tue Nov 9 9:54:00 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Nov 9 15:47:00 202113 // Update Count : 012 // Last Modified On : Wed Mar 16 13:56:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 22 22 #include "AST/TranslationUnit.hpp" 23 23 #include "ResolvExpr/CandidateFinder.hpp" 24 #include "ResolvExpr/Resolver.h" 24 25 25 26 #include <iostream> … … 29 30 namespace { 30 31 31 class CandidatePrintCore : public ast::WithSymbolTable { 32 class CandidatePrintCore : public ast::WithSymbolTable, 33 public ast::WithConstTranslationUnit { 32 34 std::ostream & os; 33 35 public: … … 36 38 void postvisit( const ast::ExprStmt * stmt ) { 37 39 ast::TypeEnvironment env; 38 CandidateFinder finder( symtab, env );40 CandidateFinder finder( { symtab, transUnit().global }, env ); 39 41 finder.find( stmt->expr, ResolvMode::withAdjustment() ); 40 42 int count = 1; -
src/ResolvExpr/ResolveTypeof.cc
ref3c383 rd672350 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:12:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 19 16:49:04 201513 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 16:09:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 22 22 #include "AST/Node.hpp" 23 23 #include "AST/Pass.hpp" 24 #include "AST/TranslationUnit.hpp" 24 25 #include "AST/Type.hpp" 25 26 #include "AST/TypeEnvironment.hpp" … … 119 120 namespace { 120 121 struct ResolveTypeof_new : public ast::WithShortCircuiting { 121 const ast::SymbolTable & localSymtab; 122 123 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {} 122 const ResolveContext & context; 123 124 ResolveTypeof_new( const ResolveContext & context ) : 125 context( context ) {} 124 126 125 127 void previsit( const ast::TypeofType * ) { visit_children = false; } … … 137 139 ast::TypeEnvironment dummy; 138 140 ast::ptr< ast::Expr > newExpr = 139 resolveInVoidContext( typeofType->expr, localSymtab, dummy );141 resolveInVoidContext( typeofType->expr, context, dummy ); 140 142 assert( newExpr->result && ! newExpr->result->isVoid() ); 141 143 newType = newExpr->result; … … 161 163 } // anonymous namespace 162 164 163 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab) {164 ast::Pass< ResolveTypeof_new > mutator { symtab };165 const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) { 166 ast::Pass< ResolveTypeof_new > mutator( context ); 165 167 return type->accept( mutator ); 166 168 } … … 168 170 struct FixArrayDimension { 169 171 // should not require a mutable symbol table - prevent pass template instantiation 170 const ast::SymbolTable & _symtab;171 FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}172 const ResolveContext & context; 173 FixArrayDimension(const ResolveContext & context) : context( context ) {} 172 174 173 175 const ast::ArrayType * previsit (const ast::ArrayType * arrayType) { 174 176 if (!arrayType->dimension) return arrayType; 175 177 auto mutType = mutate(arrayType); 176 ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt); 177 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab); 178 auto globalSizeType = context.global.sizeType; 179 ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt); 180 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context ); 178 181 179 182 if (InitTweak::isConstExpr(mutType->dimension)) { … … 187 190 }; 188 191 189 const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {190 ast::Pass<FixArrayDimension> visitor {symtab};192 const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) { 193 ast::Pass<FixArrayDimension> visitor(context); 191 194 return type->accept(visitor); 192 195 } 193 196 194 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab) {195 if (!decl->isTypeFixed) { 197 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) { 198 if (!decl->isTypeFixed) { 196 199 auto mutDecl = mutate(decl); 197 auto resolvedType = resolveTypeof(decl->type, symtab);198 resolvedType = fixArrayType(resolvedType, symtab);200 auto resolvedType = resolveTypeof(decl->type, context); 201 resolvedType = fixArrayType(resolvedType, context); 199 202 mutDecl->type = resolvedType; 200 203 -
src/ResolvExpr/ResolveTypeof.h
ref3c383 rd672350 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:14:53 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:38:35 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 11:33:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 22 22 namespace ast { 23 23 class Type; 24 class SymbolTable;25 24 class ObjectDecl; 26 25 } 27 26 28 27 namespace ResolvExpr { 28 struct ResolveContext; 29 29 30 Type *resolveTypeof( Type*, const SymTab::Indexer &indexer ); 30 const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable& );31 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab);31 const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & ); 32 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & ); 32 33 } // namespace ResolvExpr 33 34 -
src/ResolvExpr/Resolver.cc
ref3c383 rd672350 9 9 // Author : Aaron B. Moss 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 1 16:27:14202213 // Update Count : 24 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 18 10:41:00 2022 13 // Update Count : 247 14 14 // 15 15 … … 997 997 /// Calls the CandidateFinder and finds the single best candidate 998 998 CandidateRef findUnfinishedKindExpression( 999 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,999 const ast::Expr * untyped, const ResolveContext & context, const std::string & kind, 1000 1000 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 1001 1001 ) { … … 1007 1007 ++recursion_level; 1008 1008 ast::TypeEnvironment env; 1009 CandidateFinder finder { symtab, env };1009 CandidateFinder finder( context, env ); 1010 1010 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 1011 1011 --recursion_level; … … 1129 1129 1130 1130 ast::ptr< ast::Expr > resolveInVoidContext( 1131 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1131 const ast::Expr * expr, const ResolveContext & context, 1132 ast::TypeEnvironment & env 1132 1133 ) { 1133 1134 assertf( expr, "expected a non-null expression" ); … … 1136 1137 ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr }; 1137 1138 CandidateRef choice = findUnfinishedKindExpression( 1138 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );1139 untyped, context, "", anyCandidate, ResolvMode::withAdjustment() ); 1139 1140 1140 1141 // a cast expression has either 0 or 1 interpretations (by language rules); … … 1149 1150 /// context. 1150 1151 ast::ptr< ast::Expr > findVoidExpression( 1151 const ast::Expr * untyped, const ast::SymbolTable & symtab1152 const ast::Expr * untyped, const ResolveContext & context 1152 1153 ) { 1153 1154 ast::TypeEnvironment env; 1154 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );1155 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env ); 1155 1156 finishExpr( newExpr, env, untyped->env ); 1156 1157 return newExpr; … … 1163 1164 /// lowest cost, returning the resolved version 1164 1165 ast::ptr< ast::Expr > findKindExpression( 1165 const ast::Expr * untyped, const ast::SymbolTable & symtab,1166 const ast::Expr * untyped, const ResolveContext & context, 1166 1167 std::function<bool(const Candidate &)> pred = anyCandidate, 1167 1168 const std::string & kind = "", ResolvMode mode = {} … … 1169 1170 if ( ! untyped ) return {}; 1170 1171 CandidateRef choice = 1171 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );1172 findUnfinishedKindExpression( untyped, context, kind, pred, mode ); 1172 1173 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env ); 1173 1174 return std::move( choice->expr ); … … 1176 1177 /// Resolve `untyped` to the single expression whose candidate is the best match 1177 1178 ast::ptr< ast::Expr > findSingleExpression( 1178 const ast::Expr * untyped, const ast::SymbolTable & symtab1179 const ast::Expr * untyped, const ResolveContext & context 1179 1180 ) { 1180 1181 Stats::ResolveTime::start( untyped ); 1181 auto res = findKindExpression( untyped, symtab);1182 auto res = findKindExpression( untyped, context ); 1182 1183 Stats::ResolveTime::stop(); 1183 1184 return res; … … 1186 1187 1187 1188 ast::ptr< ast::Expr > findSingleExpression( 1188 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1189 const ast::Expr * untyped, const ast::Type * type, 1190 const ResolveContext & context 1189 1191 ) { 1190 1192 assert( untyped && type ); 1191 1193 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 1192 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab);1193 removeExtraneousCast( newExpr, symtab );1194 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context ); 1195 removeExtraneousCast( newExpr, context.symtab ); 1194 1196 return newExpr; 1195 1197 } … … 1217 1219 /// Resolve `untyped` as an integral expression, returning the resolved version 1218 1220 ast::ptr< ast::Expr > findIntegralExpression( 1219 const ast::Expr * untyped, const ast::SymbolTable & symtab1221 const ast::Expr * untyped, const ResolveContext & context 1220 1222 ) { 1221 return findKindExpression( untyped, symtab, hasIntegralType, "condition" );1223 return findKindExpression( untyped, context, hasIntegralType, "condition" ); 1222 1224 } 1223 1225 … … 1249 1251 // for work previously in GenInit 1250 1252 static InitTweak::ManagedTypes_new managedTypes; 1253 ResolveContext context; 1251 1254 1252 1255 bool inEnumDecl = false; … … 1254 1257 public: 1255 1258 static size_t traceId; 1256 Resolver_new() = default; 1257 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 1259 Resolver_new( const ast::TranslationGlobal & global ) : 1260 context{ symtab, global } {} 1261 Resolver_new( const ResolveContext & context ) : 1262 ast::WithSymbolTable{ context.symtab }, 1263 context{ symtab, context.global } {} 1258 1264 1259 1265 const ast::FunctionDecl * previsit( const ast::FunctionDecl * ); … … 1272 1278 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1273 1279 const ast::IfStmt * previsit( const ast::IfStmt * ); 1274 const ast::WhileDoStmt * previsit( const ast::WhileDoStmt * );1280 const ast::WhileDoStmt * previsit( const ast::WhileDoStmt * ); 1275 1281 const ast::ForStmt * previsit( const ast::ForStmt * ); 1276 1282 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); … … 1299 1305 1300 1306 void resolve( ast::TranslationUnit& translationUnit ) { 1301 ast::Pass< Resolver_new >::run( translationUnit );1307 ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global ); 1302 1308 } 1303 1309 1304 1310 ast::ptr< ast::Init > resolveCtorInit( 1305 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab1311 const ast::ConstructorInit * ctorInit, const ResolveContext & context 1306 1312 ) { 1307 1313 assert( ctorInit ); 1308 ast::Pass< Resolver_new > resolver { symtab };1314 ast::Pass< Resolver_new > resolver( context ); 1309 1315 return ctorInit->accept( resolver ); 1310 1316 } 1311 1317 1312 1318 const ast::Expr * resolveStmtExpr( 1313 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab1319 const ast::StmtExpr * stmtExpr, const ResolveContext & context 1314 1320 ) { 1315 1321 assert( stmtExpr ); 1316 ast::Pass< Resolver_new > resolver { symtab };1322 ast::Pass< Resolver_new > resolver( context ); 1317 1323 auto ret = mutate(stmtExpr->accept(resolver)); 1318 1324 strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult(); … … 1321 1327 1322 1328 namespace { 1323 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {1329 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) { 1324 1330 std::string name = attr->normalizedName(); 1325 1331 if (name == "constructor" || name == "destructor") { 1326 1332 if (attr->params.size() == 1) { 1327 1333 auto arg = attr->params.front(); 1328 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab);1334 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context ); 1329 1335 auto result = eval(arg); 1330 1336 … … 1369 1375 1370 1376 for (auto & attr: mutDecl->attributes) { 1371 attr = handleAttribute(mutDecl->location, attr, symtab);1377 attr = handleAttribute(mutDecl->location, attr, context ); 1372 1378 } 1373 1379 … … 1382 1388 } 1383 1389 for (auto & asst : mutDecl->assertions) { 1384 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);1390 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context); 1385 1391 symtab.addId(asst); 1386 1392 mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst)); … … 1394 1400 1395 1401 for (auto & param : mutDecl->params) { 1396 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);1402 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context); 1397 1403 symtab.addId(param); 1398 1404 paramTypes.emplace_back(param->get_type()); 1399 1405 } 1400 1406 for (auto & ret : mutDecl->returns) { 1401 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);1407 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context); 1402 1408 returnTypes.emplace_back(ret->get_type()); 1403 1409 } … … 1470 1476 // enumerator initializers should not use the enum type to initialize, since the 1471 1477 // enum type is still incomplete at this point. Use `int` instead. 1472 objectDecl = fixObjectType(objectDecl, symtab);1478 objectDecl = fixObjectType(objectDecl, context); 1473 1479 currentObject = ast::CurrentObject{ 1474 1480 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; … … 1476 1482 else { 1477 1483 if (!objectDecl->isTypeFixed) { 1478 auto newDecl = fixObjectType(objectDecl, symtab);1484 auto newDecl = fixObjectType(objectDecl, context); 1479 1485 auto mutDecl = mutate(newDecl); 1480 1486 … … 1507 1513 // nested type decls are hoisted already. no need to do anything 1508 1514 if (auto obj = member.as<ast::ObjectDecl>()) { 1509 member = fixObjectType(obj, symtab);1515 member = fixObjectType(obj, context); 1510 1516 } 1511 1517 } … … 1530 1536 return ast::mutate_field( 1531 1537 assertDecl, &ast::StaticAssertDecl::cond, 1532 findIntegralExpression( assertDecl->cond, symtab) );1538 findIntegralExpression( assertDecl->cond, context ) ); 1533 1539 } 1534 1540 1535 1541 template< typename PtrType > 1536 const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab) {1542 const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) { 1537 1543 if ( type->dimension ) { 1538 ast::ptr< ast::Type > sizeType = ast::sizeType;1544 ast::ptr< ast::Type > sizeType = context.global.sizeType; 1539 1545 ast::mutate_field( 1540 1546 type, &PtrType::dimension, 1541 findSingleExpression( type->dimension, sizeType, symtab) );1547 findSingleExpression( type->dimension, sizeType, context ) ); 1542 1548 } 1543 1549 return type; … … 1545 1551 1546 1552 const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) { 1547 return handlePtrType( at, symtab);1553 return handlePtrType( at, context ); 1548 1554 } 1549 1555 1550 1556 const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) { 1551 return handlePtrType( pt, symtab);1557 return handlePtrType( pt, context ); 1552 1558 } 1553 1559 … … 1557 1563 1558 1564 return ast::mutate_field( 1559 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab) );1565 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) ); 1560 1566 } 1561 1567 … … 1564 1570 1565 1571 asmExpr = ast::mutate_field( 1566 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab) );1572 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) ); 1567 1573 1568 1574 return asmExpr; … … 1578 1584 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1579 1585 return ast::mutate_field( 1580 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab) );1586 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) ); 1581 1587 } 1582 1588 1583 1589 const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) { 1584 1590 return ast::mutate_field( 1585 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab) );1591 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) ); 1586 1592 } 1587 1593 … … 1589 1595 if ( forStmt->cond ) { 1590 1596 forStmt = ast::mutate_field( 1591 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab) );1597 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) ); 1592 1598 } 1593 1599 1594 1600 if ( forStmt->inc ) { 1595 1601 forStmt = ast::mutate_field( 1596 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab) );1602 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) ); 1597 1603 } 1598 1604 … … 1604 1610 switchStmt = ast::mutate_field( 1605 1611 switchStmt, &ast::SwitchStmt::cond, 1606 findIntegralExpression( switchStmt->cond, symtab) );1612 findIntegralExpression( switchStmt->cond, context ) ); 1607 1613 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 1608 1614 return switchStmt; … … 1617 1623 ast::ptr< ast::Expr > untyped = 1618 1624 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1619 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab);1625 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context ); 1620 1626 1621 1627 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1638 1644 branchStmt = ast::mutate_field( 1639 1645 branchStmt, &ast::BranchStmt::computedTarget, 1640 findSingleExpression( branchStmt->computedTarget, target, symtab) );1646 findSingleExpression( branchStmt->computedTarget, target, context ) ); 1641 1647 } 1642 1648 return branchStmt; … … 1648 1654 returnStmt = ast::mutate_field( 1649 1655 returnStmt, &ast::ReturnStmt::expr, 1650 findSingleExpression( returnStmt->expr, functionReturn, symtab) );1656 findSingleExpression( returnStmt->expr, functionReturn, context ) ); 1651 1657 } 1652 1658 return returnStmt; … … 1663 1669 throwStmt = ast::mutate_field( 1664 1670 throwStmt, &ast::ThrowStmt::expr, 1665 findSingleExpression( throwStmt->expr, exceptType, symtab) );1671 findSingleExpression( throwStmt->expr, exceptType, context ) ); 1666 1672 } 1667 1673 return throwStmt; … … 1707 1713 1708 1714 ast::TypeEnvironment env; 1709 CandidateFinder funcFinder { symtab, env };1715 CandidateFinder funcFinder( context, env ); 1710 1716 1711 1717 // Find all candidates for a function in canonical form … … 1921 1927 ); 1922 1928 1923 clause2.target.args.emplace_back( findSingleExpression( init, symtab) );1929 clause2.target.args.emplace_back( findSingleExpression( init, context ) ); 1924 1930 } 1925 1931 1926 1932 // Resolve the conditions as if it were an IfStmt, statements normally 1927 clause2.cond = findSingleExpression( clause.cond, symtab);1933 clause2.cond = findSingleExpression( clause.cond, context ); 1928 1934 clause2.stmt = clause.stmt->accept( *visitor ); 1929 1935 … … 1940 1946 ast::ptr< ast::Type > target = 1941 1947 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1942 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab);1943 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab);1948 timeout2.time = findSingleExpression( stmt->timeout.time, target, context ); 1949 timeout2.cond = findSingleExpression( stmt->timeout.cond, context ); 1944 1950 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1945 1951 … … 1954 1960 ast::WaitForStmt::OrElse orElse2; 1955 1961 1956 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab);1962 orElse2.cond = findSingleExpression( stmt->orElse.cond, context ); 1957 1963 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1958 1964 … … 1975 1981 for (auto & expr : exprs) { 1976 1982 // only struct- and union-typed expressions are viable candidates 1977 expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );1983 expr = findKindExpression( expr, context, structOrUnion, "with expression" ); 1978 1984 1979 1985 // if with expression might be impure, create a temporary so that it is evaluated once … … 2001 2007 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 2002 2008 singleInit->location, singleInit->value, currentObject.getOptions() }; 2003 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab);2009 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context ); 2004 2010 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 2005 2011 -
src/ResolvExpr/Resolver.h
ref3c383 rd672350 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:18:34 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Feb 18 20:40:38 201913 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 11:32:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 23 23 class Declaration; 24 24 class Expression; 25 class DeletedExpr; 25 26 class StmtExpr; 27 class Type; 26 28 namespace SymTab { 27 29 class Indexer; … … 35 37 class StmtExpr; 36 38 class SymbolTable; 39 class TranslationGlobal; 37 40 class TranslationUnit; 38 41 class Type; … … 55 58 void resolveWithExprs( std::list< Declaration * > & translationUnit ); 56 59 60 /// Helper Type: Passes around information between various sub-calls. 61 struct ResolveContext { 62 const ast::SymbolTable & symtab; 63 const ast::TranslationGlobal & global; 64 }; 65 57 66 /// Checks types and binds syntactic constructs to typed representations 58 67 void resolve( ast::TranslationUnit& translationUnit ); … … 62 71 /// context. 63 72 ast::ptr< ast::Expr > resolveInVoidContext( 64 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );73 const ast::Expr * expr, const ResolveContext &, ast::TypeEnvironment & env ); 65 74 /// Resolve `untyped` to the single expression whose candidate is the best match for the 66 75 /// given type. 67 76 ast::ptr< ast::Expr > findSingleExpression( 68 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab);77 const ast::Expr * untyped, const ast::Type * type, const ResolveContext & ); 69 78 ast::ptr< ast::Expr > findVoidExpression( 70 const ast::Expr * untyped, const ast::SymbolTable & symtab);79 const ast::Expr * untyped, const ResolveContext & ); 71 80 /// Resolves a constructor init expression 72 81 ast::ptr< ast::Init > resolveCtorInit( 73 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab);82 const ast::ConstructorInit * ctorInit, const ResolveContext & context ); 74 83 /// Resolves a statement expression 75 84 const ast::Expr * resolveStmtExpr( 76 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab);85 const ast::StmtExpr * stmtExpr, const ResolveContext & context ); 77 86 } // namespace ResolvExpr 78 87 -
src/ResolvExpr/Unify.cc
ref3c383 rd672350 943 943 // check that the other type is compatible and named the same 944 944 auto otherInst = dynamic_cast< const XInstType * >( other ); 945 this->result = otherInst && inst->name == otherInst->name;945 if (otherInst && inst->name == otherInst->name) this->result = otherInst; 946 946 return otherInst; 947 947 } -
src/SymTab/Validate.cc
ref3c383 rd672350 194 194 }; 195 195 196 // These structs are the sub-sub-passes of ForallPointerDecay_old. 197 198 struct TraitExpander_old final { 199 void previsit( FunctionType * ); 200 void previsit( StructDecl * ); 201 void previsit( UnionDecl * ); 202 }; 203 204 struct AssertionFixer_old final { 205 void previsit( FunctionType * ); 206 void previsit( StructDecl * ); 207 void previsit( UnionDecl * ); 208 }; 209 210 struct CheckOperatorTypes_old final { 211 void previsit( ObjectDecl * ); 212 }; 213 214 struct FixUniqueIds_old final { 215 void previsit( DeclarationWithType * ); 216 }; 217 196 218 struct ReturnChecker : public WithGuards { 197 219 /// Checks that return statements return nothing if their return type is void … … 386 408 387 409 void validate_D( std::list< Declaration * > & translationUnit ) { 388 PassVisitor<ForallPointerDecay_old> fpd;389 410 { 390 411 Stats::Heap::newPass("validate-D"); … … 394 415 }); 395 416 Stats::Time::TimeBlock("Forall Pointer Decay", [&]() { 396 acceptAll( translationUnit, fpd); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution417 decayForallPointers( translationUnit ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution 397 418 }); 398 419 Stats::Time::TimeBlock("Hoist Control Declarations", [&]() { … … 454 475 455 476 void decayForallPointers( std::list< Declaration * > & translationUnit ) { 456 PassVisitor<ForallPointerDecay_old> fpd; 457 acceptAll( translationUnit, fpd ); 477 PassVisitor<TraitExpander_old> te; 478 acceptAll( translationUnit, te ); 479 PassVisitor<AssertionFixer_old> af; 480 acceptAll( translationUnit, af ); 481 PassVisitor<CheckOperatorTypes_old> cot; 482 acceptAll( translationUnit, cot ); 483 PassVisitor<FixUniqueIds_old> fui; 484 acceptAll( translationUnit, fui ); 485 } 486 487 void decayForallPointersA( std::list< Declaration * > & translationUnit ) { 488 PassVisitor<TraitExpander_old> te; 489 acceptAll( translationUnit, te ); 490 } 491 void decayForallPointersB( std::list< Declaration * > & translationUnit ) { 492 PassVisitor<AssertionFixer_old> af; 493 acceptAll( translationUnit, af ); 494 } 495 void decayForallPointersC( std::list< Declaration * > & translationUnit ) { 496 PassVisitor<CheckOperatorTypes_old> cot; 497 acceptAll( translationUnit, cot ); 498 } 499 void decayForallPointersD( std::list< Declaration * > & translationUnit ) { 500 PassVisitor<FixUniqueIds_old> fui; 501 acceptAll( translationUnit, fui ); 458 502 } 459 503 … … 470 514 PassVisitor<EnumAndPointerDecay_old> epc; 471 515 PassVisitor<LinkReferenceToTypes_old> lrt( indexer ); 472 PassVisitor<ForallPointerDecay_old> fpd; 516 PassVisitor<TraitExpander_old> te; 517 PassVisitor<AssertionFixer_old> af; 518 PassVisitor<CheckOperatorTypes_old> cot; 519 PassVisitor<FixUniqueIds_old> fui; 473 520 type->accept( epc ); 474 521 type->accept( lrt ); 475 type->accept( fpd ); 522 type->accept( te ); 523 type->accept( af ); 524 type->accept( cot ); 525 type->accept( fui ); 476 526 } 477 527 … … 972 1022 } 973 1023 1024 /// Replace all traits in assertion lists with their assertions. 1025 void expandTraits( std::list< TypeDecl * > & forall ) { 1026 for ( TypeDecl * type : forall ) { 1027 std::list< DeclarationWithType * > asserts; 1028 asserts.splice( asserts.end(), type->assertions ); 1029 // expand trait instances into their members 1030 for ( DeclarationWithType * assertion : asserts ) { 1031 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) { 1032 // expand trait instance into all of its members 1033 expandAssertions( traitInst, back_inserter( type->assertions ) ); 1034 delete traitInst; 1035 } else { 1036 // pass other assertions through 1037 type->assertions.push_back( assertion ); 1038 } // if 1039 } // for 1040 } 1041 } 1042 1043 /// Fix each function in the assertion list and check for invalid void type. 1044 void fixAssertions( 1045 std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) { 1046 for ( TypeDecl * type : forall ) { 1047 for ( DeclarationWithType *& assertion : type->assertions ) { 1048 bool isVoid = fixFunction( assertion ); 1049 if ( isVoid ) { 1050 SemanticError( node, "invalid type void in assertion of function " ); 1051 } // if 1052 } // for 1053 } 1054 } 1055 974 1056 void ForallPointerDecay_old::previsit( ObjectDecl * object ) { 975 1057 // ensure that operator names only apply to functions or function pointers … … 994 1076 void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) { 995 1077 forallFixer( aggrDecl->parameters, aggrDecl ); 1078 } 1079 1080 void TraitExpander_old::previsit( FunctionType * ftype ) { 1081 expandTraits( ftype->forall ); 1082 } 1083 1084 void TraitExpander_old::previsit( StructDecl * aggrDecl ) { 1085 expandTraits( aggrDecl->parameters ); 1086 } 1087 1088 void TraitExpander_old::previsit( UnionDecl * aggrDecl ) { 1089 expandTraits( aggrDecl->parameters ); 1090 } 1091 1092 void AssertionFixer_old::previsit( FunctionType * ftype ) { 1093 fixAssertions( ftype->forall, ftype ); 1094 } 1095 1096 void AssertionFixer_old::previsit( StructDecl * aggrDecl ) { 1097 fixAssertions( aggrDecl->parameters, aggrDecl ); 1098 } 1099 1100 void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) { 1101 fixAssertions( aggrDecl->parameters, aggrDecl ); 1102 } 1103 1104 void CheckOperatorTypes_old::previsit( ObjectDecl * object ) { 1105 // ensure that operator names only apply to functions or function pointers 1106 if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) { 1107 SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." ) ); 1108 } 1109 } 1110 1111 void FixUniqueIds_old::previsit( DeclarationWithType * decl ) { 1112 decl->fixUniqueId(); 996 1113 } 997 1114 -
src/SymTab/Validate.h
ref3c383 rd672350 43 43 void validate_F( std::list< Declaration * > &translationUnit ); 44 44 void decayForallPointers( std::list< Declaration * > & translationUnit ); 45 void decayForallPointersA( std::list< Declaration * > & translationUnit ); 46 void decayForallPointersB( std::list< Declaration * > & translationUnit ); 47 void decayForallPointersC( std::list< Declaration * > & translationUnit ); 48 void decayForallPointersD( std::list< Declaration * > & translationUnit ); 45 49 46 50 const ast::Type * validateType( -
src/Tuples/TupleAssignment.cc
ref3c383 rd672350 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 23:45:33 201913 // Update Count : 911 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 14:06:00 2022 13 // Update Count : 10 14 14 // 15 15 … … 465 465 // resolve ctor/dtor for the new object 466 466 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder. localSyms);467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.context ); 468 468 // remove environments from subexpressions of stmtExpr 469 469 ast::Pass< EnvRemover > rm{ env }; … … 560 560 // resolve the cast expression so that rhsCand return type is bound by the cast 561 561 // type as needed, and transfer the resulting environment 562 ResolvExpr::CandidateFinder finder { spotter.crntFinder.localSyms, env };562 ResolvExpr::CandidateFinder finder( spotter.crntFinder.context, env ); 563 563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 564 564 assert( finder.candidates.size() == 1 ); … … 609 609 // explode the LHS so that each field of a tuple-valued expr is assigned 610 610 ResolvExpr::CandidateList lhs; 611 explode( *lhsCand, crntFinder. localSyms, back_inserter(lhs), true );611 explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true ); 612 612 for ( ResolvExpr::CandidateRef & cand : lhs ) { 613 613 // each LHS value must be a reference - some come in with a cast, if not … … 629 629 if ( isTuple( rhsCand->expr ) ) { 630 630 // multiple assignment 631 explode( *rhsCand, crntFinder. localSyms, back_inserter(rhs), true );631 explode( *rhsCand, crntFinder.context.symtab, back_inserter(rhs), true ); 632 632 matcher.reset( 633 633 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 648 648 // multiple assignment 649 649 ResolvExpr::CandidateList rhs; 650 explode( rhsCand, crntFinder. localSyms, back_inserter(rhs), true );650 explode( rhsCand, crntFinder.context.symtab, back_inserter(rhs), true ); 651 651 matcher.reset( 652 652 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 678 678 ) 679 679 680 ResolvExpr::CandidateFinder finder { crntFinder.localSyms, matcher->env };680 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env ); 681 681 682 682 try { -
src/Validate/FindSpecialDeclsNew.cpp
ref3c383 rd672350 30 30 31 31 struct FindDeclsCore : public ast::WithShortCircuiting { 32 ast::Translation Unit::Global & global;33 FindDeclsCore( ast::Translation Unit::Global & g ) : global( g ) {}32 ast::TranslationGlobal & global; 33 FindDeclsCore( ast::TranslationGlobal & g ) : global( g ) {} 34 34 35 35 void previsit( const ast::Decl * decl ); … … 74 74 ast::Pass<FindDeclsCore>::run( translationUnit, translationUnit.global ); 75 75 76 // TODO: When everything gets the globals from the translation unit,77 // remove these.78 ast::dereferenceOperator = translationUnit.global.dereference;79 ast::dtorStruct = translationUnit.global.dtorStruct;80 ast::dtorStructDestroy = translationUnit.global.dtorDestroy;81 82 76 // TODO: conditionally generate 'fake' declarations for missing features, 83 77 // so that translation can proceed in the event that builtins, prelude, -
src/Validate/module.mk
ref3c383 rd672350 20 20 Validate/CompoundLiteral.cpp \ 21 21 Validate/CompoundLiteral.hpp \ 22 Validate/ForallPointerDecay.cpp \ 23 Validate/ForallPointerDecay.hpp \ 22 24 Validate/HandleAttributes.cc \ 23 25 Validate/HandleAttributes.h \ -
src/Virtual/Tables.cc
ref3c383 rd672350 10 10 // Created On : Mon Aug 31 11:11:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 21 15:36:00 2021 13 // Update Count : 2 14 // 15 12 // Last Modified On : Fri Mar 11 10:40:00 2022 13 // Update Count : 3 14 // 15 16 #include "AST/Attribute.hpp" 17 #include "AST/Copy.hpp" 18 #include "AST/Decl.hpp" 19 #include "AST/Expr.hpp" 20 #include "AST/Init.hpp" 21 #include "AST/Stmt.hpp" 22 #include "AST/Type.hpp" 16 23 #include <SynTree/Attribute.h> 17 24 #include <SynTree/Declaration.h> … … 77 84 } 78 85 86 static ast::ObjectDecl * makeVtableDeclaration( 87 CodeLocation const & location, std::string const & name, 88 ast::StructInstType const * type, ast::Init const * init ) { 89 ast::Storage::Classes storage; 90 if ( nullptr == init ) { 91 storage.is_extern = true; 92 } 93 return new ast::ObjectDecl( 94 location, 95 name, 96 type, 97 init, 98 storage, 99 ast::Linkage::Cforall 100 ); 101 } 102 79 103 ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) { 80 104 assert( type ); 81 105 return makeVtableDeclaration( name, type, nullptr ); 106 } 107 108 ast::ObjectDecl * makeVtableForward( 109 CodeLocation const & location, std::string const & name, 110 ast::StructInstType const * vtableType ) { 111 assert( vtableType ); 112 return makeVtableDeclaration( location, name, vtableType, nullptr ); 82 113 } 83 114 … … 123 154 } 124 155 156 static std::vector<ast::ptr<ast::Init>> buildInits( 157 CodeLocation const & location, 158 //std::string const & name, 159 ast::StructInstType const * vtableType, 160 ast::Type const * objectType ) { 161 ast::StructDecl const * vtableStruct = vtableType->base; 162 163 std::vector<ast::ptr<ast::Init>> inits; 164 inits.reserve( vtableStruct->members.size() ); 165 166 // This is designed to run before the resolver. 167 for ( auto field : vtableStruct->members ) { 168 if ( std::string( "parent" ) == field->name ) { 169 // This will not work with polymorphic state. 170 auto oField = field.strict_as<ast::ObjectDecl>(); 171 auto fieldType = oField->type.strict_as<ast::PointerType>(); 172 auto parentType = fieldType->base.strict_as<ast::StructInstType>(); 173 std::string const & parentInstance = instanceName( parentType->name ); 174 inits.push_back( 175 new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) ); 176 } else if ( std::string( "__cfavir_typeid" ) == field->name ) { 177 std::string const & baseType = baseTypeName( vtableType->name ); 178 std::string const & typeId = typeIdName( baseType ); 179 inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) ); 180 } else if ( std::string( "size" ) == field->name ) { 181 inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType ) 182 ) ); 183 } else if ( std::string( "align" ) == field->name ) { 184 inits.push_back( new ast::SingleInit( location, 185 new ast::AlignofExpr( location, objectType ) 186 ) ); 187 } else { 188 inits.push_back( new ast::SingleInit( location, 189 new ast::NameExpr( location, field->name ) 190 ) ); 191 } 192 //ast::Expr * expr = buildInitExpr(...); 193 //inits.push_back( new ast::SingleInit( location, expr ) ) 194 } 195 196 return inits; 197 } 198 199 ast::ObjectDecl * makeVtableInstance( 200 CodeLocation const & location, 201 std::string const & name, 202 ast::StructInstType const * vtableType, 203 ast::Type const * objectType, 204 ast::Init const * init ) { 205 assert( vtableType ); 206 assert( objectType ); 207 208 // Build the initialization. 209 if ( nullptr == init ) { 210 init = new ast::ListInit( location, 211 buildInits( location, vtableType, objectType ) ); 212 213 // The provided init should initialize everything except the parent 214 // pointer, the size-of and align-of fields. These should be inserted. 215 } else { 216 // Except this is not yet supported. 217 assert(false); 218 } 219 return makeVtableDeclaration( location, name, vtableType, init ); 220 } 221 125 222 namespace { 126 223 std::string const functionName = "get_exception_vtable"; … … 140 237 new ReferenceType( noQualifiers, vtableType ), 141 238 nullptr, 142 { new Attribute("unused") }239 { new Attribute("unused") } 143 240 ) ); 144 241 type->parameters.push_back( new ObjectDecl( … … 157 254 type, 158 255 nullptr 256 ); 257 } 258 259 ast::FunctionDecl * makeGetExceptionForward( 260 CodeLocation const & location, 261 ast::Type const * vtableType, 262 ast::Type const * exceptType ) { 263 assert( vtableType ); 264 assert( exceptType ); 265 return new ast::FunctionDecl( 266 location, 267 functionName, 268 { /* forall */ }, 269 { new ast::ObjectDecl( 270 location, 271 "__unused", 272 new ast::PointerType( exceptType ) 273 ) }, 274 { new ast::ObjectDecl( 275 location, 276 "_retvalue", 277 new ast::ReferenceType( vtableType ) 278 ) }, 279 nullptr, 280 ast::Storage::Classes(), 281 ast::Linkage::Cforall, 282 { new ast::Attribute( "unused" ) } 159 283 ); 160 284 } … … 172 296 } 173 297 298 ast::FunctionDecl * makeGetExceptionFunction( 299 CodeLocation const & location, 300 ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) { 301 assert( vtableInstance ); 302 assert( exceptType ); 303 ast::FunctionDecl * func = makeGetExceptionForward( 304 location, ast::deepCopy( vtableInstance->type ), exceptType ); 305 func->stmts = new ast::CompoundStmt( location, { 306 new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) ) 307 } ); 308 return func; 309 } 310 174 311 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) { 175 312 assert( typeIdType ); … … 191 328 } 192 329 193 } 330 ast::ObjectDecl * makeTypeIdInstance( 331 CodeLocation const & location, 332 ast::StructInstType const * typeIdType ) { 333 assert( typeIdType ); 334 ast::StructInstType * type = ast::mutate( typeIdType ); 335 type->set_const( true ); 336 std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name ); 337 return new ast::ObjectDecl( 338 location, 339 typeid_name, 340 type, 341 new ast::ListInit( location, { 342 new ast::SingleInit( location, 343 new ast::AddressExpr( location, 344 new ast::NameExpr( location, "__cfatid_exception_t" ) ) ) 345 } ), 346 ast::Storage::Classes(), 347 ast::Linkage::Cforall, 348 nullptr, 349 { new ast::Attribute( "cfa_linkonce" ) } 350 ); 351 } 352 353 } -
src/Virtual/Tables.h
ref3c383 rd672350 10 10 // Created On : Mon Aug 31 11:07:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : We d Apr 21 10:30:00 202113 // Update Count : 212 // Last Modified On : Wec Dec 8 16:58:00 2021 13 // Update Count : 3 14 14 // 15 15 16 16 #include <list> // for list 17 17 18 #include <string> 19 #include "AST/Fwd.hpp" 18 20 class Declaration; 19 21 class StructDecl; … … 35 37 * vtableType node is consumed. 36 38 */ 39 ast::ObjectDecl * makeVtableForward( 40 CodeLocation const & location, std::string const & name, 41 ast::StructInstType const * vtableType ); 37 42 38 43 ObjectDecl * makeVtableInstance( … … 43 48 * vtableType and init (if provided) nodes are consumed. 44 49 */ 50 ast::ObjectDecl * makeVtableInstance( 51 CodeLocation const & location, 52 std::string const & name, 53 ast::StructInstType const * vtableType, 54 ast::Type const * objectType, 55 ast::Init const * init = nullptr ); 45 56 46 57 // Some special code for how exceptions interact with virtual tables. … … 49 60 * linking the vtableType to the exceptType. Both nodes are consumed. 50 61 */ 62 ast::FunctionDecl * makeGetExceptionForward( 63 CodeLocation const & location, 64 ast::Type const * vtableType, 65 ast::Type const * exceptType ); 51 66 52 67 FunctionDecl * makeGetExceptionFunction( … … 55 70 * exceptType node is consumed. 56 71 */ 72 ast::FunctionDecl * makeGetExceptionFunction( 73 CodeLocation const & location, 74 ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ); 57 75 58 76 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ); … … 60 78 * TODO: Should take the parent type. Currently locked to the exception_t. 61 79 */ 80 ast::ObjectDecl * makeTypeIdInstance( 81 const CodeLocation & location, ast::StructInstType const * typeIdType ); 62 82 63 83 } -
src/main.cc
ref3c383 rd672350 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jan 26 14:09:00 202213 // Update Count : 67 012 // Last Modified On : Fri Mar 11 10:39:00 2022 13 // Update Count : 671 14 14 // 15 15 … … 76 76 #include "Validate/Autogen.hpp" // for autogenerateRoutines 77 77 #include "Validate/FindSpecialDecls.h" // for findGlobalDecls 78 #include "Validate/ForallPointerDecay.hpp" // for decayForallPointers 78 79 #include "Validate/CompoundLiteral.hpp" // for handleCompoundLiterals 79 80 #include "Validate/InitializerLength.hpp" // for setLengthFromInitializer … … 331 332 332 333 if( useNewAST ) { 333 PASS( "Apply Concurrent Keywords", Concurrency::applyKeywords( translationUnit ) );334 PASS( "Forall Pointer Decay", SymTab::decayForallPointers( translationUnit ) );335 334 CodeTools::fillLocations( translationUnit ); 336 335 … … 342 341 343 342 forceFillCodeLocations( transUnit ); 343 344 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 345 346 // Must be after implement concurrent keywords; because uniqueIds 347 // must be set on declaration before resolution. 348 // Must happen before autogen routines are added. 349 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 344 350 345 351 // Must happen before autogen routines are added. … … 487 493 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) ); 488 494 } 489 490 491 495 492 496 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
Note:
See TracChangeset
for help on using the changeset viewer.