Changeset b067d9b for src/ResolvExpr
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (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/ResolvExpr
- Files:
-
- 13 added
- 32 edited
-
AdjustExprType.cc (modified) (6 diffs)
-
Alternative.cc (modified) (7 diffs)
-
Alternative.h (modified) (3 diffs)
-
AlternativeFinder.cc (modified) (61 diffs)
-
AlternativeFinder.h (modified) (4 diffs)
-
Candidate.cpp (added)
-
Candidate.hpp (added)
-
CandidateFinder.cpp (added)
-
CandidateFinder.hpp (added)
-
CastCost.cc (modified) (5 diffs)
-
CommonType.cc (modified) (15 diffs)
-
ConversionCost.cc (modified) (19 diffs)
-
ConversionCost.h (modified) (4 diffs)
-
Cost.h (modified) (2 diffs)
-
CurrentObject.cc (modified) (4 diffs)
-
CurrentObject.h (modified) (2 diffs)
-
ExplodedActual.cc (modified) (2 diffs)
-
ExplodedActual.h (modified) (2 diffs)
-
ExplodedArg.cpp (added)
-
ExplodedArg.hpp (added)
-
FindOpenVars.cc (modified) (7 diffs)
-
FindOpenVars.h (modified) (1 diff)
-
Occurs.cc (modified) (3 diffs)
-
PolyCost.cc (modified) (2 diffs)
-
PtrsAssignable.cc (modified) (5 diffs)
-
PtrsCastable.cc (modified) (6 diffs)
-
RenameVars.cc (modified) (5 diffs)
-
RenameVars.h (modified) (1 diff)
-
ResolvMode.h (added)
-
ResolveAssertions.cc (added)
-
ResolveAssertions.h (added)
-
ResolveTypeof.cc (modified) (4 diffs)
-
ResolveTypeof.h (modified) (1 diff)
-
Resolver.cc (modified) (45 diffs)
-
Resolver.h (modified) (2 diffs)
-
SatisfyAssertions.cpp (added)
-
SatisfyAssertions.hpp (added)
-
SpecCost.cc (added)
-
TypeEnvironment.cc (modified) (13 diffs)
-
TypeEnvironment.h (modified) (8 diffs)
-
Unify.cc (modified) (27 diffs)
-
Unify.h (modified) (3 diffs)
-
WidenMode.h (added)
-
module.mk (modified) (1 diff)
-
typeops.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AdjustExprType.cc
r7951100 rb067d9b 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AdjustExprType .cc --7 // AdjustExprType_old.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 14 14 // 15 15 16 #include "AST/Node.hpp" 17 #include "AST/Pass.hpp" 18 #include "AST/SymbolTable.hpp" 19 #include "AST/Type.hpp" 20 #include "AST/TypeEnvironment.hpp" 16 21 #include "Common/PassVisitor.h" 17 22 #include "SymTab/Indexer.h" // for Indexer … … 22 27 23 28 namespace ResolvExpr { 24 class AdjustExprType : public WithShortCircuiting { 25 public: 26 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 29 30 namespace { 31 class AdjustExprType_old final : public WithShortCircuiting { 32 public: 33 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 27 34 void premutate( VoidType * ) { visit_children = false; } 28 35 void premutate( BasicType * ) { visit_children = false; } … … 40 47 void premutate( OneType * ) { visit_children = false; } 41 48 42 Type * postmutate( ArrayType * arrayType );43 Type * postmutate( FunctionType * functionType );44 Type * postmutate( TypeInstType * aggregateUseType );49 Type * postmutate( ArrayType * arrayType ); 50 Type * postmutate( FunctionType * functionType ); 51 Type * postmutate( TypeInstType * aggregateUseType ); 45 52 46 private:53 private: 47 54 const TypeEnvironment & env; 48 55 const SymTab::Indexer & indexer; 49 56 }; 50 57 51 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 52 PassVisitor<AdjustExprType> adjuster( env, indexer ); 53 Type *newType = type->acceptMutator( adjuster ); 54 type = newType; 55 } 56 57 void adjustExprType( Type *& type ) { 58 TypeEnvironment env; 59 SymTab::Indexer indexer; 60 adjustExprType( type, env, indexer ); 61 } 62 63 AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 58 AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 64 59 : env( env ), indexer( indexer ) { 65 60 } 66 61 67 Type * AdjustExprType ::postmutate( ArrayType * arrayType ) {68 PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };62 Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) { 63 PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base }; 69 64 arrayType->base = nullptr; 70 65 delete arrayType; … … 72 67 } 73 68 74 Type * AdjustExprType ::postmutate( FunctionType * functionType ) {69 Type * AdjustExprType_old::postmutate( FunctionType * functionType ) { 75 70 return new PointerType{ Type::Qualifiers(), functionType }; 76 71 } 77 72 78 Type * AdjustExprType ::postmutate( TypeInstType * typeInst ) {79 if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {73 Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) { 74 if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) { 80 75 if ( eqvClass->data.kind == TypeDecl::Ftype ) { 81 76 return new PointerType{ Type::Qualifiers(), typeInst }; 82 77 } 83 } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {84 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {78 } else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 79 if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) { 85 80 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 86 81 return new PointerType{ Type::Qualifiers(), typeInst }; … … 90 85 return typeInst; 91 86 } 87 } // anonymous namespace 88 89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 90 PassVisitor<AdjustExprType_old> adjuster( env, indexer ); 91 Type * newType = type->acceptMutator( adjuster ); 92 type = newType; 93 } 94 95 void adjustExprType( Type *& type ) { 96 TypeEnvironment env; 97 SymTab::Indexer indexer; 98 adjustExprType( type, env, indexer ); 99 } 100 101 namespace { 102 struct AdjustExprType_new final : public ast::WithShortCircuiting { 103 const ast::TypeEnvironment & tenv; 104 const ast::SymbolTable & symtab; 105 106 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms ) 107 : tenv( e ), symtab( syms ) {} 108 109 void premutate( const ast::VoidType * ) { visit_children = false; } 110 void premutate( const ast::BasicType * ) { visit_children = false; } 111 void premutate( const ast::PointerType * ) { visit_children = false; } 112 void premutate( const ast::ArrayType * ) { visit_children = false; } 113 void premutate( const ast::FunctionType * ) { visit_children = false; } 114 void premutate( const ast::StructInstType * ) { visit_children = false; } 115 void premutate( const ast::UnionInstType * ) { visit_children = false; } 116 void premutate( const ast::EnumInstType * ) { visit_children = false; } 117 void premutate( const ast::TraitInstType * ) { visit_children = false; } 118 void premutate( const ast::TypeInstType * ) { visit_children = false; } 119 void premutate( const ast::TupleType * ) { visit_children = false; } 120 void premutate( const ast::VarArgsType * ) { visit_children = false; } 121 void premutate( const ast::ZeroType * ) { visit_children = false; } 122 void premutate( const ast::OneType * ) { visit_children = false; } 123 124 const ast::Type * postmutate( const ast::ArrayType * at ) { 125 return new ast::PointerType{ at->base, at->qualifiers }; 126 } 127 128 const ast::Type * postmutate( const ast::FunctionType * ft ) { 129 return new ast::PointerType{ ft }; 130 } 131 132 const ast::Type * postmutate( const ast::TypeInstType * inst ) { 133 // replace known function-type-variables with pointer-to-function 134 if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) { 135 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) { 136 return new ast::PointerType{ inst }; 137 } 138 } else if ( const ast::NamedTypeDecl * ntDecl = symtab.lookupType( inst->name ) ) { 139 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( ntDecl ) ) { 140 if ( tyDecl->kind == ast::TypeVar::Ftype ) { 141 return new ast::PointerType{ inst }; 142 } 143 } 144 } 145 return inst; 146 } 147 }; 148 } // anonymous namespace 149 150 const ast::Type * adjustExprType( 151 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 152 ) { 153 ast::Pass<AdjustExprType_new> adjuster{ env, symtab }; 154 return type->accept( adjuster ); 155 } 156 92 157 } // namespace ResolvExpr 93 158 -
src/ResolvExpr/Alternative.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:44:23 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat May 16 23:54:23 201513 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 3 14 14 // 15 15 … … 20 20 #include <utility> // for move 21 21 22 #include "Common/utility.h" // for maybeClone22 #include "Common/utility.h" // for cloneAll 23 23 #include "ResolvExpr/Cost.h" // for Cost, Cost::zero, operator<< 24 24 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment … … 27 27 28 28 namespace ResolvExpr { 29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {} 29 Alternative::Alternative() 30 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {} 30 31 31 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost ) 32 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {} 32 Alternative::Alternative( Expression *expr, const TypeEnvironment &env ) 33 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {} 34 35 Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost ) 36 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ), 37 need() { cloneAll( o.need, need ); } 33 38 34 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost ) 35 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 39 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 40 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost ) 41 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 42 need() { cloneAll( oneed, need ); } 36 43 37 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 } 44 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 45 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost, 46 const Cost &cvtCost ) 47 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 48 need() { cloneAll( oneed, need ); } 49 50 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 51 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost) 52 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 53 need() { cloneAll( oneed, need ); } 54 55 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 56 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost, 57 const Cost& cvtCost ) 58 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 59 need() { cloneAll( oneed, need ); } 60 61 Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 62 AssertionSet &&needSet, const Cost &cost ) 63 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ), 64 openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {} 65 66 Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 67 AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost ) 68 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ), 69 openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {} 70 71 Alternative::Alternative( const Alternative &other ) 72 : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), 73 env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); } 39 74 40 75 Alternative &Alternative::operator=( const Alternative &other ) { … … 45 80 expr = maybeClone( other.expr ); 46 81 env = other.env; 82 openVars = other.openVars; 83 need.clear(); 84 cloneAll( other.need, need ); 47 85 return *this; 48 86 } 49 87 50 Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) { 51 other.expr = nullptr; 52 } 88 Alternative::Alternative( Alternative && other ) 89 : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), 90 env( std::move( other.env ) ), openVars( std::move( other.openVars ) ), 91 need( std::move( other.need ) ) { other.expr = nullptr; } 53 92 54 93 Alternative & Alternative::operator=( Alternative && other ) { … … 59 98 expr = other.expr; 60 99 env = std::move( other.env ); 100 openVars = std::move( other.openVars ); 101 need = std::move( other.need ); 61 102 other.expr = nullptr; 62 103 return *this; … … 64 105 65 106 Alternative::~Alternative() { 107 for ( AssertionItem& n : need ) { delete n.decl; } 66 108 delete expr; 67 109 } … … 78 120 os << "Null expression!" << std::endl; 79 121 } // if 80 os << indent << "Environment: ";122 os << indent << "Environment:"; 81 123 env.print( os, indent+1 ); 82 124 os << std::endl; 83 }84 85 void splice( AltList& dst, AltList& src ) {86 dst.reserve( dst.size() + src.size() );87 for ( Alternative& alt : src ) {88 dst.push_back( std::move(alt) );89 }90 src.clear();91 }92 93 void spliceBegin( AltList& dst, AltList& src ) {94 splice( src, dst );95 dst.swap( src );96 125 } 97 126 -
src/ResolvExpr/Alternative.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:45:43 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:36 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 20 20 21 21 #include "Cost.h" // for Cost 22 #include "TypeEnvironment.h" // for TypeEnvironment 22 #include "TypeEnvironment.h" // for TypeEnvironment, AssertionSetValue 23 24 #include "Common/utility.h" // for maybeClone 23 25 24 26 class Expression; 25 27 26 28 namespace ResolvExpr { 29 /// One assertion to resolve 30 struct AssertionItem { 31 const DeclarationWithType* decl; 32 AssertionSetValue info; 33 34 AssertionItem() = default; 35 AssertionItem( const DeclarationWithType* decl, const AssertionSetValue& info ) 36 : decl(decl), info(info) {} 37 AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {} 38 operator AssertionSet::value_type () const { return { decl, info }; } 39 40 // to support cloneAll 41 AssertionItem clone() const { return { maybeClone(decl), info }; } 42 }; 43 /// A list of unresolved assertions 44 using AssertionList = std::vector<AssertionItem>; 45 46 /// Clones an assertion list into an assertion set 47 static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) { 48 for ( const AssertionItem& item : src ) { 49 dst.emplace( maybeClone(item.decl), item.info ); 50 } 51 } 52 53 /// Clones an assertion set into an assertion list 54 static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) { 55 dst.reserve( dst.size() + src.size() ); 56 for ( const auto& entry : src ) { 57 dst.emplace_back( maybeClone(entry.first), entry.second ); 58 } 59 } 60 61 /// Clones an assertion list into an assertion list 62 static inline void cloneAll( const AssertionList& src, AssertionList& dst ) { 63 dst.reserve( dst.size() + src.size() ); 64 for ( const AssertionItem& item : src ) { 65 dst.emplace_back( maybeClone(item.decl), item.info ); 66 } 67 } 68 69 /// One option for resolution of an expression 27 70 struct Alternative { 28 71 Alternative(); 29 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost ); 30 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost ); 72 Alternative( Expression *expr, const TypeEnvironment &env ); 73 Alternative( const Alternative &o, Expression *expr, const Cost &cost ); 74 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 75 const AssertionList& need, const Cost &cost ); 76 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 77 const AssertionList& need, const Cost &cost, const Cost &cvtCost ); 78 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 79 const AssertionSet &need, const Cost &cost); 80 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 81 const AssertionSet &need, const Cost &cost, const Cost& cvtCost ); 82 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 83 AssertionSet &&need, const Cost &cost ); 84 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 85 AssertionSet &&need, const Cost &cost, const Cost &cvtCost ); 31 86 Alternative( const Alternative &other ); 32 87 Alternative &operator=( const Alternative &other ); … … 44 99 } 45 100 46 Cost cost; 47 Cost cvtCost; 48 Expression *expr; 49 TypeEnvironment env; 101 /// Sorts by cost 102 bool operator< ( const Alternative& o ) const { return cost < o.cost; } 103 104 Cost cost; ///< Cost of the whole expression 105 Cost cvtCost; ///< Cost of conversions to the satisfying expression 106 Expression *expr; ///< Satisfying expression 107 TypeEnvironment env; ///< Containing type environment 108 OpenVarSet openVars; ///< Open variables for environment 109 AssertionList need; ///< Assertions which need to be resolved 50 110 }; 51 111 52 112 typedef std::vector< Alternative > AltList; 53 54 /// Moves all elements from src to the end of dst55 void splice( AltList& dst, AltList& src );56 57 /// Moves all elements from src to the beginning of dst58 void spliceBegin( AltList& dst, AltList& src );59 113 60 114 static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) { -
src/ResolvExpr/AlternativeFinder.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:52:08 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 17 11:19:39 201813 // Update Count : 3 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Aug 8 16:35:00 2019 13 // Update Count : 38 14 14 // 15 15 … … 25 25 #include <vector> // for vector 26 26 27 #include "CompilationState.h" // for resolvep 27 28 #include "Alternative.h" // for AltList, Alternative 28 29 #include "AlternativeFinder.h" 30 #include "AST/Expr.hpp" 31 #include "AST/SymbolTable.hpp" 32 #include "AST/Type.hpp" 29 33 #include "Common/SemanticError.h" // for SemanticError 30 34 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation … … 33 37 #include "InitTweak/InitTweak.h" // for getFunctionName 34 38 #include "RenameVars.h" // for RenameVars, global_renamer 39 #include "ResolveAssertions.h" // for resolveAssertions 35 40 #include "ResolveTypeof.h" // for resolveTypeof 36 41 #include "Resolver.h" // for resolveStmtExpr … … 49 54 #include "typeops.h" // for adjustExprType, polyCost, castCost 50 55 51 extern bool resolvep;52 56 #define PRINT( text ) if ( resolvep ) { text } 53 57 //#define DEBUG_COST 54 55 using std::move;56 57 /// copies any copyable type58 template<typename T>59 T copy(const T& x) { return x; }60 58 61 59 namespace ResolvExpr { … … 81 79 void postvisit( OffsetofExpr * offsetofExpr ); 82 80 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr );84 81 void postvisit( LogicalExpr * logicalExpr ); 85 82 void postvisit( ConditionalExpr * conditionalExpr ); … … 102 99 void addAnonConversions( const Alternative & alt ); 103 100 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );101 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name ); 105 102 /// Adds alternatives for member expressions where the left side has tuple type 106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression *member );103 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ); 107 104 /// Adds alternatives for offsetof expressions, given the base type and name of the member 108 105 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 112 109 /// Finds matching alternatives for a function, given a set of arguments 113 110 template<typename OutputIterator> 114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs & args, OutputIterator out );115 /// Checks if assertion parameters match for a newalternative111 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out ); 112 /// Sets up parameter inference for an output alternative 116 113 template< typename OutputIterator > 117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );114 void inferParameters( Alternative &newAlt, OutputIterator out ); 118 115 private: 119 116 AlternativeFinder & altFinder; … … 133 130 134 131 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) { 135 Indenter indent = { Indenter::tabsize,indentAmt };132 Indenter indent = { indentAmt }; 136 133 for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) { 137 134 i->print( os, indent ); … … 176 173 selected[ mangleName ] = current; 177 174 } else if ( candidate->cost == mapPlace->second.candidate->cost ) { 178 PRINT( 179 std::cerr << "marking ambiguous" << std::endl; 180 ) 181 mapPlace->second.isAmbiguous = true; 175 // if one of the candidates contains a deleted identifier, can pick the other, since 176 // deleted expressions should not be ambiguous if there is another option that is at least as good 177 if ( findDeletedExpr( candidate->expr ) ) { 178 // do nothing 179 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 180 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) { 181 PRINT( std::cerr << "current is deleted" << std::endl; ) 182 selected[ mangleName ] = current; 183 } else { 184 PRINT( 185 std::cerr << "marking ambiguous" << std::endl; 186 ) 187 mapPlace->second.isAmbiguous = true; 188 } 182 189 } else { 183 190 PRINT( … … 234 241 } 235 242 236 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast) {243 void AlternativeFinder::find( Expression *expr, ResolvMode mode ) { 237 244 PassVisitor<Finder> finder( *this ); 238 245 expr->accept( finder ); 239 if ( failFast && alternatives.empty() ) {246 if ( mode.failFast && alternatives.empty() ) { 240 247 PRINT( 241 248 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 243 250 SemanticError( expr, "No reasonable alternatives for expression " ); 244 251 } 245 if ( prune ) { 252 if ( mode.satisfyAssns || mode.prune ) { 253 // trim candidates just to those where the assertions resolve 254 // - necessary pre-requisite to pruning 255 AltList candidates; 256 std::list<std::string> errors; 257 for ( unsigned i = 0; i < alternatives.size(); ++i ) { 258 resolveAssertions( alternatives[i], indexer, candidates, errors ); 259 } 260 // fail early if none such 261 if ( mode.failFast && candidates.empty() ) { 262 std::ostringstream stream; 263 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 264 // << "Alternatives with failing assertions are:\n"; 265 // printAlts( alternatives, stream, 1 ); 266 for ( const auto& err : errors ) { 267 stream << err; 268 } 269 SemanticError( expr->location, stream.str() ); 270 } 271 // reset alternatives 272 alternatives = std::move( candidates ); 273 } 274 if ( mode.prune ) { 246 275 auto oldsize = alternatives.size(); 247 276 PRINT( … … 251 280 AltList pruned; 252 281 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 253 if ( failFast && pruned.empty() ) {282 if ( mode.failFast && pruned.empty() ) { 254 283 std::ostringstream stream; 255 284 AltList winners; … … 270 299 } 271 300 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 272 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i) {273 if ( adjust) {274 adjustExprType( i ->expr->get_result(), i->env, indexer );301 if ( mode.adjust ) { 302 for ( Alternative& i : alternatives ) { 303 adjustExprType( i.expr->get_result(), i.env, indexer ); 275 304 } 276 305 } … … 284 313 285 314 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 286 find( expr, true);315 find( expr, ResolvMode::withAdjustment() ); 287 316 } 288 317 289 318 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 290 find( expr, true, false);319 find( expr, ResolvMode::withoutPrune() ); 291 320 } 292 321 293 322 void AlternativeFinder::maybeFind( Expression * expr ) { 294 find( expr, true, true, false);323 find( expr, ResolvMode::withoutFailFast() ); 295 324 } 296 325 … … 306 335 } 307 336 308 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {309 addAggMembers( structInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );310 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {311 addAggMembers( unionInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );337 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 338 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 339 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 340 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 312 341 } // if 313 342 } 314 343 315 344 template< typename StructOrUnionType > 316 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) { 317 346 std::list< Declaration* > members; 318 347 aggInst->lookup( name, members ); 319 348 320 349 for ( Declaration * decl : members ) { 321 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {350 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 322 351 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 323 352 // can't construct in place and use vector::back 324 Alternative newAlt ( new MemberExpr( dwt, expr->clone() ), env, newCost );353 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost }; 325 354 renameTypes( newAlt.expr ); 326 355 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 332 361 } 333 362 334 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {363 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) { 335 364 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 336 365 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning 337 // xxx - this should be improved by memoizing the value of constant exprs 338 // during parsing and reusing that information here. 339 std::stringstream ss( constantExpr->get_constant()->get_value() ); 340 int val = 0; 366 auto val = constantExpr->intValue(); 341 367 std::string tmp; 342 if ( ss >> val && ! (ss >> tmp) ) { 343 if ( val >= 0 && (unsigned int)val < tupleType->size() ) { 344 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 345 } // if 368 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 346 371 } // if 347 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {348 // xxx - temporary hack until 0/1 are int constants349 if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {350 std::stringstream ss( nameExpr->get_name() );351 int val;352 ss >> val;353 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );354 }355 372 } // if 356 373 } 357 374 358 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 359 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 360 } 361 362 Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 375 void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) { 376 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 377 } 378 379 Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue, 380 const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 363 381 PRINT( 364 382 std::cerr << std::endl << "converting "; … … 370 388 std::cerr << std::endl; 371 389 ) 372 Cost convCost = conversionCost( actualType, formalType, indexer, env );390 Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env ); 373 391 PRINT( 374 392 std::cerr << std::endl << "cost is " << convCost << std::endl; … … 385 403 386 404 Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 387 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env ); 405 Cost convCost = computeConversionCost( 406 actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env ); 388 407 389 408 // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion. … … 413 432 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 414 433 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 415 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());416 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());434 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 435 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 417 436 418 437 Cost convCost = Cost::zero; 419 std::list< DeclarationWithType* >& formals = function-> get_parameters();438 std::list< DeclarationWithType* >& formals = function->parameters; 420 439 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 421 std::list< Expression* >& actuals = appExpr-> get_args();422 423 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr) {424 Type * actualType = (*actualExpr)->get_result();440 std::list< Expression* >& actuals = appExpr->args; 441 442 for ( Expression*& actualExpr : actuals ) { 443 Type * actualType = actualExpr->result; 425 444 PRINT( 426 445 std::cerr << "actual expression:" << std::endl; 427 (*actualExpr)->print( std::cerr, 8 );446 actualExpr->print( std::cerr, 8 ); 428 447 std::cerr << "--- results are" << std::endl; 429 448 actualType->print( std::cerr, 8 ); 430 449 ) 431 450 if ( formal == formals.end() ) { 432 if ( function-> get_isVarArgs()) {451 if ( function->isVarArgs ) { 433 452 convCost.incUnsafe(); 434 453 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 435 454 // convert reference-typed expressions to value-typed expressions 436 referenceToRvalueConversion( *actualExpr, convCost );455 referenceToRvalueConversion( actualExpr, convCost ); 437 456 continue; 438 457 } else { … … 440 459 } 441 460 } 461 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) { 462 // default arguments should be free - don't include conversion cost. 463 // Unwrap them here because they are not relevant to the rest of the system. 464 actualExpr = def->expr; 465 ++formal; 466 continue; 467 } 468 // mark conversion cost to formal and also specialization cost of formal type 442 469 Type * formalType = (*formal)->get_type(); 443 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 470 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 471 convCost.decSpec( specCost( formalType ) ); 444 472 ++formal; // can't be in for-loop update because of the continue 445 473 } … … 448 476 } 449 477 450 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 451 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 478 // specialization cost of return types can't be accounted for directly, it disables 479 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 480 // 481 // forall(otype OS) { 482 // void ?|?(OS&, int); // with newline 483 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 484 // } 485 486 // mark type variable and specialization cost of forall clause 487 convCost.incVar( function->forall.size() ); 488 for ( TypeDecl* td : function->forall ) { 489 convCost.decSpec( td->assertions.size() ); 452 490 } 453 491 … … 462 500 needAssertions[ *assert ].isUsed = true; 463 501 } 464 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 465 } 466 } 467 468 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 469 470 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 471 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 472 if ( i->second.isUsed ) { 473 indexer.addId( i->first ); 474 } 475 } 476 } 477 478 template< typename ForwardIterator, typename OutputIterator > 479 void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) { 480 if ( begin == end ) { 481 if ( newNeed.empty() ) { 482 PRINT( 483 std::cerr << "all assertions satisfied, output alternative: "; 484 newAlt.print( std::cerr ); 485 std::cerr << std::endl; 486 ); 487 *out++ = newAlt; 488 return; 489 } else if ( level >= recursionLimit ) { 490 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 491 } else { 492 AssertionSet newerNeed; 493 PRINT( 494 std::cerr << "recursing with new set:" << std::endl; 495 printAssertionSet( newNeed, std::cerr, 8 ); 496 ) 497 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 498 return; 499 } 500 } 501 502 ForwardIterator cur = begin++; 503 if ( ! cur->second.isUsed ) { 504 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 505 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 506 } 507 DeclarationWithType *curDecl = cur->first; 508 509 PRINT( 510 std::cerr << "inferRecursive: assertion is "; 511 curDecl->print( std::cerr ); 512 std::cerr << std::endl; 513 ) 514 std::list< SymTab::Indexer::IdData > candidates; 515 decls.lookupId( curDecl->get_name(), candidates ); 516 /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 517 for ( const auto & data : candidates ) { 518 DeclarationWithType * candidate = data.id; 519 PRINT( 520 std::cerr << "inferRecursive: candidate is "; 521 candidate->print( std::cerr ); 522 std::cerr << std::endl; 523 ) 524 525 AssertionSet newHave, newerNeed( newNeed ); 526 TypeEnvironment newEnv( newAlt.env ); 527 OpenVarSet newOpenVars( openVars ); 528 Type *adjType = candidate->get_type()->clone(); 529 adjustExprType( adjType, newEnv, indexer ); 530 renameTyVars( adjType ); 531 PRINT( 532 std::cerr << "unifying "; 533 curDecl->get_type()->print( std::cerr ); 534 std::cerr << " with "; 535 adjType->print( std::cerr ); 536 std::cerr << std::endl; 537 ) 538 if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 539 PRINT( 540 std::cerr << "success!" << std::endl; 541 ) 542 SymTab::Indexer newDecls( decls ); 543 addToIndexer( newHave, newDecls ); 544 Alternative newerAlt( newAlt ); 545 newerAlt.env = newEnv; 546 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 547 548 // everything with an empty idChain was pulled in by the current assertion. 549 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 550 for ( auto & a : newerNeed ) { 551 if ( a.second.idChain.empty() ) { 552 a.second.idChain = cur->second.idChain; 553 a.second.idChain.push_back( curDecl->get_uniqueId() ); 554 } 555 } 556 557 Expression *varExpr = data.combine( newerAlt.cvtCost ); 558 delete varExpr->get_result(); 559 varExpr->set_result( adjType->clone() ); 560 PRINT( 561 std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 562 curDecl->print( std::cerr ); 563 std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 564 candidate->print( std::cerr ); 565 std::cerr << std::endl; 566 ) 567 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter). 568 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 569 for ( UniqueId id : cur->second.idChain ) { 570 inferParameters = (*inferParameters)[ id ].inferParams.get(); 571 } 572 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 573 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 574 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 575 } else { 576 delete adjType; 577 } 578 } 579 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp) 506 extern UniqueId globalResnSlot; 580 507 581 508 template< typename OutputIterator > 582 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 583 // PRINT( 584 // std::cerr << "inferParameters: assertions needed are" << std::endl; 585 // printAll( need, std::cerr, 8 ); 586 // ) 587 SymTab::Indexer decls( indexer ); 588 // PRINT( 589 // std::cerr << "============= original indexer" << std::endl; 590 // indexer.print( std::cerr ); 591 // std::cerr << "============= new indexer" << std::endl; 592 // decls.print( std::cerr ); 593 // ) 594 addToIndexer( have, decls ); 595 AssertionSet newNeed; 596 PRINT( 597 std::cerr << "env is: " << std::endl; 598 newAlt.env.print( std::cerr, 0 ); 599 std::cerr << std::endl; 600 ) 601 602 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 603 // PRINT( 604 // std::cerr << "declaration 14 is "; 605 // Declaration::declFromId 606 // *out++ = newAlt; 607 // ) 509 void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) { 510 // Set need bindings for any unbound assertions 511 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 512 for ( auto& assn : newAlt.need ) { 513 // skip already-matched assertions 514 if ( assn.info.resnSlot != 0 ) continue; 515 // assign slot for expression if needed 516 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 517 // fix slot to assertion 518 assn.info.resnSlot = crntResnSlot; 519 } 520 // pair slot to expression 521 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); } 522 523 // add to output list, assertion resolution is deferred 524 *out++ = newAlt; 608 525 } 609 526 … … 611 528 ConstantExpr* getDefaultValue( Initializer* init ) { 612 529 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 613 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 614 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 530 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) { 531 return dynamic_cast<ConstantExpr*>( ce->arg ); 532 } else { 533 return dynamic_cast<ConstantExpr*>( si->value ); 615 534 } 616 535 } … … 659 578 660 579 /// Gets the list of exploded alternatives for this pack 661 const ExplodedActual& getExpl( const ExplodedArgs & args ) const {580 const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const { 662 581 return args[nextArg-1][explAlt]; 663 582 } … … 683 602 /// Instantiates an argument to match a formal, returns false if no results left 684 603 bool instantiateArgument( Type* formalType, Initializer* initializer, 685 const ExplodedArgs & args, std::vector<ArgPack>& results, std::size_t& genStart,604 const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart, 686 605 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 687 606 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 873 792 indexer ) ) { 874 793 results.emplace_back( 875 i, cnstExpr, move(env), move(need), move(have),794 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have), 876 795 move(openVars), nextArg, nTuples ); 877 796 } … … 944 863 } 945 864 // build and validate new alternative 946 Alternative newAlt ( appExpr, result.env, cost );865 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost }; 947 866 PRINT( 948 867 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 950 869 printAssertionSet( result.need, std::cerr, 8 ); 951 870 ) 952 inferParameters( result.need, result.have, newAlt, result.openVars, out );871 inferParameters( newAlt, out ); 953 872 } 954 873 955 874 template<typename OutputIterator> 956 875 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 957 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {876 FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) { 958 877 OpenVarSet funcOpenVars; 959 878 AssertionSet funcNeed, funcHave; … … 1065 984 funcFinder.findWithAdjustment( untypedExpr->function ); 1066 985 // if there are no function alternatives, then proceeding is a waste of time. 986 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary. 1067 987 if ( funcFinder.alternatives.empty() ) return; 1068 988 … … 1086 1006 1087 1007 // pre-explode arguments 1088 ExplodedArgs argExpansions;1008 ExplodedArgs_old argExpansions; 1089 1009 argExpansions.reserve( argAlternatives.size() ); 1090 1010 … … 1092 1012 argExpansions.emplace_back(); 1093 1013 auto& argE = argExpansions.back(); 1094 argE.reserve( arg.alternatives.size() );1014 // argE.reserve( arg.alternatives.size() ); 1095 1015 1096 1016 for ( const Alternative& actual : arg ) { … … 1178 1098 std::cerr << "bindings are:" << std::endl; 1179 1099 withFunc.env.print( std::cerr, 8 ); 1100 std::cerr << "cost is: " << withFunc.cost << std::endl; 1180 1101 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1181 1102 ) … … 1193 1114 1194 1115 // function may return struct or union value, in which case we need to add alternatives 1195 // for implicit conversions to each of the anonymous members, must happen after findMinCost1116 // for implicit conversions to each of the anonymous members, must happen after findMinCost 1196 1117 // since anon conversions are never the cheapest expression 1197 1118 for ( const Alternative & alt : winners ) { … … 1216 1137 bool isLvalue( Expression *expr ) { 1217 1138 // xxx - recurse into tuples? 1218 return expr->result && ( expr-> result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );1139 return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) ); 1219 1140 } 1220 1141 … … 1225 1146 if ( isLvalue( alt.expr ) ) { 1226 1147 alternatives.push_back( 1227 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } ); 1228 1149 } // if 1229 1150 } // for … … 1231 1152 1232 1153 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1233 alternatives.push_back( Alternative{ expr->clone(), env , Cost::zero} );1154 alternatives.push_back( Alternative{ expr->clone(), env } ); 1234 1155 } 1235 1156 … … 1267 1188 assert( toType ); 1268 1189 toType = resolveTypeof( toType, indexer ); 1190 assert(!dynamic_cast<TypeofType *>(toType)); 1269 1191 SymTab::validateType( toType, &indexer ); 1270 1192 adjustExprType( toType, env, indexer ); … … 1276 1198 AltList candidates; 1277 1199 for ( Alternative & alt : finder.alternatives ) { 1278 AssertionSet needAssertions, haveAssertions; 1279 OpenVarSet openVars; 1200 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1201 AssertionSet haveAssertions; 1202 OpenVarSet openVars{ alt.openVars }; 1280 1203 1281 1204 alt.env.extractOpenVars( openVars ); … … 1292 1215 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1293 1216 haveAssertions, openVars, indexer ); 1294 Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,1295 alt.env );1217 Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), 1218 indexer, alt.env ); 1296 1219 PRINT( 1297 1220 std::cerr << "working on cast with result: " << castExpr->result << std::endl; … … 1305 1228 // count one safe conversion for each value that is thrown away 1306 1229 thisCost.incSafe( discardedValues ); 1307 Alternative newAlt ( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,1308 alt.cost, thisCost );1309 inferParameters( needAssertions, haveAssertions, newAlt, openVars,1310 back_inserter( candidates ) );1230 Alternative newAlt{ 1231 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1232 alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost }; 1233 inferParameters( newAlt, back_inserter( candidates ) ); 1311 1234 } // if 1312 1235 } // for … … 1321 1244 1322 1245 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1323 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1246 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1324 1247 AlternativeFinder finder( indexer, env ); 1325 1248 // don't prune here, since it's guaranteed all alternatives will have the same type 1326 1249 finder.findWithoutPrune( castExpr->get_arg() ); 1327 1250 for ( Alternative & alt : finder.alternatives ) { 1328 alternatives.push_back( Alternative (1329 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),1330 alt. env, alt.cost ));1251 alternatives.push_back( Alternative{ 1252 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1253 alt.cost } ); 1331 1254 } 1332 1255 } … … 1335 1258 /// Gets name from untyped member expression (member must be NameExpr) 1336 1259 const std::string& get_member_name( UntypedMemberExpr *memberExpr ) { 1260 if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) { 1261 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 1262 } // if 1337 1263 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1338 1264 assert( nameExpr ); … … 1353 1279 // find member of the given type 1354 1280 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1355 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1281 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1356 1282 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1357 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1283 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1358 1284 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1359 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1285 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1360 1286 } // if 1361 1287 } // for … … 1363 1289 1364 1290 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1365 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1291 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1366 1292 } 1367 1293 … … 1376 1302 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1377 1303 // can't construct in place and use vector::back 1378 Alternative newAlt ( newExpr, env, Cost::zero, cost );1304 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1379 1305 PRINT( 1380 1306 std::cerr << "decl is "; … … 1394 1320 // not sufficient to clone here, because variable's type may have changed 1395 1321 // since the VariableExpr was originally created. 1396 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1322 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1397 1323 } 1398 1324 1399 1325 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1400 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1326 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1401 1327 } 1402 1328 … … 1404 1330 if ( sizeofExpr->get_isType() ) { 1405 1331 Type * newType = sizeofExpr->get_type()->clone(); 1406 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1332 alternatives.push_back( Alternative{ 1333 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1407 1334 } else { 1408 1335 // find all alternatives for the argument to sizeof … … 1418 1345 Alternative &choice = winners.front(); 1419 1346 referenceToRvalueConversion( choice.expr, choice.cost ); 1420 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1347 alternatives.push_back( Alternative{ 1348 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1421 1349 } // if 1422 1350 } … … 1425 1353 if ( alignofExpr->get_isType() ) { 1426 1354 Type * newType = alignofExpr->get_type()->clone(); 1427 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1355 alternatives.push_back( Alternative{ 1356 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1428 1357 } else { 1429 1358 // find all alternatives for the argument to sizeof … … 1439 1368 Alternative &choice = winners.front(); 1440 1369 referenceToRvalueConversion( choice.expr, choice.cost ); 1441 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1370 alternatives.push_back( Alternative{ 1371 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1442 1372 } // if 1443 1373 } … … 1449 1379 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1450 1380 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1451 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1381 alternatives.push_back( Alternative{ 1382 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1452 1383 renameTypes( alternatives.back().expr ); 1453 1384 } else { … … 1468 1399 1469 1400 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1470 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1401 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1471 1402 } 1472 1403 1473 1404 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1474 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1475 } 1476 1477 namespace { 1478 void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) { 1479 // assume no polymorphism 1480 // assume no implicit conversions 1481 assert( function->get_parameters().size() == 1 ); 1482 PRINT( 1483 std::cerr << "resolvAttr: funcDecl is "; 1484 data.id->print( std::cerr ); 1485 std::cerr << " argType is "; 1486 argType->print( std::cerr ); 1487 std::cerr << std::endl; 1488 ) 1489 const SymTab::Indexer & indexer = finder.get_indexer(); 1490 AltList & alternatives = finder.get_alternatives(); 1491 if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) { 1492 Cost cost = Cost::zero; 1493 Expression * newExpr = data.combine( cost ); 1494 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1495 for ( DeclarationWithType * retVal : function->returnVals ) { 1496 alternatives.back().expr->result = retVal->get_type()->clone(); 1497 } // for 1498 } // if 1499 } 1500 } 1501 1502 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1503 // assume no 'pointer-to-attribute' 1504 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); 1505 assert( nameExpr ); 1506 std::list< SymTab::Indexer::IdData > attrList; 1507 indexer.lookupId( nameExpr->get_name(), attrList ); 1508 if ( attrExpr->get_isType() || attrExpr->get_expr() ) { 1509 for ( auto & data : attrList ) { 1510 DeclarationWithType * id = data.id; 1511 // check if the type is function 1512 if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) { 1513 // assume exactly one parameter 1514 if ( function->get_parameters().size() == 1 ) { 1515 if ( attrExpr->get_isType() ) { 1516 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1517 } else { 1518 AlternativeFinder finder( indexer, env ); 1519 finder.find( attrExpr->get_expr() ); 1520 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1521 if ( choice->expr->get_result()->size() == 1 ) { 1522 resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder ); 1523 } // fi 1524 } // for 1525 } // if 1526 } // if 1527 } // if 1528 } // for 1529 } else { 1530 for ( auto & data : attrList ) { 1531 Cost cost = Cost::zero; 1532 Expression * newExpr = data.combine( cost ); 1533 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1534 renameTypes( alternatives.back().expr ); 1535 } // for 1536 } // if 1537 } 1538 1539 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1405 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1406 } 1407 1408 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) { 1540 1409 AlternativeFinder firstFinder( indexer, env ); 1541 1410 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1546 1415 for ( const Alternative & first : firstFinder.alternatives ) { 1547 1416 for ( const Alternative & second : secondFinder.alternatives ) { 1548 TypeEnvironment compositeEnv; 1549 compositeEnv.simpleCombine( first.env ); 1417 TypeEnvironment compositeEnv{ first.env }; 1550 1418 compositeEnv.simpleCombine( second.env ); 1551 1552 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1553 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1419 OpenVarSet openVars{ first.openVars }; 1420 mergeOpenVars( openVars, second.openVars ); 1421 AssertionSet need; 1422 cloneAll( first.need, need ); 1423 cloneAll( second.need, need ); 1424 1425 LogicalExpr *newExpr = new LogicalExpr{ 1426 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1427 alternatives.push_back( Alternative{ 1428 newExpr, std::move(compositeEnv), std::move(openVars), 1429 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1554 1430 } 1555 1431 } … … 1572 1448 for ( const Alternative & second : secondFinder.alternatives ) { 1573 1449 for ( const Alternative & third : thirdFinder.alternatives ) { 1574 TypeEnvironment compositeEnv; 1575 compositeEnv.simpleCombine( first.env ); 1450 TypeEnvironment compositeEnv{ first.env }; 1576 1451 compositeEnv.simpleCombine( second.env ); 1577 1452 compositeEnv.simpleCombine( third.env ); 1453 OpenVarSet openVars{ first.openVars }; 1454 mergeOpenVars( openVars, second.openVars ); 1455 mergeOpenVars( openVars, third.openVars ); 1456 AssertionSet need; 1457 cloneAll( first.need, need ); 1458 cloneAll( second.need, need ); 1459 cloneAll( third.need, need ); 1460 AssertionSet have; 1578 1461 1579 1462 // unify true and false types, then infer parameters to produce new alternatives 1580 OpenVarSet openVars;1581 AssertionSet needAssertions, haveAssertions;1582 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );1583 1463 Type* commonType = nullptr; 1584 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1585 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1464 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1465 need, have, openVars, indexer, commonType ) ) { 1466 ConditionalExpr *newExpr = new ConditionalExpr{ 1467 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1586 1468 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1587 1469 // convert both options to the conditional result type 1588 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1589 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1590 newAlt.expr = newExpr; 1591 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1470 Cost cost = first.cost + second.cost + third.cost; 1471 cost += computeExpressionConversionCost( 1472 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1473 cost += computeExpressionConversionCost( 1474 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1475 // output alternative 1476 Alternative newAlt{ 1477 newExpr, std::move(compositeEnv), std::move(openVars), 1478 AssertionList( need.begin(), need.end() ), cost }; 1479 inferParameters( newAlt, back_inserter( alternatives ) ); 1592 1480 } // if 1593 1481 } // for … … 1602 1490 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1603 1491 for ( const Alternative & alt : secondFinder.alternatives ) { 1604 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1492 alternatives.push_back( Alternative{ 1493 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1605 1494 } // for 1606 1495 delete newFirstArg; … … 1617 1506 for ( const Alternative & first : firstFinder.alternatives ) { 1618 1507 for ( const Alternative & second : secondFinder.alternatives ) { 1619 TypeEnvironment compositeEnv; 1620 compositeEnv.simpleCombine( first.env ); 1508 TypeEnvironment compositeEnv{ first.env }; 1621 1509 compositeEnv.simpleCombine( second.env ); 1622 OpenVarSet openVars; 1623 AssertionSet needAssertions, haveAssertions; 1624 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1510 OpenVarSet openVars{ first.openVars }; 1511 mergeOpenVars( openVars, second.openVars ); 1512 AssertionSet need; 1513 cloneAll( first.need, need ); 1514 cloneAll( second.need, need ); 1515 AssertionSet have; 1516 1625 1517 Type* commonType = nullptr; 1626 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1627 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1518 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1519 openVars, indexer, commonType ) ) { 1520 RangeExpr * newExpr = 1521 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1628 1522 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1629 newAlt.expr = newExpr; 1630 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1523 Alternative newAlt{ 1524 newExpr, std::move(compositeEnv), std::move(openVars), 1525 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1526 inferParameters( newAlt, back_inserter( alternatives ) ); 1631 1527 } // if 1632 1528 } // for … … 1646 1542 1647 1543 TypeEnvironment compositeEnv; 1648 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1649 alternatives.push_back( 1650 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1544 OpenVarSet openVars; 1545 AssertionSet need; 1546 for ( const Alternative& alt : alts ) { 1547 compositeEnv.simpleCombine( alt.env ); 1548 mergeOpenVars( openVars, alt.openVars ); 1549 cloneAll( alt.need, need ); 1550 } 1551 1552 alternatives.push_back( Alternative{ 1553 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1554 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1651 1555 } // for 1652 1556 } 1653 1557 1654 1558 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1655 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1559 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1656 1560 } 1657 1561 1658 1562 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1659 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1563 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1660 1564 } 1661 1565 … … 1666 1570 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1667 1571 for ( Alternative & alt : finder.alternatives ) { 1668 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1572 alternatives.push_back( Alternative{ 1573 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1669 1574 } 1670 1575 } 1671 1576 1672 1577 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1673 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1578 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1674 1579 } 1675 1580 1676 1581 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1677 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1582 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1678 1583 } 1679 1584 … … 1684 1589 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1685 1590 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1686 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1591 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1687 1592 } 1688 1593 } … … 1692 1597 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1693 1598 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1694 alternatives.push_back( Alternative ( newStmtExpr, env, Cost::zero ));1599 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1695 1600 } 1696 1601 … … 1714 1619 for ( Alternative & alt : finder.get_alternatives() ) { 1715 1620 TypeEnvironment newEnv( alt.env ); 1716 AssertionSet needAssertions, haveAssertions; 1717 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1621 AssertionSet need; 1622 cloneAll( alt.need, need ); 1623 AssertionSet have; 1624 OpenVarSet openVars( alt.openVars ); 1625 // xxx - find things in env that don't have a "representative type" and claim 1626 // those are open vars? 1718 1627 PRINT( 1719 1628 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1720 1629 ) 1721 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1722 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1723 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1724 // to. 1630 // It's possible that a cast can throw away some values in a multiply-valued 1631 // expression. (An example is a cast-to-void, which casts from one value to 1632 // zero.) Figure out the prefix of the subexpression results that are cast 1633 // directly. The candidate is invalid if it has fewer results than there are 1634 // types to cast to. 1725 1635 int discardedValues = alt.expr->result->size() - toType->size(); 1726 1636 if ( discardedValues < 0 ) continue; 1727 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1728 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1637 // xxx - may need to go into tuple types and extract relevant types and use 1638 // unifyList. Note that currently, this does not allow casting a tuple to an 1639 // atomic type (e.g. (int)([1, 2, 3])) 1640 1729 1641 // unification run for side-effects 1730 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1731 1732 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); 1642 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1643 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1644 1645 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(), 1646 indexer, newEnv ); 1733 1647 if ( thisCost != Cost::infinity ) { 1734 1648 // count one safe conversion for each value that is thrown away 1735 1649 thisCost.incSafe( discardedValues ); 1736 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1737 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1650 Alternative newAlt{ 1651 new InitExpr{ 1652 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1653 std::move(newEnv), std::move(openVars), 1654 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1655 inferParameters( newAlt, back_inserter( candidates ) ); 1738 1656 } 1739 1657 } -
src/ResolvExpr/AlternativeFinder.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:56:12 2015 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Wed Jul 26 11:24:00 201713 // Update Count : 411 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Oct -5 10:01:00 2018 13 // Update Count : 5 14 14 // 15 15 … … 24 24 #include "ResolvExpr/Cost.h" // for Cost, Cost::infinity 25 25 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 26 #include "ResolvMode.h" // for ResolvMode 26 27 #include "SynTree/Visitor.h" // for Visitor 27 28 #include "SynTree/SynTree.h" // for Visitor Nodes … … 36 37 /// First index is which argument, second index is which alternative for that argument, 37 38 /// third index is which exploded element of that alternative 38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;39 using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >; 39 40 40 41 class AlternativeFinder { … … 68 69 } 69 70 70 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true);71 void find( Expression *expr, ResolvMode mode = ResolvMode{} ); 71 72 /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types 72 73 void findWithAdjustment( Expression *expr ); -
src/ResolvExpr/CastCost.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 06:57:43 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue Feb 2 15:34:36 201613 // Update Count : 711 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Aug 8 16:12:00 2019 13 // Update Count : 8 14 14 // 15 15 16 16 #include <cassert> // for assert 17 17 18 #include "AST/Print.hpp" 19 #include "AST/SymbolTable.hpp" 20 #include "AST/Type.hpp" 21 #include "AST/TypeEnvironment.hpp" 18 22 #include "ConversionCost.h" // for ConversionCost 19 23 #include "Cost.h" // for Cost, Cost::infinity … … 31 35 32 36 namespace ResolvExpr { 33 struct CastCost : public ConversionCost {37 struct CastCost_old : public ConversionCost { 34 38 public: 35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ); 39 CastCost_old( const Type * dest, bool srcIsLvalue, 40 const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ); 36 41 37 42 using ConversionCost::previsit; 38 43 using ConversionCost::postvisit; 39 void postvisit( BasicType * basicType );40 void postvisit( PointerType * pointerType );44 void postvisit( const BasicType * basicType ); 45 void postvisit( const PointerType * pointerType ); 41 46 }; 42 47 43 Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 44 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { 45 if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) { 48 Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue, 49 const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 50 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) { 51 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) { 46 52 if ( eqvClass->type ) { 47 return castCost( src, eqvClass->type, indexer, env );53 return castCost( src, eqvClass->type, srcIsLvalue, indexer, env ); 48 54 } else { 49 55 return Cost::infinity; 50 56 } 51 } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name()) ) {57 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) { 52 58 // all typedefs should be gone by this point 53 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );59 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType ); 54 60 if ( type->base ) { 55 return castCost( src, type->base, indexer, env ) + Cost::safe;61 return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe; 56 62 } // if 57 63 } // if … … 70 76 PRINT( std::cerr << "compatible!" << std::endl; ) 71 77 return Cost::zero; 72 } else if ( dynamic_cast< VoidType* >( dest ) ) {78 } else if ( dynamic_cast< const VoidType * >( dest ) ) { 73 79 return Cost::safe; 74 } else if ( ReferenceType * refType = dynamic_cast<ReferenceType * > ( dest ) ) {80 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) { 75 81 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 76 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1,Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {82 return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 77 83 return ptrsCastable( t1, t2, env, indexer ); 78 84 }); 79 85 } else { 80 PassVisitor<CastCost> converter( dest, indexer, env, castCost ); 86 PassVisitor<CastCost_old> converter( 87 dest, srcIsLvalue, indexer, env, 88 (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & )) 89 castCost ); 81 90 src->accept( converter ); 82 91 if ( converter.pass.get_cost() == Cost::infinity ) { … … 89 98 } 90 99 91 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 92 : ConversionCost( dest, indexer, env, costFunc ) { 93 } 94 95 void CastCost::postvisit( BasicType *basicType ) { 96 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest ); 100 CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue, 101 const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 102 : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) { 103 } 104 105 void CastCost_old::postvisit( const BasicType * basicType ) { 106 const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest ); 97 107 if ( destAsPointer && basicType->isInteger() ) { 98 // necessary for, e.g. unsigned long => void *108 // necessary for, e.g. unsigned long => void * 99 109 cost = Cost::unsafe; 100 110 } else { 101 cost = conversionCost( basicType, dest, indexer, env );111 cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env ); 102 112 } // if 103 113 } 104 114 105 void CastCost ::postvisit( PointerType *pointerType ) {106 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {107 if ( pointerType-> get_qualifiers() <= destAsPtr->get_qualifiers()&& typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {115 void CastCost_old::postvisit( const PointerType * pointerType ) { 116 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) { 117 if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 108 118 cost = Cost::safe; 109 119 } else { … … 118 128 } // if 119 129 } // if 120 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {130 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) { 121 131 if ( destAsBasic->isInteger() ) { 122 // necessary for, e.g. void * => unsigned long132 // necessary for, e.g. void * => unsigned long 123 133 cost = Cost::unsafe; 124 134 } // if 125 135 } 126 136 } 137 138 namespace { 139 struct CastCost_new : public ConversionCost_new { 140 using ConversionCost_new::previsit; 141 using ConversionCost_new::postvisit; 142 143 CastCost_new( 144 const ast::Type * dst, const ast::SymbolTable & symtab, 145 const ast::TypeEnvironment & env, CostCalculation costFunc ) 146 : ConversionCost_new( dst, symtab, env, costFunc ) {} 147 148 void postvisit( const ast::BasicType * basicType ) { 149 auto ptr = dynamic_cast< const ast::PointerType * >( dst ); 150 if ( ptr && basicType->isInteger() ) { 151 // needed for, e.g. unsigned long => void * 152 cost = Cost::unsafe; 153 } else { 154 cost = conversionCost( basicType, dst, symtab, env ); 155 } 156 } 157 158 void postvisit( const ast::PointerType * pointerType ) { 159 if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) { 160 if ( 161 pointerType->qualifiers <= ptr->qualifiers 162 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env ) 163 ) { 164 cost = Cost::safe; 165 } else { 166 ast::TypeEnvironment newEnv{ env }; 167 if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) { 168 newEnv.add( wParams->forall ); 169 } 170 int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv ); 171 if ( castResult > 0 ) { 172 cost = Cost::safe; 173 } else if ( castResult < 0 ) { 174 cost = Cost::infinity; 175 } 176 } 177 } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) { 178 if ( basic->isInteger() ) { 179 // necessary for, e.g. void * => unsigned long 180 cost = Cost::unsafe; 181 } 182 } 183 } 184 }; 185 } // anonymous namespace 186 187 Cost castCost( 188 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 189 const ast::TypeEnvironment & env 190 ) { 191 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 192 if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) { 193 // check cast cost against bound type, if present 194 if ( eqvClass->bound ) { 195 return castCost( src, eqvClass->bound, symtab, env ); 196 } else { 197 return Cost::infinity; 198 } 199 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) { 200 // all typedefs should be gone by now 201 auto type = strict_dynamic_cast< const ast::TypeDecl * >( named ); 202 if ( type->base ) { 203 return castCost( src, type->base, symtab, env ) + Cost::safe; 204 } 205 } 206 } 207 208 PRINT( 209 std::cerr << "castCost ::: src is "; 210 ast::print( std::cerr, src ); 211 std::cerr << std::endl << "dest is "; 212 ast::print( std::cerr, dst ); 213 std::cerr << std::endl << "env is" << std::endl; 214 ast::print( std::cerr, env, 2 ); 215 ) 216 217 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) { 218 PRINT( std::cerr << "compatible!" << std::endl; ) 219 return Cost::zero; 220 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { 221 return Cost::safe; 222 } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) { 223 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 224 #warning cast on ptrsCastable artifact of having two functions, remove when port done 225 return convertToReferenceCost( 226 src, refType, symtab, env, 227 ( int (*)( 228 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 229 const ast::TypeEnvironment & ) 230 ) ptrsCastable ); 231 } else { 232 #warning cast on castCost artifact of having two functions, remove when port done 233 ast::Pass< CastCost_new > converter{ 234 dst, symtab, env, 235 ( Cost (*)( 236 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 237 const ast::TypeEnvironment & ) 238 ) castCost }; 239 src->accept( converter ); 240 return converter.pass.cost; 241 } 242 } 243 127 244 } // namespace ResolvExpr 128 245 -
src/ResolvExpr/CommonType.cc
r7951100 rb067d9b 10 10 // Created On : Sun May 17 06:59:27 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 25 15:18:17 201713 // Update Count : 912 // Last Modified On : Thu Feb 14 17:10:10 2019 13 // Update Count : 24 14 14 // 15 15 … … 18 18 #include <utility> // for pair 19 19 20 #include "AST/Decl.hpp" 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" 21 23 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 24 26 #include "SynTree/Type.h" // for BasicType, BasicType::Kind::... 25 27 #include "SynTree/Visitor.h" // for Visitor 26 #include "Unify.h" // for unifyExact, bindVar,WidenMode28 #include "Unify.h" // for unifyExact, WidenMode 27 29 #include "typeops.h" // for isFtype 28 30 … … 35 37 36 38 namespace ResolvExpr { 37 struct CommonType : public WithShortCircuiting {38 CommonType ( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );39 Type * get_result() const { return result; }39 struct CommonType_old : public WithShortCircuiting { 40 CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 41 Type * get_result() const { return result; } 40 42 41 43 void previsit( BaseSyntaxNode * ) { visit_children = false; } … … 58 60 59 61 private: 60 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer* otherPointer );61 template< typename RefType > void handleRefType( RefType * inst, Type *other );62 63 Type * result;64 Type * type2; // inherited62 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ); 63 template< typename RefType > void handleRefType( RefType * inst, Type * other ); 64 65 Type * result; 66 Type * type2; // inherited 65 67 bool widenFirst, widenSecond; 66 68 const SymTab::Indexer &indexer; … … 78 80 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl; 79 81 ) 80 if ( (widenFirst || t2-> get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {82 if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) { 81 83 PRINT( 82 84 std::cerr << "widen okay" << std::endl; 83 85 ) 84 common-> get_qualifiers() |= t1->get_qualifiers();85 common-> get_qualifiers() |= t2->get_qualifiers();86 common->tq |= t1->tq; 87 common->tq |= t2->tq; 86 88 return common; 87 89 } … … 93 95 } 94 96 95 Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {96 PassVisitor<CommonType > visitor( type2, widenFirst, widenSecond, indexer, env, openVars );97 Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 98 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 97 99 98 100 int depth1 = type1->referenceDepth(); … … 125 127 std::cerr << "formal is reference; result should be reference" << std::endl; 126 128 ) 127 result = new ReferenceType( ref1-> get_qualifiers(), result );129 result = new ReferenceType( ref1->tq, result ); 128 130 } 129 131 PRINT( … … 136 138 137 139 type1->accept( visitor ); 138 Type * result = visitor.pass.get_result();140 Type * result = visitor.pass.get_result(); 139 141 if ( ! result ) { 140 142 // this appears to be handling for opaque type declarations 141 143 if ( widenSecond ) { 142 if ( TypeInstType *inst = dynamic_cast< TypeInstType* >( type2 ) ) {143 if ( NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ) ) {144 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( nt );144 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) { 145 if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) { 146 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt ); 145 147 if ( type->get_base() ) { 146 Type::Qualifiers tq1 = type1-> get_qualifiers(), tq2 = type2->get_qualifiers();148 Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq; 147 149 AssertionSet have, need; 148 150 OpenVarSet newOpen( openVars ); 149 type1-> get_qualifiers()= Type::Qualifiers();150 type->get_base()-> get_qualifiers()= tq1;151 type1->tq = Type::Qualifiers(); 152 type->get_base()->tq = tq1; 151 153 if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) { 152 154 result = type1->clone(); 153 result-> get_qualifiers()= tq1 | tq2;155 result->tq = tq1 | tq2; 154 156 } // if 155 type1-> get_qualifiers()= tq1;156 type->get_base()-> get_qualifiers()= Type::Qualifiers();157 type1->tq = tq1; 158 type->get_base()->tq = Type::Qualifiers(); 157 159 } // if 158 160 } // if … … 176 178 } 177 179 178 static const BasicType::Kind combinedType[][ BasicType::NUMBER_OF_BASIC_TYPES ] = 179 { 180 /* Bool Char SignedChar UnsignedChar ShortSignedInt ShortUnsignedInt SignedInt UnsignedInt LongSignedInt LongUnsignedInt LongLongSignedInt LongLongUnsignedInt Float Double LongDouble FloatComplex DoubleComplex LongDoubleComplex FloatImaginary DoubleImaginary LongDoubleImaginary SignedInt128 UnsignedInt128 Float80 Float128 */ 181 /* Bool */ { BasicType::Bool, BasicType::Char, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 182 /* Char */ { BasicType::Char, BasicType::Char, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 183 /* SignedChar */ { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 184 /* UnsignedChar */ { BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 185 /* ShortSignedInt */ { BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 186 /* ShortUnsignedInt */ { BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 187 /* SignedInt */ { BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 188 /* UnsignedInt */ { BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 189 /* LongSignedInt */ { BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 190 /* LongUnsignedInt */ { BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 191 /* LongLongSignedInt */ { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 192 /* LongLongUnsignedInt */ { BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 193 /* Float */ { BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Float, BasicType::Float, BasicType::Float80, BasicType::Float128 }, 194 /* Double */ { BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::LongDouble, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Double, BasicType::Double, BasicType::Float80, BasicType::Float128 }, 195 /* LongDouble */ { BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDouble, BasicType::LongDouble, BasicType::BasicType::LongDouble, BasicType::Float128 }, 196 /* FloatComplex */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, }, 197 /* DoubleComplex */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex }, 198 /* LongDoubleComplex */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, }, 199 /* FloatImaginary */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::FloatImaginary, BasicType::FloatImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 200 /* DoubleImaginary */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::DoubleImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 201 /* LongDoubleImaginary */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 202 /* SignedInt128 */ { BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, }, 203 /* UnsignedInt128 */ { BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, }, 204 /* Float80 */ { BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::LongDouble, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float128 }, 205 /* Float128 */ { BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128 }, 206 }; 180 // GENERATED START, DO NOT EDIT 181 // GENERATED BY BasicTypes-gen.cc 182 #define BT BasicType:: 183 static const BasicType::Kind commonTypes[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // nearest common ancestor 184 /* B C SC UC SI SUI 185 I UI LI LUI LLI LLUI 186 IB UIB _FH _FH _F _FC 187 F FC _FX _FXC FD _FDC 188 D DC F80X _FDXC F80 _FB 189 _FLDC FB LD LDC _FBX _FLDXC 190 */ 191 { 192 /* B */ BT Bool, BT Char, BT SignedChar, BT UnsignedChar, BT ShortSignedInt, BT ShortUnsignedInt, 193 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 194 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 195 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 196 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 197 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 198 }, 199 { 200 /* C */ BT Char, BT Char, BT SignedChar, BT UnsignedChar, BT ShortSignedInt, BT ShortUnsignedInt, 201 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 202 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 203 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 204 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 205 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 206 }, 207 { 208 /* SC */ BT SignedChar, BT SignedChar, BT SignedChar, BT UnsignedChar, BT ShortSignedInt, BT ShortUnsignedInt, 209 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 210 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 211 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 212 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 213 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 214 }, 215 { 216 /* UC */ BT UnsignedChar, BT UnsignedChar, BT UnsignedChar, BT UnsignedChar, BT ShortSignedInt, BT ShortUnsignedInt, 217 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 218 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 219 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 220 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 221 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 222 }, 223 { 224 /* SI */ BT ShortSignedInt, BT ShortSignedInt, BT ShortSignedInt, BT ShortSignedInt, BT ShortSignedInt, BT ShortUnsignedInt, 225 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 226 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 227 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 228 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 229 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 230 }, 231 { 232 /* SUI */ BT ShortUnsignedInt, BT ShortUnsignedInt, BT ShortUnsignedInt, BT ShortUnsignedInt, BT ShortUnsignedInt, BT ShortUnsignedInt, 233 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 234 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 235 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 236 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 237 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 238 }, 239 { 240 /* I */ BT SignedInt, BT SignedInt, BT SignedInt, BT SignedInt, BT SignedInt, BT SignedInt, 241 BT SignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 242 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 243 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 244 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 245 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 246 }, 247 { 248 /* UI */ BT UnsignedInt, BT UnsignedInt, BT UnsignedInt, BT UnsignedInt, BT UnsignedInt, BT UnsignedInt, 249 BT UnsignedInt, BT UnsignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 250 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 251 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 252 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 253 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 254 }, 255 { 256 /* LI */ BT LongSignedInt, BT LongSignedInt, BT LongSignedInt, BT LongSignedInt, BT LongSignedInt, BT LongSignedInt, 257 BT LongSignedInt, BT LongSignedInt, BT LongSignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 258 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 259 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 260 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 261 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 262 }, 263 { 264 /* LUI */ BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, 265 BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, BT LongUnsignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 266 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 267 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 268 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 269 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 270 }, 271 { 272 /* LLI */ BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, 273 BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongSignedInt, BT LongLongUnsignedInt, 274 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 275 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 276 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 277 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 278 }, 279 { 280 /* LLUI */ BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, 281 BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, 282 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 283 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 284 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 285 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 286 }, 287 { 288 /* IB */ BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, 289 BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, BT SignedInt128, 290 BT SignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 291 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 292 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 293 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 294 }, 295 { 296 /* UIB */ BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, 297 BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, BT UnsignedInt128, 298 BT UnsignedInt128, BT UnsignedInt128, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 299 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 300 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 301 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 302 }, 303 { 304 /* _FH */ BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, 305 BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16, 306 BT uFloat16, BT uFloat16, BT uFloat16, BT uFloat16Complex, BT uFloat32, BT uFloat32Complex, 307 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 308 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 309 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 310 }, 311 { 312 /* _FH */ BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, 313 BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, 314 BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat16Complex, BT uFloat32Complex, BT uFloat32Complex, 315 BT FloatComplex, BT FloatComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat64Complex, BT uFloat64Complex, 316 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 317 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 318 }, 319 { 320 /* _F */ BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, 321 BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32, 322 BT uFloat32, BT uFloat32, BT uFloat32, BT uFloat32Complex, BT uFloat32, BT uFloat32Complex, 323 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 324 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 325 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 326 }, 327 { 328 /* _FC */ BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, 329 BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, 330 BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, BT uFloat32Complex, 331 BT FloatComplex, BT FloatComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat64Complex, BT uFloat64Complex, 332 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 333 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 334 }, 335 { 336 /* F */ BT Float, BT Float, BT Float, BT Float, BT Float, BT Float, 337 BT Float, BT Float, BT Float, BT Float, BT Float, BT Float, 338 BT Float, BT Float, BT Float, BT FloatComplex, BT Float, BT FloatComplex, 339 BT Float, BT FloatComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 340 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 341 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 342 }, 343 { 344 /* FC */ BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, 345 BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, 346 BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, BT FloatComplex, 347 BT FloatComplex, BT FloatComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat64Complex, BT uFloat64Complex, 348 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 349 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 350 }, 351 { 352 /* _FX */ BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, 353 BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32x, 354 BT uFloat32x, BT uFloat32x, BT uFloat32x, BT uFloat32xComplex, BT uFloat32x, BT uFloat32xComplex, 355 BT uFloat32x, BT uFloat32xComplex, BT uFloat32x, BT uFloat32xComplex, BT uFloat64, BT uFloat64Complex, 356 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 357 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 358 }, 359 { 360 /* _FXC */ BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, 361 BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, 362 BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, 363 BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat32xComplex, BT uFloat64Complex, BT uFloat64Complex, 364 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 365 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 366 }, 367 { 368 /* FD */ BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, 369 BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64, 370 BT uFloat64, BT uFloat64, BT uFloat64, BT uFloat64Complex, BT uFloat64, BT uFloat64Complex, 371 BT uFloat64, BT uFloat64Complex, BT uFloat64, BT uFloat64Complex, BT uFloat64, BT uFloat64Complex, 372 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 373 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 374 }, 375 { 376 /* _FDC */ BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, 377 BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, 378 BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, 379 BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, BT uFloat64Complex, 380 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 381 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 382 }, 383 { 384 /* D */ BT Double, BT Double, BT Double, BT Double, BT Double, BT Double, 385 BT Double, BT Double, BT Double, BT Double, BT Double, BT Double, 386 BT Double, BT Double, BT Double, BT DoubleComplex, BT Double, BT DoubleComplex, 387 BT Double, BT DoubleComplex, BT Double, BT DoubleComplex, BT Double, BT DoubleComplex, 388 BT Double, BT DoubleComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 389 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 390 }, 391 { 392 /* DC */ BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, 393 BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, 394 BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, 395 BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, BT DoubleComplex, 396 BT DoubleComplex, BT DoubleComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 397 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 398 }, 399 { 400 /* F80X */ BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, 401 BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64x, 402 BT uFloat64x, BT uFloat64x, BT uFloat64x, BT uFloat64xComplex, BT uFloat64x, BT uFloat64xComplex, 403 BT uFloat64x, BT uFloat64xComplex, BT uFloat64x, BT uFloat64xComplex, BT uFloat64x, BT uFloat64xComplex, 404 BT uFloat64x, BT uFloat64xComplex, BT uFloat64x, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 405 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 406 }, 407 { 408 /* _FDXC */ BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, 409 BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, 410 BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, 411 BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, 412 BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat64xComplex, BT uFloat128Complex, 413 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 414 }, 415 { 416 /* F80 */ BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, 417 BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uuFloat80, 418 BT uuFloat80, BT uuFloat80, BT uuFloat80, BT uFloat64xComplex, BT uuFloat80, BT uFloat64xComplex, 419 BT uuFloat80, BT uFloat64xComplex, BT uuFloat80, BT uFloat64xComplex, BT uuFloat80, BT uFloat64xComplex, 420 BT uuFloat80, BT uFloat64xComplex, BT uuFloat80, BT uFloat64xComplex, BT uuFloat80, BT uFloat128, 421 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 422 }, 423 { 424 /* _FB */ BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, 425 BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128, 426 BT uFloat128, BT uFloat128, BT uFloat128, BT uFloat128Complex, BT uFloat128, BT uFloat128Complex, 427 BT uFloat128, BT uFloat128Complex, BT uFloat128, BT uFloat128Complex, BT uFloat128, BT uFloat128Complex, 428 BT uFloat128, BT uFloat128Complex, BT uFloat128, BT uFloat128Complex, BT uFloat128, BT uFloat128, 429 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 430 }, 431 { 432 /* _FLDC */ BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, 433 BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, 434 BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, 435 BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, 436 BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, BT uFloat128Complex, 437 BT uFloat128Complex, BT uFloat128Complex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 438 }, 439 { 440 /* FB */ BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, 441 BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uuFloat128, 442 BT uuFloat128, BT uuFloat128, BT uuFloat128, BT uFloat128Complex, BT uuFloat128, BT uFloat128Complex, 443 BT uuFloat128, BT uFloat128Complex, BT uuFloat128, BT uFloat128Complex, BT uuFloat128, BT uFloat128Complex, 444 BT uuFloat128, BT uFloat128Complex, BT uuFloat128, BT uFloat128Complex, BT uuFloat128, BT uuFloat128, 445 BT uFloat128Complex, BT uuFloat128, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 446 }, 447 { 448 /* LD */ BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, 449 BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, BT LongDouble, 450 BT LongDouble, BT LongDouble, BT LongDouble, BT LongDoubleComplex, BT LongDouble, BT LongDoubleComplex, 451 BT LongDouble, BT LongDoubleComplex, BT LongDouble, BT LongDoubleComplex, BT LongDouble, BT LongDoubleComplex, 452 BT LongDouble, BT LongDoubleComplex, BT LongDouble, BT LongDoubleComplex, BT LongDouble, BT LongDouble, 453 BT LongDoubleComplex, BT LongDouble, BT LongDouble, BT LongDoubleComplex, BT uFloat128x, BT uFloat128xComplex, 454 }, 455 { 456 /* LDC */ BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, 457 BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, 458 BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, 459 BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, 460 BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, 461 BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT LongDoubleComplex, BT uFloat128xComplex, BT uFloat128xComplex, 462 }, 463 { 464 /* _FBX */ BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, 465 BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128x, 466 BT uFloat128x, BT uFloat128x, BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128xComplex, 467 BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128xComplex, 468 BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128x, 469 BT uFloat128xComplex, BT uFloat128x, BT uFloat128x, BT uFloat128xComplex, BT uFloat128x, BT uFloat128xComplex, 470 }, 471 { 472 /* _FLDXC */ BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 473 BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 474 BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 475 BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 476 BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 477 BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, BT uFloat128xComplex, 478 }, 479 }; // commonTypes 480 #undef BT 481 // GENERATED END 207 482 static_assert( 208 sizeof(com binedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,483 sizeof(commonTypes)/sizeof(commonTypes[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES, 209 484 "Each basic type kind should have a corresponding row in the combined type matrix" 210 485 ); 211 486 212 CommonType ::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )487 CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) 213 488 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) { 214 489 } 215 490 216 void CommonType ::postvisit( VoidType * ) {}217 218 void CommonType ::postvisit( BasicType *basicType ) {219 if ( BasicType * otherBasic = dynamic_cast< BasicType* >( type2 ) ) {220 BasicType::Kind newType = com binedType[ basicType->get_kind() ][ otherBasic->get_kind() ];221 if ( ( ( newType == basicType->get_kind() && basicType-> get_qualifiers() >= otherBasic->get_qualifiers() ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->get_qualifiers() <= otherBasic->get_qualifiers()) || widenSecond ) ) {222 result = new BasicType( basicType-> get_qualifiers() | otherBasic->get_qualifiers(), newType );491 void CommonType_old::postvisit( VoidType * ) {} 492 493 void CommonType_old::postvisit( BasicType * basicType ) { 494 if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) { 495 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ]; 496 if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) { 497 result = new BasicType( basicType->tq | otherBasic->tq, newType ); 223 498 } // if 224 } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {499 } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) { 225 500 // use signed int in lieu of the enum/zero/one type 226 BasicType::Kind newType = com binedType[ basicType->get_kind() ][ BasicType::SignedInt ];227 if ( ( ( newType == basicType->get_kind() && basicType-> get_qualifiers() >= type2->get_qualifiers() ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->get_qualifiers() <= type2->get_qualifiers()) || widenSecond ) ) {228 result = new BasicType( basicType-> get_qualifiers() | type2->get_qualifiers(), newType );501 BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ]; 502 if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) { 503 result = new BasicType( basicType->tq | type2->tq, newType ); 229 504 } // if 230 505 } // if … … 232 507 233 508 template< typename Pointer > 234 void CommonType ::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {235 if ( TypeInstType * var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {509 void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) { 510 if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) { 236 511 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); 237 512 if ( entry != openVars.end() ) { 238 513 AssertionSet need, have; 239 514 WidenMode widen( widenFirst, widenSecond ); 240 if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;515 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return; 241 516 } 242 517 } 243 518 result = voidPointer->clone(); 244 result-> get_qualifiers() |= otherPointer->get_qualifiers();245 } 246 247 void CommonType ::postvisit( PointerType *pointerType ) {248 if ( PointerType * otherPointer = dynamic_cast< PointerType* >( type2 ) ) {519 result->tq |= otherPointer->tq; 520 } 521 522 void CommonType_old::postvisit( PointerType * pointerType ) { 523 if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) { 249 524 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; 250 if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {525 if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) { 251 526 getCommonWithVoidPointer( otherPointer, pointerType ); 252 } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {527 } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) { 253 528 getCommonWithVoidPointer( pointerType, otherPointer ); 254 } else if ( ( pointerType->get_base()-> get_qualifiers() >= otherPointer->get_base()->get_qualifiers()|| widenFirst )255 && ( pointerType->get_base()-> get_qualifiers() <= otherPointer->get_base()->get_qualifiers()|| widenSecond ) ) {529 } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst ) 530 && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) { 256 531 // std::cerr << "middle case" << std::endl; 257 Type::Qualifiers tq1 = pointerType->get_base()-> get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers();258 pointerType->get_base()-> get_qualifiers()= Type::Qualifiers();259 otherPointer->get_base()-> get_qualifiers()= Type::Qualifiers();532 Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq; 533 pointerType->get_base()->tq = Type::Qualifiers(); 534 otherPointer->get_base()->tq = Type::Qualifiers(); 260 535 AssertionSet have, need; 261 536 OpenVarSet newOpen( openVars ); … … 267 542 result = otherPointer->clone(); 268 543 } // if 269 result->get_qualifiers()= tq1 | tq2;544 strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2; 270 545 } else { 271 546 /// std::cerr << "place for ptr-to-type" << std::endl; 272 547 } // if 273 pointerType->get_base()-> get_qualifiers()= tq1;274 otherPointer->get_base()-> get_qualifiers()= tq2;548 pointerType->get_base()->tq = tq1; 549 otherPointer->get_base()->tq = tq2; 275 550 } // if 276 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {551 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) { 277 552 result = pointerType->clone(); 278 result-> get_qualifiers() |= type2->get_qualifiers();553 result->tq |= type2->tq; 279 554 } // if 280 555 } 281 556 282 void CommonType ::postvisit( ArrayType * ) {}283 284 void CommonType ::postvisit( ReferenceType *refType ) {285 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {557 void CommonType_old::postvisit( ArrayType * ) {} 558 559 void CommonType_old::postvisit( ReferenceType * refType ) { 560 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) { 286 561 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; 287 // std::cerr << ( refType->get_base()-> get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers()|| widenSecond) << std::endl;288 if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {562 // std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl; 563 if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) { 289 564 getCommonWithVoidPointer( otherRef, refType ); 290 } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {565 } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) { 291 566 getCommonWithVoidPointer( refType, otherRef ); 292 } else if ( ( refType->get_base()-> get_qualifiers() >= otherRef->get_base()->get_qualifiers()|| widenFirst )293 && ( refType->get_base()-> get_qualifiers() <= otherRef->get_base()->get_qualifiers()|| widenSecond ) ) {567 } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) 568 && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) { 294 569 // std::cerr << "middle case" << std::endl; 295 Type::Qualifiers tq1 = refType->get_base()-> get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();296 refType->get_base()-> get_qualifiers()= Type::Qualifiers();297 otherRef->get_base()-> get_qualifiers()= Type::Qualifiers();570 Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq; 571 refType->get_base()->tq = Type::Qualifiers(); 572 otherRef->get_base()->tq = Type::Qualifiers(); 298 573 AssertionSet have, need; 299 574 OpenVarSet newOpen( openVars ); … … 304 579 result = otherRef->clone(); 305 580 } // if 306 result->get_qualifiers()= tq1 | tq2;581 strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2; 307 582 } else { 308 583 /// std::cerr << "place for ptr-to-type" << std::endl; 309 584 } // if 310 refType->get_base()-> get_qualifiers()= tq1;311 otherRef->get_base()-> get_qualifiers()= tq2;585 refType->get_base()->tq = tq1; 586 otherRef->get_base()->tq = tq2; 312 587 } // if 313 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {588 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) { 314 589 result = refType->clone(); 315 result-> get_qualifiers() |= type2->get_qualifiers();590 result->tq |= type2->tq; 316 591 } // if 317 592 } 318 593 319 void CommonType ::postvisit( FunctionType * ) {}320 void CommonType ::postvisit( StructInstType * ) {}321 void CommonType ::postvisit( UnionInstType * ) {}322 323 void CommonType ::postvisit( EnumInstType *enumInstType ) {324 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {594 void CommonType_old::postvisit( FunctionType * ) {} 595 void CommonType_old::postvisit( StructInstType * ) {} 596 void CommonType_old::postvisit( UnionInstType * ) {} 597 598 void CommonType_old::postvisit( EnumInstType * enumInstType ) { 599 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) { 325 600 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 326 601 result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars ); … … 328 603 } 329 604 330 void CommonType ::postvisit( TraitInstType * ) {331 } 332 333 void CommonType ::postvisit( TypeInstType *inst ) {605 void CommonType_old::postvisit( TraitInstType * ) { 606 } 607 608 void CommonType_old::postvisit( TypeInstType * inst ) { 334 609 if ( widenFirst ) { 335 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );610 const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ); 336 611 if ( nt ) { 337 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( nt );612 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt ); 338 613 if ( type->get_base() ) { 339 Type::Qualifiers tq1 = inst-> get_qualifiers(), tq2 = type2->get_qualifiers();614 Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq; 340 615 AssertionSet have, need; 341 616 OpenVarSet newOpen( openVars ); 342 type2-> get_qualifiers()= Type::Qualifiers();343 type->get_base()-> get_qualifiers()= tq1;617 type2->tq = Type::Qualifiers(); 618 type->get_base()->tq = tq1; 344 619 if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) { 345 620 result = type2->clone(); 346 result-> get_qualifiers()= tq1 | tq2;621 result->tq = tq1 | tq2; 347 622 } // if 348 type2-> get_qualifiers()= tq2;349 type->get_base()-> get_qualifiers()= Type::Qualifiers();623 type2->tq = tq2; 624 type->get_base()->tq = Type::Qualifiers(); 350 625 } // if 351 626 } // if … … 353 628 } 354 629 355 void CommonType ::postvisit( TupleType * ) {}356 void CommonType ::postvisit( VarArgsType * ) {}357 358 void CommonType ::postvisit( ZeroType *zeroType ) {630 void CommonType_old::postvisit( TupleType * ) {} 631 void CommonType_old::postvisit( VarArgsType * ) {} 632 633 void CommonType_old::postvisit( ZeroType * zeroType ) { 359 634 if ( widenFirst ) { 360 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {361 if ( widenSecond || zeroType-> get_qualifiers() <= type2->get_qualifiers()) {635 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) { 636 if ( widenSecond || zeroType->tq <= type2->tq ) { 362 637 result = type2->clone(); 363 result-> get_qualifiers() |= zeroType->get_qualifiers();364 } 365 } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {366 result = new BasicType( zeroType-> get_qualifiers(), BasicType::SignedInt );367 result-> get_qualifiers() |= type2->get_qualifiers();368 } 369 } 370 } 371 372 void CommonType ::postvisit( OneType *oneType ) {638 result->tq |= zeroType->tq; 639 } 640 } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) { 641 result = new BasicType( zeroType->tq, BasicType::SignedInt ); 642 result->tq |= type2->tq; 643 } 644 } 645 } 646 647 void CommonType_old::postvisit( OneType * oneType ) { 373 648 if ( widenFirst ) { 374 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {375 if ( widenSecond || oneType-> get_qualifiers() <= type2->get_qualifiers()) {649 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) { 650 if ( widenSecond || oneType->tq <= type2->tq ) { 376 651 result = type2->clone(); 377 result->get_qualifiers() |= oneType->get_qualifiers(); 378 } 379 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) { 380 result = new BasicType( oneType->get_qualifiers(), BasicType::SignedInt ); 381 result->get_qualifiers() |= type2->get_qualifiers(); 382 } 383 } 384 } 652 result->tq |= oneType->tq; 653 } 654 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) { 655 result = new BasicType( oneType->tq, BasicType::SignedInt ); 656 result->tq |= type2->tq; 657 } 658 } 659 } 660 661 class CommonType_new final : public ast::WithShortCircuiting { 662 const ast::Type * type2; 663 WidenMode widen; 664 const ast::SymbolTable & symtab; 665 ast::TypeEnvironment & tenv; 666 const ast::OpenVarSet & open; 667 public: 668 ast::ptr< ast::Type > result; 669 670 CommonType_new( 671 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st, 672 ast::TypeEnvironment & env, const ast::OpenVarSet & o ) 673 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {} 674 675 void previsit( const ast::Node * ) { visit_children = false; } 676 677 void postvisit( const ast::VoidType * ) {} 678 679 void postvisit( const ast::BasicType * basic ) { 680 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 681 #warning remove casts when `commonTypes` moved to new AST 682 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 683 if ( 684 ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers ) 685 || widen.first ) 686 && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers ) 687 || widen.second ) 688 ) { 689 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 690 } 691 } else if ( 692 dynamic_cast< const ast::EnumInstType * >( type2 ) 693 || dynamic_cast< const ast::ZeroType * >( type2 ) 694 || dynamic_cast< const ast::OneType * >( type2 ) 695 ) { 696 #warning remove casts when `commonTypes` moved to new AST 697 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ]; 698 if ( 699 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 700 || widen.first ) 701 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 702 || widen.second ) 703 ) { 704 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 705 } 706 } 707 } 708 709 private: 710 template< typename Pointer > 711 void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) { 712 const ast::Type * base = oPtr->base; 713 if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) { 714 auto entry = open.find( var->name ); 715 if ( entry != open.end() ) { 716 ast::AssertionSet need, have; 717 if ( ! tenv.bindVar( 718 var, voidPtr->base, entry->second, need, have, open, widen, symtab ) 719 ) return; 720 } 721 } 722 result = voidPtr; 723 add_qualifiers( result, oPtr->qualifiers ); 724 } 725 726 public: 727 void postvisit( const ast::PointerType * pointer ) { 728 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 729 if ( 730 widen.first 731 && pointer2->base.as< ast::VoidType >() 732 && ! ast::isFtype( pointer->base ) 733 ) { 734 getCommonWithVoidPointer( pointer2, pointer ); 735 } else if ( 736 widen.second 737 && pointer->base.as< ast::VoidType >() 738 && ! ast::isFtype( pointer2->base ) 739 ) { 740 getCommonWithVoidPointer( pointer, pointer2 ); 741 } else if ( 742 ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first ) 743 && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second ) 744 ) { 745 ast::CV::Qualifiers q1 = pointer->base->qualifiers; 746 ast::CV::Qualifiers q2 = pointer2->base->qualifiers; 747 748 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 749 // pointer{,2}->base are unchanged 750 ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base }; 751 reset_qualifiers( t1 ); 752 reset_qualifiers( t2 ); 753 754 ast::AssertionSet have, need; 755 ast::OpenVarSet newOpen{ open }; 756 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 757 result = pointer; 758 if ( q1.val != q2.val ) { 759 // reset result->base->qualifiers to be union of two base qualifiers 760 strict_dynamic_cast< ast::PointerType * >( 761 result.get_and_mutate() 762 )->base.get_and_mutate()->qualifiers = q1 | q2; 763 } 764 } 765 } 766 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 767 result = pointer; 768 add_qualifiers( result, type2->qualifiers ); 769 } 770 } 771 772 void postvisit( const ast::ArrayType * ) {} 773 774 void postvisit( const ast::ReferenceType * ref ) { 775 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 776 if ( 777 widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base ) 778 ) { 779 getCommonWithVoidPointer( ref2, ref ); 780 } else if ( 781 widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base ) 782 ) { 783 getCommonWithVoidPointer( ref, ref2 ); 784 } else if ( 785 ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first ) 786 && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second ) 787 ) { 788 ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers; 789 790 // force t{1,2} to be cloned if their qualifiers must be stripped, so that 791 // ref{,2}->base are unchanged 792 ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base }; 793 reset_qualifiers( t1 ); 794 reset_qualifiers( t2 ); 795 796 ast::AssertionSet have, need; 797 ast::OpenVarSet newOpen{ open }; 798 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 799 result = ref; 800 if ( q1.val != q2.val ) { 801 // reset result->base->qualifiers to be union of two base qualifiers 802 strict_dynamic_cast< ast::ReferenceType * >( 803 result.get_and_mutate() 804 )->base.get_and_mutate()->qualifiers = q1 | q2; 805 } 806 } 807 } 808 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 809 result = ref; 810 add_qualifiers( result, type2->qualifiers ); 811 } 812 } 813 814 void postvisit( const ast::FunctionType * ) {} 815 816 void postvisit( const ast::StructInstType * ) {} 817 818 void postvisit( const ast::UnionInstType * ) {} 819 820 void postvisit( const ast::EnumInstType * enumInst ) { 821 if ( 822 dynamic_cast< const ast::BasicType * >( type2 ) 823 || dynamic_cast< const ast::ZeroType * >( type2 ) 824 || dynamic_cast< const ast::OneType * >( type2 ) 825 ) { 826 // reuse BasicType/EnumInstType common type by swapping 827 result = commonType( type2, enumInst, widen, symtab, tenv, open ); 828 } 829 } 830 831 void postvisit( const ast::TraitInstType * ) {} 832 833 void postvisit( const ast::TypeInstType * inst ) { 834 if ( ! widen.first ) return; 835 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 836 if ( const ast::Type * base = 837 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base 838 ) { 839 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers; 840 841 // force t{1,2} to be cloned if their qualifiers must be mutated 842 ast::ptr< ast::Type > t1{ base }, t2{ type2 }; 843 reset_qualifiers( t1, q1 ); 844 reset_qualifiers( t2 ); 845 846 ast::AssertionSet have, need; 847 ast::OpenVarSet newOpen{ open }; 848 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 849 result = type2; 850 reset_qualifiers( result, q1 | q2 ); 851 } 852 } 853 } 854 } 855 856 void postvisit( const ast::TupleType * ) {} 857 858 void postvisit( const ast::VarArgsType * ) {} 859 860 void postvisit( const ast::ZeroType * zero ) { 861 if ( ! widen.first ) return; 862 if ( 863 dynamic_cast< const ast::BasicType * >( type2 ) 864 || dynamic_cast< const ast::PointerType * >( type2 ) 865 || dynamic_cast< const ast::EnumInstType * >( type2 ) 866 ) { 867 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 868 result = type2; 869 add_qualifiers( result, zero->qualifiers ); 870 } 871 } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) { 872 result = new ast::BasicType{ 873 ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers }; 874 } 875 } 876 877 void postvisit( const ast::OneType * one ) { 878 if ( ! widen.first ) return; 879 if ( 880 dynamic_cast< const ast::BasicType * >( type2 ) 881 || dynamic_cast< const ast::EnumInstType * >( type2 ) 882 ) { 883 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 884 result = type2; 885 add_qualifiers( result, one->qualifiers ); 886 } 887 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { 888 result = new ast::BasicType{ 889 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 890 } 891 } 892 893 }; 894 895 namespace { 896 ast::ptr< ast::Type > handleReference( 897 const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen, 898 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 899 const ast::OpenVarSet & open 900 ) { 901 ast::ptr<ast::Type> common; 902 ast::AssertionSet have, need; 903 ast::OpenVarSet newOpen{ open }; 904 905 // need unify to bind type variables 906 if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) { 907 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers; 908 PRINT( 909 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl; 910 ) 911 if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) { 912 PRINT( 913 std::cerr << "widen okay" << std::endl; 914 ) 915 add_qualifiers( common, q1 | q2 ); 916 return common; 917 } 918 } 919 920 PRINT( 921 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 922 ) 923 return { nullptr }; 924 } 925 } 926 927 ast::ptr< ast::Type > commonType( 928 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 929 WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env, 930 const ast::OpenVarSet & open 931 ) { 932 unsigned depth1 = type1->referenceDepth(); 933 unsigned depth2 = type2->referenceDepth(); 934 935 if ( depth1 != depth2 ) { // implies depth1 > 0 || depth2 > 0 936 PRINT( 937 std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl; 938 ) 939 ast::ptr< ast::Type > result; 940 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 941 const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >(); 942 943 if ( depth1 > depth2 ) { 944 assert( ref1 ); 945 result = handleReference( ref1->base, type2, widen, symtab, env, open ); 946 } else { // implies depth1 < depth2 947 assert( ref2 ); 948 result = handleReference( type1, ref2->base, widen, symtab, env, open ); 949 } 950 951 if ( result && ref1 ) { 952 // formal is reference, so result should be reference 953 PRINT( 954 std::cerr << "formal is reference; result should be reference" << std::endl; 955 ) 956 result = new ast::ReferenceType{ result, ref1->qualifiers }; 957 } 958 959 PRINT( 960 std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is " 961 "[" << result << "]" << std::endl; 962 ) 963 return result; 964 } 965 // otherwise both are reference types of the same depth and this is handled by the visitor 966 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open }; 967 type1->accept( visitor ); 968 ast::ptr< ast::Type > result = visitor.pass.result; 969 970 // handling for opaque type declarations (?) 971 if ( ! result && widen.second ) { 972 if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) { 973 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 974 auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt ); 975 if ( type->base ) { 976 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 977 ast::AssertionSet have, need; 978 ast::OpenVarSet newOpen{ open }; 979 980 // force t{1,2} to be cloned if its qualifiers must be stripped, so that 981 // type1 and type->base are left unchanged; calling convention forces 982 // {type1,type->base}->strong_ref >= 1 983 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base }; 984 reset_qualifiers( t1 ); 985 reset_qualifiers( t2, q1 ); 986 987 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) { 988 result = t1; 989 reset_qualifiers( result, q1 | q2 ); 990 } 991 } 992 } 993 } 994 } 995 996 return result; 997 } 998 385 999 } // namespace ResolvExpr 386 1000 -
src/ResolvExpr/ConversionCost.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 07:06:19 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Sep 25 15:43:34 201713 // Update Count : 1011 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Aug 12 10:21:00 2019 13 // Update Count : 27 14 14 // 15 15 … … 28 28 29 29 namespace ResolvExpr { 30 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 32 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 33 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 34 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 35 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 30 #if 0 31 const Cost Cost::zero = Cost{ 0, 0, 0, 0, 0, 0, 0 }; 32 const Cost Cost::infinity = Cost{ -1, -1, -1, -1, -1, 1, -1 }; 33 const Cost Cost::unsafe = Cost{ 1, 0, 0, 0, 0, 0, 0 }; 34 const Cost Cost::poly = Cost{ 0, 1, 0, 0, 0, 0, 0 }; 35 const Cost Cost::safe = Cost{ 0, 0, 1, 0, 0, 0, 0 }; 36 const Cost Cost::sign = Cost{ 0, 0, 0, 1, 0, 0, 0 }; 37 const Cost Cost::var = Cost{ 0, 0, 0, 0, 1, 0, 0 }; 38 const Cost Cost::spec = Cost{ 0, 0, 0, 0, 0, -1, 0 }; 39 const Cost Cost::reference = Cost{ 0, 0, 0, 0, 0, 0, 1 }; 40 #endif 36 41 37 42 #if 0 … … 40 45 #define PRINT(x) 41 46 #endif 42 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 43 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { 47 48 Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue, 49 const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 50 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) { 44 51 PRINT( std::cerr << "type inst " << destAsTypeInst->name; ) 45 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {52 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) { 46 53 if ( eqvClass->type ) { 47 return conversionCost( src, eqvClass->type, indexer, env );54 return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env ); 48 55 } else { 49 56 return Cost::infinity; 50 57 } 51 } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {58 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) { 52 59 PRINT( std::cerr << " found" << std::endl; ) 53 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );60 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType ); 54 61 // all typedefs should be gone by this point 55 62 assert( type ); 56 63 if ( type->base ) { 57 return conversionCost( src, type->base, indexer, env ) + Cost::safe; 64 return conversionCost( src, type->base, srcIsLvalue, indexer, env ) 65 + Cost::safe; 58 66 } // if 59 67 } // if … … 71 79 PRINT( std::cerr << "compatible!" << std::endl; ) 72 80 return Cost::zero; 73 } else if ( dynamic_cast< VoidType* >( dest ) ) {81 } else if ( dynamic_cast< const VoidType * >( dest ) ) { 74 82 return Cost::safe; 75 } else if ( ReferenceType * refType = dynamic_cast<ReferenceType * > ( dest ) ) {83 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) { 76 84 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 77 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1,Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){85 return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){ 78 86 return ptrsAssignable( t1, t2, env ); 79 87 }); 80 88 } else { 81 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 89 PassVisitor<ConversionCost> converter( 90 dest, srcIsLvalue, indexer, env, 91 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&)) 92 conversionCost ); 82 93 src->accept( converter ); 83 94 if ( converter.pass.get_cost() == Cost::infinity ) { … … 89 100 } 90 101 91 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 102 static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue, 103 int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 92 104 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; ) 93 105 if ( diff > 0 ) { 94 106 // TODO: document this 95 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func ); 107 Cost cost = convertToReferenceCost( 108 strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue, 109 diff-1, indexer, env, func ); 96 110 cost.incReference(); 97 111 return cost; 98 112 } else if ( diff < -1 ) { 99 113 // TODO: document this 100 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func ); 114 Cost cost = convertToReferenceCost( 115 src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue, 116 diff+1, indexer, env, func ); 101 117 cost.incReference(); 102 118 return cost; 103 119 } else if ( diff == 0 ) { 104 ReferenceType * srcAsRef = dynamic_cast<ReferenceType * >( src );105 ReferenceType * destAsRef = dynamic_cast<ReferenceType * >( dest );120 const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src ); 121 const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest ); 106 122 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 107 123 PRINT( std::cerr << "converting between references" << std::endl; ) 108 Type::Qualifiers tq1 = srcAsRef->base-> get_qualifiers();109 Type::Qualifiers tq2 = destAsRef->base-> get_qualifiers();124 Type::Qualifiers tq1 = srcAsRef->base->tq; 125 Type::Qualifiers tq2 = destAsRef->base->tq; 110 126 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) { 111 127 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) … … 128 144 } else { 129 145 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 130 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 146 PassVisitor<ConversionCost> converter( 147 dest, srcIsLvalue, indexer, env, 148 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&)) 149 conversionCost ); 131 150 src->accept( converter ); 132 151 return converter.pass.get_cost(); 133 152 } // if 134 153 } else { 135 ReferenceType * destAsRef = dynamic_cast<ReferenceType * >( dest );154 const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest ); 136 155 assert( diff == -1 && destAsRef ); 137 156 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 138 157 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 139 158 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 140 if ( src ->get_lvalue()) {159 if ( srcIsLvalue ) { 141 160 PRINT( 142 161 std::cerr << "lvalue to reference conversion" << std::endl; … … 144 163 ) 145 164 // lvalue-to-reference conversion: cv lvalue T => cv T & 146 if ( src-> get_qualifiers() == destAsRef->base->get_qualifiers()) {165 if ( src->tq == destAsRef->base->tq ) { 147 166 return Cost::reference; // cost needs to be non-zero to add cast 148 } if ( src-> get_qualifiers() < destAsRef->base->get_qualifiers()) {167 } if ( src->tq < destAsRef->base->tq ) { 149 168 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 150 169 } else { … … 166 185 } 167 186 168 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 187 Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue, 188 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 169 189 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth(); 170 Cost cost = convertToReferenceCost( src, dest, s depth-ddepth, indexer, env, func );190 Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func ); 171 191 PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; ) 172 192 return cost; 173 193 } 174 194 175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) { 177 } 178 179 /* 180 Old 181 === 182 Double 183 | 184 Float 185 | 186 ULong 187 / \ 188 UInt Long 189 \ / 190 Int 191 | 192 Ushort 193 | 194 Short 195 | 196 Uchar 197 / \ 198 Schar Char 199 200 New 201 === 202 +-----LongDoubleComplex--+ 203 LongDouble--+ | +-LongDoubleImag 204 | +---DoubleComplex---+ | 205 Double------+ | +----DoubleImag 206 | +-FloatComplex-+ | 207 Float---------+ +-------FloatImag 208 | 209 ULongLong 210 | 211 LongLong 212 | 213 ULong 214 / \ 215 UInt Long 216 \ / 217 Int 218 | 219 Ushort 220 | 221 Short 222 | 223 Uchar 224 / \ 225 Schar Char 226 \ / 227 Bool 228 */ 229 230 static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = { 231 /* Src \ Dest: Bool Char SChar UChar Short UShort Int UInt Long ULong LLong ULLong Float Double LDbl FCplex DCplex LDCplex FImag DImag LDImag I128, U128, F80, F128 */ 232 /* Bool */ { 0, 1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 12, 13, 14, 12, 13, 14, -1, -1, -1, 10, 11, 14, 15}, 233 /* Char */ { -1, 0, -1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, 13, 14}, 234 /* SChar */ { -1, -1, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, 13, 14}, 235 /* UChar */ { -1, -1, -1, 0, 1, 2, 3, 4, 4, 5, 6, 7, 10, 11, 12, 10, 11, 12, -1, -1, -1, 8, 9, 12, 13}, 236 /* Short */ { -1, -1, -1, -1, 0, 1, 2, 3, 3, 4, 5, 6, 9, 10, 11, 9, 10, 11, -1, -1, -1, 7, 8, 11, 12}, 237 /* UShort */{ -1, -1, -1, -1, -1, 0, 1, 2, 2, 3, 4, 5, 8, 9, 10, 8, 9, 10, -1, -1, -1, 6, 7, 10, 11}, 238 /* Int */ { -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 7, 8, 9, 7, 8, 9, -1, -1, -1, 5, 6, 9, 10}, 239 /* UInt */ { -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, 8, 9}, 240 /* Long */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, 8, 9}, 241 /* ULong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 5, 6, 7, 5, 6, 7, -1, -1, -1, 3, 4, 7, 8}, 242 /* LLong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 4, 5, 6, 4, 5, 6, -1, -1, -1, 2, 3, 6, 7}, 243 /* ULLong */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 4, 5, 3, 4, 5, -1, -1, -1, 1, 2, 5, 6}, 244 245 /* Float */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 1, 2, 3, -1, -1, -1, -1, -1, 2, 3}, 246 /* Double */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 1, 2, -1, -1, -1, -1, -1, 1, 2}, 247 /* LDbl */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1}, 248 /* FCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, -1, -1, -1, -1, -1, -1}, 249 /* DCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1}, 250 /* LDCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1}, 251 /* FImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 0, 1, 2, -1, -1, -1, -1}, 252 /* DImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, 0, 1, -1, -1, -1, -1}, 253 /* LDImag */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, -1, -1, -1, -1}, 254 255 /* I128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 3, 4, 5, -1, -1, -1, 0, 1, 4, 4}, 256 /* U128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 2, 3, 4, -1, -1, -1, -1, 0, 3, 3}, 257 258 /* F80 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 0, 1}, 259 /* F128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 0}, 260 }; 195 ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 196 : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) { 197 } 198 199 // GENERATED START, DO NOT EDIT 200 // GENERATED BY BasicTypes-gen.cc 201 /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves) 202 _Bool 203 char signed char unsigned char 204 signed short int unsigned short int 205 signed int unsigned int 206 signed long int unsigned long int 207 signed long long int unsigned long long int 208 __int128 unsigned __int128 209 _Float16 _Float16 _Complex 210 _Float32 _Float32 _Complex 211 float float _Complex 212 _Float32x _Float32x _Complex 213 _Float64 _Float64 _Complex 214 double double _Complex 215 _Float64x _Float64x _Complex 216 __float80 217 _Float128 _Float128 _Complex 218 __float128 219 long double long double _Complex 220 _Float128x _Float128x _Complex 221 */ 222 // GENERATED END 223 224 // GENERATED START, DO NOT EDIT 225 // GENERATED BY BasicTypes-gen.cc 226 static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node 227 /* B C SC UC SI SUI I UI LI LUI LLI LLUI IB UIB _FH _FH _F _FC F FC _FX _FXC FD _FDC D DC F80X_FDXC F80 _FB_FLDC FB LD LDC _FBX_FLDXC */ 228 /* B */ { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 16, 18, 17, }, 229 /* C */ { -1, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 15, 17, 16, }, 230 /* SC */ { -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 15, 17, 16, }, 231 /* UC */ { -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 15, 17, 16, }, 232 /* SI */ { -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 14, 16, 15, }, 233 /* SUI */ { -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 14, 16, 15, }, 234 /* I */ { -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 13, 15, 14, }, 235 /* UI */ { -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 13, 15, 14, }, 236 /* LI */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 12, 14, 13, }, 237 /* LUI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 12, 14, 13, }, 238 /* LLI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 11, 13, 12, }, 239 /* LLUI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 11, 13, 12, }, 240 /* IB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 10, 12, 11, }, 241 /* UIB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 10, 12, 11, }, 242 /* _FH */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 9, 11, 10, }, 243 /* _FH */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, -1, 7, -1, -1, 8, -1, 9, }, 244 /* _F */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 8, 10, 9, }, 245 /* _FC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, -1, 6, -1, -1, 7, -1, 8, }, 246 /* F */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 7, 9, 8, }, 247 /* FC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, -1, 5, -1, -1, 6, -1, 7, }, 248 /* _FX */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 6, 8, 7, }, 249 /* _FXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, -1, 4, -1, -1, 5, -1, 6, }, 250 /* FD */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 5, 7, 6, }, 251 /* _FDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 2, -1, -1, 3, -1, -1, 4, -1, 5, }, 252 /* D */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, 4, 5, 4, 6, 5, }, 253 /* DC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, -1, 2, -1, -1, 3, -1, 4, }, 254 /* F80X */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 4, 3, 5, 4, }, 255 /* _FDXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, -1, 2, -1, 3, }, 256 /* F80 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 1, 2, 2, 3, 3, 4, 4, }, 257 /* _FB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 2, 3, 3, }, 258 /* _FLDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, 2, }, 259 /* FB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 1, 2, 2, 3, }, 260 /* LD */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, }, 261 /* LDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, }, 262 /* _FBX */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, }, 263 /* _FLDXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, }, 264 }; // costMatrix 265 static const int maxIntCost = 15; 266 // GENERATED END 261 267 static_assert( 262 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES *BasicType::NUMBER_OF_BASIC_TYPES,263 " Each basic type kind should have a corresponding row in the cost matrix"268 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES, 269 "Missing row in the cost matrix" 264 270 ); 265 271 266 267 void ConversionCost::postvisit( VoidType * ) { 272 // GENERATED START, DO NOT EDIT 273 // GENERATED BY BasicTypes-gen.cc 274 static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion 275 /* B C SC UC SI SUI I UI LI LUI LLI LLUI IB UIB _FH _FH _F _FC F FC _FX _FXC FD _FDC D DC F80X_FDXC F80 _FB_FLDC FB LD LDC _FBX_FLDXC */ 276 /* B */ { 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 277 /* C */ { -1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 278 /* SC */ { -1, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 279 /* UC */ { -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 280 /* SI */ { -1, -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 281 /* SUI */ { -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 282 /* I */ { -1, -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 283 /* UI */ { -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 284 /* LI */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 285 /* LUI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 286 /* LLI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 287 /* LLUI */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 288 /* IB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 289 /* UIB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 290 /* _FH */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 291 /* _FH */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 292 /* _F */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 293 /* _FC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 294 /* F */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 295 /* FC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 296 /* _FX */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 297 /* _FXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 298 /* FD */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 299 /* _FDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 300 /* D */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 301 /* DC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 302 /* F80X */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 303 /* _FDXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 0, -1, -1, 0, -1, 0, }, 304 /* F80 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 305 /* _FB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, }, 306 /* _FLDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 0, -1, 0, }, 307 /* FB */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, }, 308 /* LD */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, }, 309 /* LDC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, }, 310 /* _FBX */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, }, 311 /* _FLDXC */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, }, 312 }; // signMatrix 313 // GENERATED END 314 static_assert( 315 sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES, 316 "Missing row in the sign matrix" 317 ); 318 319 void ConversionCost::postvisit( const VoidType * ) { 268 320 cost = Cost::infinity; 269 321 } 270 322 271 void ConversionCost::postvisit( BasicType *basicType) {272 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {273 int tableResult = costMatrix[ basicType-> get_kind() ][ destAsBasic->get_kind()];323 void ConversionCost::postvisit(const BasicType * basicType) { 324 if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) { 325 int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ]; 274 326 if ( tableResult == -1 ) { 275 327 cost = Cost::unsafe; … … 277 329 cost = Cost::zero; 278 330 cost.incSafe( tableResult ); 279 } // if 280 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 331 cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] ); 332 } // if 333 } else if ( dynamic_cast< const EnumInstType * >( dest ) ) { 281 334 // xxx - not positive this is correct, but appears to allow casting int => enum 282 335 cost = Cost::unsafe; … … 285 338 } 286 339 287 void ConversionCost::postvisit( PointerType * pointerType ) {288 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {340 void ConversionCost::postvisit( const PointerType * pointerType ) { 341 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) { 289 342 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 290 Type::Qualifiers tq1 = pointerType->base-> get_qualifiers();291 Type::Qualifiers tq2 = destAsPtr->base-> get_qualifiers();343 Type::Qualifiers tq1 = pointerType->base->tq; 344 Type::Qualifiers tq2 = destAsPtr->base->tq; 292 345 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 293 346 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) … … 298 351 // types are the same, except otherPointer has more qualifiers 299 352 cost = Cost::safe; 300 } 353 } // if 301 354 } else { 302 355 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); … … 318 371 } 319 372 320 void ConversionCost::postvisit( ArrayType * ) {}321 322 void ConversionCost::postvisit( ReferenceType * refType ) {373 void ConversionCost::postvisit( const ArrayType * ) {} 374 375 void ConversionCost::postvisit( const ReferenceType * refType ) { 323 376 // Note: dest can never be a reference, since it would have been caught in an earlier check 324 assert( ! dynamic_cast< ReferenceType * >( dest ) );377 assert( ! dynamic_cast< const ReferenceType * >( dest ) ); 325 378 // convert reference to rvalue: cv T1 & => T2 326 379 // recursively compute conversion cost from T1 to T2. 327 380 // cv can be safely dropped because of 'implicit dereference' behavior. 328 cost = costFunc( refType->base, dest, indexer, env );329 if ( refType->base-> get_qualifiers() == dest->get_qualifiers()) {381 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env ); 382 if ( refType->base->tq == dest->tq ) { 330 383 cost.incReference(); // prefer exact qualifiers 331 } else if ( refType->base-> get_qualifiers() < dest->get_qualifiers()) {384 } else if ( refType->base->tq < dest->tq ) { 332 385 cost.incSafe(); // then gaining qualifiers 333 386 } else { … … 337 390 } 338 391 339 void ConversionCost::postvisit( FunctionType * ) {}340 341 void ConversionCost::postvisit( StructInstType * inst ) {342 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {392 void ConversionCost::postvisit( const FunctionType * ) {} 393 394 void ConversionCost::postvisit( const StructInstType * inst ) { 395 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) { 343 396 if ( inst->name == destAsInst->name ) { 344 397 cost = Cost::zero; … … 347 400 } 348 401 349 void ConversionCost::postvisit( UnionInstType * inst ) {350 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {402 void ConversionCost::postvisit( const UnionInstType * inst ) { 403 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) { 351 404 if ( inst->name == destAsInst->name ) { 352 405 cost = Cost::zero; … … 355 408 } 356 409 357 void ConversionCost::postvisit( EnumInstType * ) {410 void ConversionCost::postvisit( const EnumInstType * ) { 358 411 static Type::Qualifiers q; 359 412 static BasicType integer( q, BasicType::SignedInt ); 360 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int413 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env ); // safe if dest >= int 361 414 if ( cost < Cost::unsafe ) { 362 415 cost.incSafe(); … … 364 417 } 365 418 366 void ConversionCost::postvisit( TraitInstType * ) {}367 368 void ConversionCost::postvisit( TypeInstType *inst ) {369 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {370 cost = costFunc( eqvClass->type, dest, indexer, env );371 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {419 void ConversionCost::postvisit( const TraitInstType * ) {} 420 421 void ConversionCost::postvisit( const TypeInstType * inst ) { 422 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) { 423 cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env ); 424 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) { 372 425 if ( inst->name == destAsInst->name ) { 373 426 cost = Cost::zero; 374 427 } 375 } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {376 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );428 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) { 429 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType ); 377 430 // all typedefs should be gone by this point 378 431 assert( type ); 379 432 if ( type->base ) { 380 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;381 } // if 382 } // if 383 } 384 385 void ConversionCost::postvisit( TupleType * tupleType ) {433 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe; 434 } // if 435 } // if 436 } 437 438 void ConversionCost::postvisit( const TupleType * tupleType ) { 386 439 Cost c = Cost::zero; 387 if ( TupleType * destAsTuple = dynamic_cast<TupleType * >( dest ) ) {440 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) { 388 441 std::list< Type * >::const_iterator srcIt = tupleType->types.begin(); 389 442 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin(); 390 443 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) { 391 Cost newCost = costFunc( * srcIt++, *destIt++, indexer, env );444 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env ); 392 445 if ( newCost == Cost::infinity ) { 393 446 return; … … 403 456 } 404 457 405 void ConversionCost::postvisit( VarArgsType * ) {406 if ( dynamic_cast< VarArgsType* >( dest ) ) {407 cost = Cost::zero; 408 } 409 } 410 411 void ConversionCost::postvisit( ZeroType * ) {412 if ( dynamic_cast< ZeroType * >( dest ) ) {413 cost = Cost::zero; 414 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {415 // copied from visit(BasicType *) for signed int, but +1 for safe conversions416 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic-> get_kind()];458 void ConversionCost::postvisit( const VarArgsType * ) { 459 if ( dynamic_cast< const VarArgsType * >( dest ) ) { 460 cost = Cost::zero; 461 } 462 } 463 464 void ConversionCost::postvisit( const ZeroType * ) { 465 if ( dynamic_cast< const ZeroType * >( dest ) ) { 466 cost = Cost::zero; 467 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) { 468 // copied from visit(BasicType *) for signed int, but +1 for safe conversions 469 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ]; 417 470 if ( tableResult == -1 ) { 418 471 cost = Cost::unsafe; … … 420 473 cost = Cost::zero; 421 474 cost.incSafe( tableResult + 1 ); 422 } 423 } else if ( dynamic_cast< PointerType* >( dest ) ) { 424 cost = Cost::safe; 425 } 426 } 427 428 void ConversionCost::postvisit( OneType * ) { 429 if ( dynamic_cast< OneType * >( dest ) ) { 430 cost = Cost::zero; 431 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 432 // copied from visit(BasicType*) for signed int, but +1 for safe conversions 433 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 475 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] ); 476 } // if 477 } else if ( dynamic_cast< const PointerType * >( dest ) ) { 478 cost = Cost::zero; 479 cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation 480 } // if 481 } 482 483 void ConversionCost::postvisit( const OneType * ) { 484 if ( dynamic_cast< const OneType * >( dest ) ) { 485 cost = Cost::zero; 486 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) { 487 // copied from visit(BasicType *) for signed int, but +1 for safe conversions 488 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ]; 434 489 if ( tableResult == -1 ) { 435 490 cost = Cost::unsafe; … … 437 492 cost = Cost::zero; 438 493 cost.incSafe( tableResult + 1 ); 494 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] ); 495 } // if 496 } // if 497 } 498 499 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2, 500 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 501 return ptrsAssignable( t1, t2, env ); 502 } 503 504 // TODO: This is used for overload resolution. It might be able to be dropped once the old system 505 // is removed. 506 static Cost localConversionCost( 507 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 508 const ast::TypeEnvironment & env 509 ) { return conversionCost( src, dst, symtab, env ); } 510 511 Cost conversionCost( 512 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 513 const ast::TypeEnvironment & env 514 ) { 515 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 516 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) { 517 if ( eqv->bound ) { 518 return conversionCost(src, eqv->bound, symtab, env ); 519 } else { 520 return Cost::infinity; 439 521 } 440 } 441 } 522 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) { 523 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named ); 524 assertf( type, "Unexpected typedef." ); 525 if ( type->base ) { 526 return conversionCost( src, type->base, symtab, env ) + Cost::safe; 527 } 528 } 529 } 530 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) { 531 return Cost::zero; 532 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { 533 return Cost::safe; 534 } else if ( const ast::ReferenceType * refType = 535 dynamic_cast< const ast::ReferenceType * >( dst ) ) { 536 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable ); 537 } else { 538 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 539 src->accept( converter ); 540 return converter.pass.cost; 541 } 542 } 543 544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, 545 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 546 NumCostCalculation func ) { 547 if ( 0 < diff ) { 548 Cost cost = convertToReferenceCost( 549 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, 550 dst, (diff - 1), symtab, env, func ); 551 cost.incReference(); 552 return cost; 553 } else if ( diff < -1 ) { 554 Cost cost = convertToReferenceCost( 555 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base, 556 (diff + 1), symtab, env, func ); 557 cost.incReference(); 558 return cost; 559 } else if ( 0 == diff ) { 560 const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src ); 561 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst ); 562 if ( srcAsRef && dstAsRef ) { 563 ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers; 564 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers; 565 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 566 srcAsRef->base, dstAsRef->base, symtab, env ) ) { 567 if ( tq1 == tq2 ) { 568 return Cost::zero; 569 } else { 570 return Cost::safe; 571 } 572 } else { 573 int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env ); 574 if ( 0 < assignResult ) { 575 return Cost::safe; 576 } else if ( assignResult < 0 ) { 577 return Cost::unsafe; 578 } 579 } 580 } else { 581 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 582 src->accept( converter ); 583 return converter.pass.cost; 584 } 585 } else { 586 assert( -1 == diff ); 587 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst ); 588 assert( dstAsRef ); 589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) { 590 if ( src->is_lvalue() ) { 591 if ( src->qualifiers == dstAsRef->base->qualifiers ) { 592 return Cost::reference; 593 } else if ( src->qualifiers < dstAsRef->base->qualifiers ) { 594 return Cost::safe; 595 } else { 596 return Cost::unsafe; 597 } 598 } else if ( dstAsRef->base->is_const() ) { 599 return Cost::safe; 600 } else { 601 return Cost::unsafe; 602 } 603 } 604 } 605 return Cost::infinity; 606 } 607 608 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst, 609 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 610 NumCostCalculation func ) { 611 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth(); 612 return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func ); 613 } 614 615 void ConversionCost_new::postvisit( const ast::VoidType * voidType ) { 616 (void)voidType; 617 cost = Cost::infinity; 618 } 619 620 void ConversionCost_new::postvisit( const ast::BasicType * basicType ) { 621 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 622 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ]; 623 if ( tableResult == -1 ) { 624 cost = Cost::unsafe; 625 } else { 626 cost = Cost::zero; 627 cost.incSafe( tableResult ); 628 cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] ); 629 } 630 } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) { 631 // xxx - not positive this is correct, but appears to allow casting int => enum 632 cost = Cost::unsafe; 633 } 634 } 635 636 void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) { 637 if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) { 638 ast::CV::Qualifiers tq1 = pointerType->base->qualifiers; 639 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers; 640 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 641 pointerType->base, dstAsPtr->base, symtab, env ) ) { 642 if ( tq1 == tq2 ) { 643 cost = Cost::zero; 644 } else { 645 cost = Cost::safe; 646 } 647 } else { 648 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env ); 649 if ( 0 < assignResult && tq1 <= tq2 ) { 650 if ( tq1 == tq2 ) { 651 cost = Cost::safe; 652 } else { 653 cost = Cost::safe + Cost::safe; 654 } 655 } else if ( assignResult < 0 ) { 656 cost = Cost::unsafe; 657 } // else Cost::infinity 658 } 659 } 660 } 661 662 void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) { 663 (void)arrayType; 664 } 665 666 void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) { 667 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) ); 668 669 cost = costCalc( refType->base, dst, symtab, env ); 670 if ( refType->base->qualifiers == dst->qualifiers ) { 671 cost.incReference(); 672 } else if ( refType->base->qualifiers < dst->qualifiers ) { 673 cost.incSafe(); 674 } else { 675 cost.incUnsafe(); 676 } 677 } 678 679 void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) { 680 (void)functionType; 681 } 682 683 void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) { 684 if ( const ast::StructInstType * dstAsInst = 685 dynamic_cast< const ast::StructInstType * >( dst ) ) { 686 if ( structInstType->name == dstAsInst->name ) { 687 cost = Cost::zero; 688 } 689 } 690 } 691 692 void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) { 693 if ( const ast::UnionInstType * dstAsInst = 694 dynamic_cast< const ast::UnionInstType * >( dst ) ) { 695 if ( unionInstType->name == dstAsInst->name ) { 696 cost = Cost::zero; 697 } 698 } 699 } 700 701 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) { 702 (void)enumInstType; 703 static const ast::BasicType integer( ast::BasicType::SignedInt ); 704 cost = costCalc( &integer, dst, symtab, env ); 705 if ( cost < Cost::unsafe ) { 706 cost.incSafe(); 707 } 708 } 709 710 void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) { 711 (void)traitInstType; 712 } 713 714 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) { 715 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) { 716 cost = costCalc( eqv->bound, dst, symtab, env ); 717 } else if ( const ast::TypeInstType * dstAsInst = 718 dynamic_cast< const ast::TypeInstType * >( dst ) ) { 719 if ( typeInstType->name == dstAsInst->name ) { 720 cost = Cost::zero; 721 } 722 } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) { 723 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType ); 724 assertf( type, "Unexpected typedef."); 725 if ( type->base ) { 726 cost = costCalc( type->base, dst, symtab, env ) + Cost::safe; 727 } 728 } 729 } 730 731 void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) { 732 Cost c = Cost::zero; 733 if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) { 734 auto srcIt = tupleType->types.begin(); 735 auto dstIt = dstAsTuple->types.begin(); 736 auto srcEnd = tupleType->types.end(); 737 auto dstEnd = dstAsTuple->types.end(); 738 while ( srcIt != srcEnd && dstIt != dstEnd ) { 739 Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env ); 740 if ( newCost == Cost::infinity ) { 741 return; 742 } 743 c += newCost; 744 } 745 if ( dstIt != dstEnd ) { 746 cost = Cost::infinity; 747 } else { 748 cost = c; 749 } 750 } 751 } 752 753 void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) { 754 (void)varArgsType; 755 if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) { 756 cost = Cost::zero; 757 } 758 } 759 760 void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) { 761 (void)zeroType; 762 if ( dynamic_cast< const ast::ZeroType * >( dst ) ) { 763 cost = Cost::zero; 764 } else if ( const ast::BasicType * dstAsBasic = 765 dynamic_cast< const ast::BasicType * >( dst ) ) { 766 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ]; 767 if ( -1 == tableResult ) { 768 cost = Cost::unsafe; 769 } else { 770 cost = Cost::zero; 771 cost.incSafe( tableResult + 1 ); 772 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 773 } 774 } 775 } 776 777 void ConversionCost_new::postvisit( const ast::OneType * oneType ) { 778 (void)oneType; 779 if ( dynamic_cast< const ast::OneType * >( dst ) ) { 780 cost = Cost::zero; 781 } else if ( const ast::BasicType * dstAsBasic = 782 dynamic_cast< const ast::BasicType * >( dst ) ) { 783 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ]; 784 if ( -1 == tableResult ) { 785 cost = Cost::unsafe; 786 } else { 787 cost = Cost::zero; 788 cost.incSafe( tableResult + 1 ); 789 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 790 } 791 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 792 cost = Cost::zero; 793 cost.incSafe( maxIntCost + 2 ); 794 } 795 } 796 797 442 798 } // namespace ResolvExpr 443 799 -
src/ResolvExpr/ConversionCost.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 09:37:28 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:38:24 201713 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Aug 8 16:13:00 2019 13 // Update Count : 6 14 14 // 15 15 … … 20 20 #include "Cost.h" // for Cost 21 21 22 #include "AST/Fwd.hpp" 23 #include "AST/Pass.hpp" // for WithShortCircuiting 22 24 #include "Common/PassVisitor.h" 23 25 #include "SynTree/Visitor.h" // for Visitor … … 31 33 class TypeEnvironment; 32 34 33 typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 35 typedef std::function<Cost(const Type *, const Type *, bool, 36 const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 37 34 38 struct ConversionCost : public WithShortCircuiting { 35 39 public: 36 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 40 ConversionCost( const Type * dest, bool srcIsLvalue, 41 const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 37 42 38 43 Cost get_cost() const { return cost; } 39 44 40 void previsit( BaseSyntaxNode * ) { visit_children = false; }45 void previsit( const BaseSyntaxNode * ) { visit_children = false; } 41 46 42 void postvisit( VoidType * voidType );43 void postvisit( BasicType * basicType );44 void postvisit( PointerType * pointerType );45 void postvisit( ArrayType * arrayType );46 void postvisit( ReferenceType * refType );47 void postvisit( FunctionType * functionType );48 void postvisit( StructInstType * aggregateUseType );49 void postvisit( UnionInstType * aggregateUseType );50 void postvisit( EnumInstType * aggregateUseType );51 void postvisit( TraitInstType * aggregateUseType );52 void postvisit( TypeInstType * aggregateUseType );53 void postvisit( TupleType * tupleType );54 void postvisit( VarArgsType * varArgsType );55 void postvisit( ZeroType * zeroType );56 void postvisit( OneType * oneType );47 void postvisit( const VoidType * voidType ); 48 void postvisit( const BasicType * basicType ); 49 void postvisit( const PointerType * pointerType ); 50 void postvisit( const ArrayType * arrayType ); 51 void postvisit( const ReferenceType * refType ); 52 void postvisit( const FunctionType * functionType ); 53 void postvisit( const StructInstType * aggregateUseType ); 54 void postvisit( const UnionInstType * aggregateUseType ); 55 void postvisit( const EnumInstType * aggregateUseType ); 56 void postvisit( const TraitInstType * aggregateUseType ); 57 void postvisit( const TypeInstType * aggregateUseType ); 58 void postvisit( const TupleType * tupleType ); 59 void postvisit( const VarArgsType * varArgsType ); 60 void postvisit( const ZeroType * zeroType ); 61 void postvisit( const OneType * oneType ); 57 62 protected: 58 Type *dest; 63 const Type * dest; 64 bool srcIsLvalue; 59 65 const SymTab::Indexer &indexer; 60 66 Cost cost; … … 63 69 }; 64 70 65 typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction; 66 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 71 typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction; 72 Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue, 73 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 74 75 // Some function pointer types, differ in return type. 76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, 77 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 78 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *, 79 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 80 81 #warning when the old ConversionCost is removed, get ride of the _new suffix. 82 class ConversionCost_new : public ast::WithShortCircuiting { 83 protected: 84 const ast::Type * dst; 85 const ast::SymbolTable & symtab; 86 const ast::TypeEnvironment & env; 87 CostCalculation costCalc; 88 public: 89 Cost cost; 90 91 ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab, 92 const ast::TypeEnvironment & env, CostCalculation costCalc ) : 93 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity ) 94 {} 95 96 void previsit( const ast::Node * ) { visit_children = false; } 97 98 void postvisit( const ast::VoidType * voidType ); 99 void postvisit( const ast::BasicType * basicType ); 100 void postvisit( const ast::PointerType * pointerType ); 101 void postvisit( const ast::ArrayType * arrayType ); 102 void postvisit( const ast::ReferenceType * refType ); 103 void postvisit( const ast::FunctionType * functionType ); 104 void postvisit( const ast::StructInstType * structInstType ); 105 void postvisit( const ast::UnionInstType * unionInstType ); 106 void postvisit( const ast::EnumInstType * enumInstType ); 107 void postvisit( const ast::TraitInstType * traitInstType ); 108 void postvisit( const ast::TypeInstType * typeInstType ); 109 void postvisit( const ast::TupleType * tupleType ); 110 void postvisit( const ast::VarArgsType * varArgsType ); 111 void postvisit( const ast::ZeroType * zeroType ); 112 void postvisit( const ast::OneType * oneType ); 113 }; 114 115 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest, 116 const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func ); 117 67 118 } // namespace ResolvExpr 68 119 -
src/ResolvExpr/Cost.h
r7951100 rb067d9b 7 7 // Cost.h -- 8 8 // 9 // Author : Richard C. Bilson9 // Author : Peter Buhr and Aaron Moss 10 10 // Created On : Sun May 17 09:39:50 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:35:55 201713 // Update Count : 512 // Last Modified On : Fri Jun 21 11:39:13 2019 13 // Update Count : 63 14 14 // 15 15 … … 17 17 18 18 #include <iostream> 19 #include <cassert> 20 #include <climits> 19 21 20 22 namespace ResolvExpr { 23 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the 24 // specialization cost is a negative value so a correction is needed is a few places. 25 21 26 class Cost { 22 private: 23 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ); 27 union { 28 struct { 29 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 30 // Little-endian => first value is low priority and last is high priority. 31 unsigned char padding; ///< unused 32 unsigned char referenceCost; ///< reference conversions 33 unsigned char specCost; ///< Polymorphic type specializations (type assertions), negative cost 34 unsigned char varCost; ///< Count of polymorphic type variables 35 unsigned char signCost; ///< Count of safe sign conversions 36 unsigned char safeCost; ///< Safe (widening) conversions 37 unsigned char polyCost; ///< Count of parameters and return values bound to some poly type 38 unsigned char unsafeCost; ///< Unsafe (narrowing) conversions 39 #else 40 #error Cost BIG_ENDIAN unsupported 41 #endif 42 } v; 43 uint64_t all; 44 }; 45 static const unsigned char correctb = 0xff; // byte correction for negative spec cost 46 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost 47 public: 48 // Compiler adjusts constants for correct endian. 49 enum : uint64_t { 50 zero = 0x00'00'00'00'00'ff'00'00, 51 infinity = 0xff'ff'ff'ff'ff'00'ff'ff, 52 unsafe = 0x01'00'00'00'00'ff'00'00, 53 poly = 0x00'01'00'00'00'ff'00'00, 54 safe = 0x00'00'01'00'00'ff'00'00, 55 sign = 0x00'00'00'01'00'ff'00'00, 56 var = 0x00'00'00'00'01'ff'00'00, 57 spec = 0x00'00'00'00'00'fe'00'00, 58 reference = 0x00'00'00'00'00'ff'01'00, 59 }; //' 24 60 25 public: 26 Cost & incUnsafe( int inc = 1 ); 27 Cost & incPoly( int inc = 1 ); 28 Cost & incSafe( int inc = 1 ); 29 Cost & incReference( int inc = 1 ); 61 Cost( uint64_t all ) { Cost::all = all; } 62 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) { 63 // Assume little-endian => first value is low priority and last is high priority. 64 v = { 65 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 66 (unsigned char)0, // padding 67 (unsigned char)referenceCost, // low priority 68 (unsigned char)(specCost + correctb), // correct for signedness 69 (unsigned char)varCost, 70 (unsigned char)signCost, 71 (unsigned char)safeCost, 72 (unsigned char)polyCost, 73 (unsigned char)unsafeCost, // high priority 74 #else 75 #error Cost BIG_ENDIAN unsupported 76 #endif 77 }; 78 } 30 79 31 int get_unsafeCost() const { return unsafeCost; } 32 int get_polyCost() const { return polyCost; } 33 int get_safeCost() const { return safeCost; } 34 int get_referenceCost() const { return referenceCost; } 80 int get_unsafeCost() const { return v.unsafeCost; } 81 int get_polyCost() const { return v.polyCost; } 82 int get_safeCost() const { return v.safeCost; } 83 int get_signCost() const { return v.signCost; } 84 int get_varCost() const { return v.varCost; } 85 int get_specCost() const { return -(correctb - v.specCost); } 86 int get_referenceCost() const { return v.referenceCost; } 35 87 36 Cost operator+( const Cost &other ) const; 37 Cost operator-( const Cost &other ) const; 38 Cost &operator+=( const Cost &other ); 39 bool operator<( const Cost &other ) const; 40 bool operator==( const Cost &other ) const; 41 bool operator!=( const Cost &other ) const; 42 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 88 friend bool operator==( const Cost, const Cost ); 89 friend bool operator!=( const Cost lhs, const Cost rhs ); 90 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs 91 int compare( const Cost rhs ) const { 92 if ( all == infinity ) return 1; 93 if ( rhs.all == infinity ) return -1; 94 return all > rhs.all ? 1 : all == rhs.all ? 0 : -1; 95 } 96 friend bool operator<( const Cost lhs, const Cost rhs ); 43 97 44 static const Cost zero; 45 static const Cost infinity; 98 friend Cost operator+( const Cost lhs, const Cost rhs ); 99 100 Cost operator+=( const Cost rhs ) { 101 if ( all == infinity ) return *this; 102 if ( rhs.all == infinity ) { 103 all = infinity; 104 return *this; 105 } 106 all += rhs.all - correctw; // correct for negative spec cost 107 return *this; 108 } 46 109 47 static const Cost unsafe; 48 static const Cost poly; 49 static const Cost safe; 50 static const Cost reference; 51 private: 52 int compare( const Cost &other ) const; 110 Cost incUnsafe( int inc = 1 ) { 111 if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; } 112 return *this; 113 } 53 114 54 int unsafeCost; 55 int polyCost; 56 int safeCost; 57 int referenceCost; 115 Cost incPoly( int inc = 1 ) { 116 if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; } 117 return *this; 118 } 119 120 Cost incSafe( int inc = 1 ) { 121 if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; } 122 return *this; 123 } 124 125 Cost incSign( int inc = 1 ) { 126 if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; } 127 return *this; 128 } 129 130 Cost incVar( int inc = 1 ) { 131 if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; } 132 return *this; 133 } 134 135 Cost decSpec( int dec = 1 ) { 136 if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; } 137 return *this; 138 } 139 140 Cost incReference( int inc = 1 ) { 141 if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; } 142 return *this; 143 } 144 145 friend std::ostream & operator<<( std::ostream & os, const Cost cost ); 58 146 }; 59 147 60 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {} 61 62 inline Cost & Cost::incUnsafe( int inc ) { 63 if ( *this == infinity ) return *this; 64 unsafeCost += inc; 65 return *this; 148 inline bool operator==( const Cost lhs, const Cost rhs ) { 149 return lhs.all == rhs.all; 66 150 } 67 151 68 inline Cost & Cost::incPoly( int inc ) { 69 if ( *this == infinity ) return *this; 70 polyCost += inc; 71 return *this; 152 inline bool operator!=( const Cost lhs, const Cost rhs ) { 153 return !( lhs.all == rhs.all ); 72 154 } 73 155 74 inline Cost & Cost::incSafe( int inc) {75 if ( *this == infinity ) return *this;76 safeCost += inc;77 return *this;156 inline bool operator<( const Cost lhs, const Cost rhs ) { 157 if ( lhs.all == Cost::infinity ) return false; 158 if ( rhs.all == Cost::infinity ) return true; 159 return lhs.all < rhs.all; 78 160 } 79 161 80 inline Cost & Cost::incReference( int inc ) { 81 if ( *this == infinity ) return *this; 82 referenceCost += inc; 83 return *this; 162 inline Cost operator+( const Cost lhs, const Cost rhs ) { 163 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity }; 164 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost 84 165 } 85 166 86 inline Cost Cost::operator+( const Cost &other ) const { 87 if ( *this == infinity || other == infinity ) return infinity; 88 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost ); 89 } 90 91 inline Cost Cost::operator-( const Cost &other ) const { 92 if ( *this == infinity || other == infinity ) return infinity; 93 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost ); 94 } 95 96 inline Cost &Cost::operator+=( const Cost &other ) { 97 if ( *this == infinity ) return *this; 98 if ( other == infinity ) { 99 *this = infinity; 100 return *this; 101 } 102 unsafeCost += other.unsafeCost; 103 polyCost += other.polyCost; 104 safeCost += other.safeCost; 105 referenceCost += other.referenceCost; 106 return *this; 107 } 108 109 inline bool Cost::operator<( const Cost &other ) const { 110 if ( *this == infinity ) return false; 111 if ( other == infinity ) return true; 112 113 if ( unsafeCost > other.unsafeCost ) { 114 return false; 115 } else if ( unsafeCost < other.unsafeCost ) { 116 return true; 117 } else if ( polyCost > other.polyCost ) { 118 return false; 119 } else if ( polyCost < other.polyCost ) { 120 return true; 121 } else if ( safeCost > other.safeCost ) { 122 return false; 123 } else if ( safeCost < other.safeCost ) { 124 return true; 125 } else if ( referenceCost > other.referenceCost ) { 126 return false; 127 } else if ( referenceCost < other.referenceCost ) { 128 return true; 129 } else { 130 return false; 131 } // if 132 } 133 134 inline bool Cost::operator==( const Cost &other ) const { 135 return unsafeCost == other.unsafeCost 136 && polyCost == other.polyCost 137 && safeCost == other.safeCost 138 && referenceCost == other.referenceCost; 139 } 140 141 inline bool Cost::operator!=( const Cost &other ) const { 142 return !( *this == other ); 143 } 144 145 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { 146 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )"; 147 return os; 167 inline std::ostream & operator<<( std::ostream & os, const Cost cost ) { 168 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost() 169 << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost() 170 << ", " << cost.get_referenceCost() << " )"; 148 171 } 149 172 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
r7951100 rb067d9b 16 16 #include <stddef.h> // for size_t 17 17 #include <cassert> // for assertf, assert, safe_dynamic_... 18 #include <deque> 18 19 #include <iostream> // for ostream, operator<<, basic_ost... 19 20 #include <stack> // for stack 20 21 #include <string> // for string, operator<<, allocator 21 22 23 #include "AST/Expr.hpp" // for InitAlternative 24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution 25 #include "AST/Init.hpp" // for Designation 26 #include "AST/Node.hpp" // for readonly 27 #include "AST/Type.hpp" 22 28 #include "Common/Indenter.h" // for Indenter, operator<< 23 29 #include "Common/SemanticError.h" // for SemanticError … … 139 145 ArrayIterator( ArrayType * at ) : array( at ) { 140 146 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 141 base = at-> get_base();147 base = at->base; 142 148 memberIter = createMemberIterator( base ); 143 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @= " );144 setSize( at-> get_dimension());149 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " ); 150 setSize( at->dimension ); 145 151 } 146 152 … … 150 156 151 157 private: 152 void setSize( Expression * expr ) { 153 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 154 try { 155 size = constExpr->intValue(); 156 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 157 } catch ( SemanticErrorException & ) { 158 SemanticError( expr, "Constant expression of non-integral type in array dimension: " ); 159 } 160 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 161 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast 162 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 163 if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) { 164 long long int value; 165 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 166 size = value; 167 } 168 } 158 void setSize( Expression * expr ) { // replace this logic with an eval call 159 auto res = eval(expr); 160 if (res.second) { 161 size = res.first; 169 162 } else { 170 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this163 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) ); 171 164 } 172 165 } … … 592 585 } // namespace ResolvExpr 593 586 587 namespace ast { 588 /// create a new MemberIterator that traverses a type correctly 589 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); 590 591 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry 592 class SimpleIterator final : public MemberIterator { 593 CodeLocation location; 594 readonly< Type > type = nullptr; 595 public: 596 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} 597 598 void setPosition( 599 std::deque< ptr< Expr > >::const_iterator begin, 600 std::deque< ptr< Expr > >::const_iterator end 601 ) override { 602 if ( begin != end ) { 603 SemanticError( location, "Un-designated initializer given non-empty designator" ); 604 } 605 } 606 607 std::deque< InitAlternative > operator* () const override { return first(); } 608 609 operator bool() const override { return type; } 610 611 SimpleIterator & bigStep() override { return smallStep(); } 612 SimpleIterator & smallStep() override { 613 type = nullptr; // empty on increment because no members 614 return *this; 615 } 616 617 const Type * getType() override { return type; } 618 619 const Type * getNext() override { return type; } 620 621 std::deque< InitAlternative > first() const override { 622 if ( type ) return { InitAlternative{ type, new Designation{ location } } }; 623 return {}; 624 } 625 }; 626 627 /// Iterates array types 628 class ArrayIterator final : public MemberIterator { 629 CodeLocation location; 630 readonly< ArrayType > array = nullptr; 631 readonly< Type > base = nullptr; 632 size_t index = 0; 633 size_t size = 0; 634 std::unique_ptr< MemberIterator > memberIter; 635 636 void setSize( const Expr * expr ) { 637 auto res = eval(expr); 638 if ( ! res.second ) { 639 SemanticError( location, 640 toString("Array designator must be a constant expression: ", expr ) ); 641 } 642 size = res.first; 643 } 644 645 public: 646 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 647 : location( loc ), array( at ), base( at->base ) { 648 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 649 memberIter.reset( createMemberIterator( loc, base ) ); 650 if ( at->isVarLen ) { 651 SemanticError( location, at, "VLA initialization does not support @=: " ); 652 } 653 setSize( at->dimension ); 654 } 655 656 void setPosition( const Expr * expr ) { 657 // need to permit integer-constant-expressions, including: integer constants, 658 // enumeration constants, character constants, sizeof expressions, alignof expressions, 659 // cast expressions 660 if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { 661 try { 662 index = constExpr->intValue(); 663 } catch ( SemanticErrorException & ) { 664 SemanticError( expr, 665 "Constant expression of non-integral type in array designator: " ); 666 } 667 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) { 668 setPosition( castExpr->arg ); 669 } else if ( 670 dynamic_cast< const SizeofExpr * >( expr ) 671 || dynamic_cast< const AlignofExpr * >( expr ) 672 ) { 673 index = 0; 674 } else { 675 assertf( false, 676 "bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 677 } 678 } 679 680 void setPosition( 681 std::deque< ptr< Expr > >::const_iterator begin, 682 std::deque< ptr< Expr > >::const_iterator end 683 ) override { 684 if ( begin == end ) return; 685 686 setPosition( *begin ); 687 memberIter->setPosition( ++begin, end ); 688 } 689 690 std::deque< InitAlternative > operator* () const override { return first(); } 691 692 operator bool() const override { return index < size; } 693 694 ArrayIterator & bigStep() override { 695 PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) 696 ++index; 697 memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr ); 698 return *this; 699 } 700 701 ArrayIterator & smallStep() override { 702 PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) 703 if ( memberIter ) { 704 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; ) 705 memberIter->smallStep(); 706 if ( *memberIter ) { 707 PRINT( std::cerr << "has valid member iter" << std::endl; ) 708 return *this; 709 } 710 } 711 return bigStep(); 712 } 713 714 const Type * getType() override { return array; } 715 716 const Type * getNext() override { return base; } 717 718 std::deque< InitAlternative > first() const override { 719 PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) 720 if ( memberIter && *memberIter ) { 721 std::deque< InitAlternative > ret = memberIter->first(); 722 for ( InitAlternative & alt : ret ) { 723 alt.designation.get_and_mutate()->designators.emplace_front( 724 ConstantExpr::from_ulong( location, index ) ); 725 } 726 return ret; 727 } 728 return {}; 729 } 730 }; 731 732 class AggregateIterator : public MemberIterator { 733 protected: 734 using MemberList = std::vector< ptr< Decl > >; 735 736 CodeLocation location; 737 std::string kind; // for debug 738 std::string name; 739 const Type * inst; 740 const MemberList & members; 741 MemberList::const_iterator curMember; 742 bool atbegin = true; // false at first {small,big}Step 743 const Type * curType = nullptr; 744 std::unique_ptr< MemberIterator > memberIter = nullptr; 745 TypeSubstitution sub; 746 747 bool init() { 748 PRINT( std::cerr << "--init()--" << members.size() << std::endl; ) 749 if ( curMember != members.end() ) { 750 if ( auto field = curMember->as< ObjectDecl >() ) { 751 PRINT( std::cerr << "incremented to field: " << field << std::endl; ) 752 curType = field->get_type(); 753 memberIter.reset( createMemberIterator( location, curType ) ); 754 return true; 755 } 756 } 757 return false; 758 } 759 760 AggregateIterator( 761 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 762 const MemberList & ms ) 763 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 764 sub( genericSubstitution( i ) ) { 765 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; ) 766 init(); 767 } 768 769 public: 770 void setPosition( 771 std::deque< ptr< Expr > >::const_iterator begin, 772 std::deque< ptr< Expr > >::const_iterator end 773 ) final { 774 if ( begin == end ) return; 775 776 if ( auto varExpr = begin->as< VariableExpr >() ) { 777 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) { 778 if ( *curMember != varExpr->var ) continue; 779 780 ++begin; 781 782 memberIter.reset( createMemberIterator( location, varExpr->result ) ); 783 curType = varExpr->result; 784 atbegin = curMember == members.begin() && begin == end; 785 memberIter->setPosition( begin, end ); 786 return; 787 } 788 assertf( false, 789 "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 790 } else { 791 assertf( false, 792 "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() ); 793 } 794 } 795 796 std::deque< InitAlternative > operator* () const final { 797 if ( memberIter && *memberIter ) { 798 std::deque< InitAlternative > ret = memberIter->first(); 799 PRINT( std::cerr << "sub: " << sub << std::endl; ) 800 for ( InitAlternative & alt : ret ) { 801 PRINT( std::cerr << "iterating and adding designators" << std::endl; ) 802 alt.designation.get_and_mutate()->designators.emplace_front( 803 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 804 // need to substitute for generic types so that casts are to concrete types 805 PRINT( std::cerr << " type is: " << alt.type; ) 806 sub.apply( alt.type ); // also apply to designation?? 807 PRINT( std::cerr << " ==> " << alt.type << std::endl; ) 808 } 809 return ret; 810 } 811 return {}; 812 } 813 814 AggregateIterator & smallStep() final { 815 PRINT( std::cerr << "smallStep in " << kind << std::endl; ) 816 atbegin = false; 817 if ( memberIter ) { 818 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; ) 819 memberIter->smallStep(); 820 if ( *memberIter ) { 821 PRINT( std::cerr << "success!" << std::endl; ) 822 return *this; 823 } 824 } 825 return bigStep(); 826 } 827 828 AggregateIterator & bigStep() override = 0; 829 830 const Type * getType() final { return inst; } 831 832 const Type * getNext() final { 833 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 834 } 835 836 std::deque< InitAlternative > first() const final { 837 std::deque< InitAlternative > ret; 838 PRINT( std::cerr << "first " << kind << std::endl; ) 839 if ( memberIter && *memberIter ) { 840 PRINT( std::cerr << "adding children" << std::endl; ) 841 ret = memberIter->first(); 842 for ( InitAlternative & alt : ret ) { 843 PRINT( std::cerr << "iterating and adding designators" << std::endl; ) 844 alt.designation.get_and_mutate()->designators.emplace_front( 845 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 846 } 847 } 848 if ( atbegin ) { 849 // only add self if at the very beginning of the structure 850 PRINT( std::cerr << "adding self" << std::endl; ) 851 ret.emplace_front( inst, new Designation{ location } ); 852 } 853 return ret; 854 } 855 }; 856 857 class StructIterator final : public AggregateIterator { 858 public: 859 StructIterator( const CodeLocation & loc, const StructInstType * inst ) 860 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {} 861 862 operator bool() const override { 863 return curMember != members.end() || (memberIter && *memberIter); 864 } 865 866 StructIterator & bigStep() override { 867 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 868 atbegin = false; 869 memberIter = nullptr; 870 curType = nullptr; 871 while ( curMember != members.end() ) { 872 ++curMember; 873 if ( init() ) return *this; 874 } 875 return *this; 876 } 877 }; 878 879 class UnionIterator final : public AggregateIterator { 880 public: 881 UnionIterator( const CodeLocation & loc, const UnionInstType * inst ) 882 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {} 883 884 operator bool() const override { return memberIter && *memberIter; } 885 886 UnionIterator & bigStep() override { 887 // unions only initialize one member 888 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 889 atbegin = false; 890 memberIter = nullptr; 891 curType = nullptr; 892 curMember = members.end(); 893 return *this; 894 } 895 }; 896 897 class TupleIterator final : public AggregateIterator { 898 public: 899 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 900 : AggregateIterator( 901 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 902 ) {} 903 904 operator bool() const override { 905 return curMember != members.end() || (memberIter && *memberIter); 906 } 907 908 TupleIterator & bigStep() override { 909 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 910 atbegin = false; 911 memberIter = nullptr; 912 curType = nullptr; 913 while ( curMember != members.end() ) { 914 ++curMember; 915 if ( init() ) return *this; 916 } 917 return *this; 918 } 919 }; 920 921 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) { 922 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) { 923 if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) { 924 return new StructIterator{ loc, sit }; 925 } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) { 926 return new UnionIterator{ loc, uit }; 927 } else { 928 assertf( 929 dynamic_cast< const EnumInstType * >( aggr ) 930 || dynamic_cast< const TypeInstType * >( aggr ), 931 "Encountered unhandled ReferenceToType in createMemberIterator: %s", 932 toString( type ).c_str() ); 933 return new SimpleIterator{ loc, type }; 934 } 935 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) { 936 return new ArrayIterator{ loc, at }; 937 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) { 938 return new TupleIterator{ loc, tt }; 939 } else { 940 return new SimpleIterator{ loc, type }; 941 } 942 } 943 944 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() { 945 objStack.emplace_back( new SimpleIterator{ loc, type } ); 946 } 947 948 const Designation * CurrentObject::findNext( const Designation * designation ) { 949 using DesignatorChain = std::deque< ptr< Expr > >; 950 PRINT( std::cerr << "___findNext" << std::endl; ) 951 952 // find all the d's 953 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts; 954 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes; 955 for ( const Expr * expr : designation->designators ) { 956 PRINT( std::cerr << "____untyped: " << expr << std::endl; ) 957 auto dit = desigAlts.begin(); 958 if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) { 959 for ( const Type * t : curTypes ) { 960 assert( dit != desigAlts.end() ); 961 962 DesignatorChain & d = *dit; 963 PRINT( std::cerr << "____actual: " << t << std::endl; ) 964 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) { 965 // concatenate identical field names 966 for ( const Decl * mem : refType->lookup( nexpr->name ) ) { 967 if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) { 968 PRINT( std::cerr << "____alt: " << field->type << std::endl; ) 969 DesignatorChain d2 = d; 970 d2.emplace_back( new VariableExpr{ expr->location, field } ); 971 newDesigAlts.emplace_back( std::move( d2 ) ); 972 newTypes.emplace_back( field->type ); 973 } 974 } 975 } 976 977 ++dit; 978 } 979 } else { 980 for ( const Type * t : curTypes ) { 981 assert( dit != desigAlts.end() ); 982 983 DesignatorChain & d = *dit; 984 if ( auto at = dynamic_cast< const ArrayType * >( t ) ) { 985 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; ) 986 d.emplace_back( expr ); 987 newDesigAlts.emplace_back( d ); 988 newTypes.emplace_back( at->base ); 989 } 990 } 991 } 992 993 // reset queue 994 desigAlts = std::move( newDesigAlts ); 995 newDesigAlts.clear(); 996 curTypes = std::move( newTypes ); 997 newTypes.clear(); 998 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() ); 999 } 1000 1001 if ( desigAlts.size() > 1 ) { 1002 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") ); 1003 } else if ( desigAlts.empty() ) { 1004 SemanticError( designation, "No reasonable alternatives for designation: " ); 1005 } 1006 1007 DesignatorChain & d = desigAlts.back(); 1008 PRINT( for ( Expression * expr : d ) { 1009 std::cerr << "____desig: " << expr << std::endl; 1010 } ) // for 1011 assertf( ! curTypes.empty(), "empty designator chosen"); 1012 1013 // set new designators 1014 assertf( ! objStack.empty(), "empty object stack when setting designation" ); 1015 Designation * actualDesignation = 1016 new Designation{ designation->location, DesignatorChain{d} }; 1017 objStack.back()->setPosition( d ); // destroys d 1018 return actualDesignation; 1019 } 1020 1021 void CurrentObject::setNext( const Designation * designation ) { 1022 PRINT( std::cerr << "____setNext" << designation << std::endl; ) 1023 assertf( ! objStack.empty(), "obj stack empty in setNext" ); 1024 objStack.back()->setPosition( designation->designators ); 1025 } 1026 1027 void CurrentObject::increment() { 1028 PRINT( std::cerr << "____increment" << std::endl; ) 1029 if ( objStack.empty() ) return; 1030 PRINT( std::cerr << *objStack.back() << std::endl; ) 1031 objStack.back()->smallStep(); 1032 } 1033 1034 void CurrentObject::enterListInit( const CodeLocation & loc ) { 1035 PRINT( std::cerr << "____entering list init" << std::endl; ) 1036 assertf( ! objStack.empty(), "empty obj stack entering list init" ); 1037 const ast::Type * type = objStack.back()->getNext(); 1038 assert( type ); 1039 objStack.emplace_back( createMemberIterator( loc, type ) ); 1040 } 1041 1042 void CurrentObject::exitListInit() { 1043 PRINT( std::cerr << "____exiting list init" << std::endl; ) 1044 assertf( ! objStack.empty(), "objstack empty" ); 1045 objStack.pop_back(); 1046 if ( ! objStack.empty() ) { 1047 PRINT( std::cerr << *objStack.back() << std::endl; ) 1048 objStack.back()->bigStep(); 1049 } 1050 } 1051 1052 std::deque< InitAlternative > CurrentObject::getOptions() { 1053 PRINT( std::cerr << "____getting current options" << std::endl; ) 1054 assertf( ! objStack.empty(), "objstack empty in getOptions" ); 1055 return **objStack.back(); 1056 } 1057 1058 const Type * CurrentObject::getCurrentType() { 1059 PRINT( std::cerr << "____getting current type" << std::endl; ) 1060 assertf( ! objStack.empty(), "objstack empty in getCurrentType" ); 1061 return objStack.back()->getNext(); 1062 } 1063 } 1064 594 1065 // Local Variables: // 595 1066 // tab-width: 4 // -
src/ResolvExpr/CurrentObject.h
r7951100 rb067d9b 16 16 #pragma once 17 17 18 #include <deque> 18 19 #include <list> // for list 20 #include <memory> // for unique_ptr 19 21 #include <stack> // for stack 22 #include <vector> 23 24 #include "AST/Node.hpp" // for ptr 25 #include "Common/CodeLocation.h" 20 26 21 27 class Designation; … … 52 58 } // namespace ResolvExpr 53 59 60 namespace ast { 61 // AST class types 62 class Designation; 63 struct InitAlternative; 64 class Type; 65 66 /// Iterates members of a type by initializer 67 class MemberIterator { 68 public: 69 virtual ~MemberIterator() {} 70 71 /// Internal set position based on iterator ranges 72 virtual void setPosition( 73 std::deque< ptr< Expr > >::const_iterator it, 74 std::deque< ptr< Expr > >::const_iterator end ) = 0; 75 76 /// walks the current object using the given designators as a guide 77 void setPosition( const std::deque< ptr< Expr > > & designators ) { 78 setPosition( designators.begin(), designators.end() ); 79 } 80 81 /// retrieve the list of possible (Type,Designation) pairs for the current position in the 82 /// current object 83 virtual std::deque< InitAlternative > operator* () const = 0; 84 85 /// true if the iterator is not currently at the end 86 virtual operator bool() const = 0; 87 88 /// moves the iterator by one member in the current object 89 virtual MemberIterator & bigStep() = 0; 90 91 /// moves the iterator by one member in the current subobject 92 virtual MemberIterator & smallStep() = 0; 93 94 /// the type of the current object 95 virtual const Type * getType() = 0; 96 97 /// the type of the current subobject 98 virtual const Type * getNext() = 0; 99 100 /// helper for operator*; aggregates must add designator to each init alternative, but 101 /// adding designators in operator* creates duplicates 102 virtual std::deque< InitAlternative > first() const = 0; 103 }; 104 105 /// Builds initializer lists in resolution 106 class CurrentObject final { 107 std::vector< std::shared_ptr<MemberIterator> > objStack; 108 109 public: 110 CurrentObject() = default; 111 CurrentObject( const CodeLocation & loc, const Type * type ); 112 113 /// resolves unresolved designation 114 const Designation * findNext( const Designation * designation ); 115 /// sets current position using the resolved designation 116 void setNext( const ast::Designation * designation ); 117 /// steps to next sub-object of current object 118 void increment(); 119 /// sets new current object for the duration of this brace-enclosed intializer-list 120 void enterListInit( const CodeLocation & loc ); 121 /// restores previous current object 122 void exitListInit(); 123 /// produces a list of alternatives (Type *, Designation *) for the current sub-object's 124 /// initializer. 125 std::deque< InitAlternative > getOptions(); 126 /// produces the type of the current object but no subobjects 127 const Type * getCurrentType(); 128 }; 129 } // namespace ast 130 54 131 // Local Variables: // 55 132 // tab-width: 4 // -
src/ResolvExpr/ExplodedActual.cc
r7951100 rb067d9b 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Alternative.h--7 // ExplodedActual.cc -- 8 8 // 9 9 // Author : Aaron B. Moss … … 24 24 } 25 25 } 26 27 // Local Variables: // 28 // tab-width: 4 // 29 // mode: c++ // 30 // compile-command: "make install" // 31 // End: // -
src/ResolvExpr/ExplodedActual.h
r7951100 rb067d9b 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Alternative.h --7 // ExplodedActual.h -- 8 8 // 9 9 // Author : Aaron B. Moss … … 32 32 33 33 ExplodedActual() : env(), cost(Cost::zero), exprs() {} 34 35 34 ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer ); 35 ExplodedActual(ExplodedActual&&) = default; 36 ExplodedActual& operator= (ExplodedActual&&) = default; 36 37 }; 37 38 } 39 40 // Local Variables: // 41 // tab-width: 4 // 42 // mode: c++ // 43 // compile-command: "make install" // 44 // End: // -
src/ResolvExpr/FindOpenVars.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 09:42:48 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun May 17 09:45:25 201513 // Update Count : 311 // Last Modified By : Andrew 12 // Last Modified On : Fri Jul 12 14:18:00 2019 13 // Update Count : 4 14 14 // 15 15 … … 19 19 #include <map> // for map<>::mapped_type 20 20 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 21 23 #include "Common/PassVisitor.h" 22 24 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... … … 24 26 25 27 namespace ResolvExpr { 26 struct FindOpenVars : public WithGuards {27 FindOpenVars ( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );28 struct FindOpenVars_old : public WithGuards { 29 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 28 30 29 void previsit( PointerType * pointerType );30 void previsit( ArrayType * arrayType );31 void previsit( FunctionType * functionType );32 void previsit( TupleType * tupleType );31 void previsit( const PointerType * pointerType ); 32 void previsit( const ArrayType * arrayType ); 33 void previsit( const FunctionType * functionType ); 34 void previsit( const TupleType * tupleType ); 33 35 34 void common_action( Type *type );36 void common_action( const Type *type ); 35 37 36 38 OpenVarSet &openVars, &closedVars; … … 39 41 }; 40 42 41 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {42 PassVisitor<FindOpenVars > finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );43 void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) { 44 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen ); 43 45 type->accept( finder ); 44 46 } 45 47 46 FindOpenVars ::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )48 FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) 47 49 : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) { 48 50 } 49 51 50 void FindOpenVars ::common_action( Type *type ) {52 void FindOpenVars_old::common_action( const Type * type ) { 51 53 if ( nextIsOpen ) { 52 for ( Type::ForallList::const_iterator i = type-> get_forall().begin(); i != type->get_forall().end(); ++i ) {54 for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) { 53 55 openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 54 56 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { … … 59 61 } 60 62 } else { 61 for ( Type::ForallList::const_iterator i = type-> get_forall().begin(); i != type->get_forall().end(); ++i ) {63 for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) { 62 64 closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 63 65 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { … … 76 78 } 77 79 78 void FindOpenVars ::previsit(PointerType *pointerType) {80 void FindOpenVars_old::previsit(const PointerType * pointerType) { 79 81 common_action( pointerType ); 80 82 } 81 83 82 void FindOpenVars ::previsit(ArrayType *arrayType) {84 void FindOpenVars_old::previsit(const ArrayType * arrayType) { 83 85 common_action( arrayType ); 84 86 } 85 87 86 void FindOpenVars ::previsit(FunctionType *functionType) {88 void FindOpenVars_old::previsit(const FunctionType * functionType) { 87 89 common_action( functionType ); 88 90 nextIsOpen = ! nextIsOpen; … … 90 92 } 91 93 92 void FindOpenVars ::previsit(TupleType *tupleType) {94 void FindOpenVars_old::previsit(const TupleType * tupleType) { 93 95 common_action( tupleType ); 96 } 97 98 namespace { 99 struct FindOpenVars_new final : public ast::WithGuards { 100 ast::OpenVarSet & open; 101 ast::OpenVarSet & closed; 102 ast::AssertionSet & need; 103 ast::AssertionSet & have; 104 bool nextIsOpen; 105 106 FindOpenVars_new( 107 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 108 ast::AssertionSet & h, FirstMode firstIsOpen ) 109 : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {} 110 111 void previsit( const ast::FunctionType * type ) { 112 // mark open/closed variables 113 if ( nextIsOpen ) { 114 for ( const ast::TypeDecl * decl : type->forall ) { 115 open[ decl->name ] = ast::TypeDecl::Data{ decl }; 116 for ( const ast::DeclWithType * assert : decl->assertions ) { 117 need[ assert ].isUsed = false; 118 } 119 } 120 } else { 121 for ( const ast::TypeDecl * decl : type->forall ) { 122 closed[ decl->name ] = ast::TypeDecl::Data{ decl }; 123 for ( const ast::DeclWithType * assert : decl->assertions ) { 124 have[ assert ].isUsed = false; 125 } 126 } 127 } 128 129 // flip open variables for contained function types 130 nextIsOpen = ! nextIsOpen; 131 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } ); 132 } 133 134 }; 135 } 136 137 void findOpenVars( 138 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 139 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) { 140 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen }; 141 type->accept( finder ); 94 142 } 95 143 } // namespace ResolvExpr -
src/ResolvExpr/FindOpenVars.h
r7951100 rb067d9b 16 16 #pragma once 17 17 18 #include "AST/TypeEnvironment.hpp" // for AssertionSet, OpenVarSet 18 19 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 19 20 20 21 class Type; 22 namespace ast { 23 class Type; 24 } 21 25 22 26 namespace ResolvExpr { 23 27 // Updates open and closed variables and their associated assertions 24 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 28 void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 29 30 enum FirstMode { FirstClosed, FirstOpen }; 31 32 // Updates open and closed variables and their associated assertions 33 void findOpenVars( 34 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 35 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ); 25 36 } // namespace ResolvExpr 26 37 -
src/ResolvExpr/Occurs.cc
r7951100 rb067d9b 24 24 struct Occurs : public WithVisitorRef<Occurs> { 25 25 Occurs( std::string varName, const TypeEnvironment &env ); 26 void previsit( TypeInstType * typeInst );26 void previsit( const TypeInstType * typeInst ); 27 27 28 28 bool result; … … 31 31 }; 32 32 33 bool occurs( Type *type, std::stringvarName, const TypeEnvironment &env ) {33 bool occurs( const Type *type, const std::string & varName, const TypeEnvironment &env ) { 34 34 PassVisitor<Occurs> occur( varName, env ); 35 35 type->accept( occur ); … … 45 45 } 46 46 47 void Occurs::previsit( TypeInstType * typeInst ) {47 void Occurs::previsit( const TypeInstType * typeInst ) { 48 48 /// std::cerr << "searching for vars: "; 49 49 /// std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) ); -
src/ResolvExpr/PolyCost.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 09:50:12 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun May 17 09:52:02 201513 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 19 10:45:00 2019 13 // Update Count : 4 14 14 // 15 15 16 #include "AST/SymbolTable.hpp" 17 #include "AST/Type.hpp" 18 #include "AST/TypeEnvironment.hpp" 16 19 #include "Common/PassVisitor.h" 17 20 #include "SymTab/Indexer.h" // for Indexer … … 54 57 } 55 58 59 // TODO: When the old PolyCost is torn out get rid of the _new suffix. 60 struct PolyCost_new { 61 int result; 62 const ast::SymbolTable &symtab; 63 const ast::TypeEnvironment &env_; 64 65 PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) : 66 result( 0 ), symtab( symtab ), env_( env ) {} 67 68 void previsit( const ast::TypeInstType * type ) { 69 if ( const ast::EqvClass * eqv = env_.lookup( type->name ) ) /* && */ if ( eqv->bound ) { 70 if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) { 71 if ( symtab.lookupType( otherType->name ) ) { 72 // Bound to opaque type. 73 result += 1; 74 } 75 } else { 76 // Bound to concrete type. 77 result += 1; 78 } 79 } 80 } 81 }; 82 83 int polyCost( 84 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 85 ) { 86 ast::Pass<PolyCost_new> costing( symtab, env ); 87 type->accept( costing ); 88 return costing.pass.result; 89 } 90 56 91 } // namespace ResolvExpr 57 92 -
src/ResolvExpr/PtrsAssignable.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 11:44:11 2015 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:36:05 2016 13 // Update Count : 8 14 // 15 11 // Last Modified By : Andrew 12 // Last Modified On : Mon Jun 24 15:29:00 2019 13 // Update Count : 9 14 // 15 16 #include "typeops.h" 17 18 #include "AST/Pass.hpp" 19 #include "AST/Type.hpp" 20 #include "AST/TypeEnvironment.hpp" 16 21 #include "Common/PassVisitor.h" 17 22 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment … … 22 27 namespace ResolvExpr { 23 28 struct PtrsAssignable : public WithShortCircuiting { 24 PtrsAssignable( Type *dest, const TypeEnvironment &env );29 PtrsAssignable( const Type * dest, const TypeEnvironment &env ); 25 30 26 31 int get_result() const { return result; } 27 32 28 void previsit( Type * ) { visit_children = false; }29 30 void postvisit( VoidType * voidType );31 void postvisit( BasicType * basicType );32 void postvisit( PointerType * pointerType );33 void postvisit( ArrayType * arrayType );34 void postvisit( FunctionType * functionType );35 void postvisit( StructInstType * inst );36 void postvisit( UnionInstType * inst );37 void postvisit( EnumInstType * inst );38 void postvisit( TraitInstType * inst );39 void postvisit( TypeInstType * inst );40 void postvisit( TupleType * tupleType );41 void postvisit( VarArgsType * varArgsType );42 void postvisit( ZeroType * zeroType );43 void postvisit( OneType * oneType );33 void previsit( const Type * ) { visit_children = false; } 34 35 void postvisit( const VoidType * voidType ); 36 void postvisit( const BasicType * basicType ); 37 void postvisit( const PointerType * pointerType ); 38 void postvisit( const ArrayType * arrayType ); 39 void postvisit( const FunctionType * functionType ); 40 void postvisit( const StructInstType * inst ); 41 void postvisit( const UnionInstType * inst ); 42 void postvisit( const EnumInstType * inst ); 43 void postvisit( const TraitInstType * inst ); 44 void postvisit( const TypeInstType * inst ); 45 void postvisit( const TupleType * tupleType ); 46 void postvisit( const VarArgsType * varArgsType ); 47 void postvisit( const ZeroType * zeroType ); 48 void postvisit( const OneType * oneType ); 44 49 private: 45 Type *dest;50 const Type * dest; 46 51 int result; 47 52 const TypeEnvironment &env; 48 53 }; 49 54 50 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {55 int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) { 51 56 // std::cerr << "assignable: " << src << " | " << dest << std::endl; 52 if ( TypeInstType *destAsTypeInst = dynamic_cast<TypeInstType* >( dest ) ) {53 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {57 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) { 58 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) { 54 59 return ptrsAssignable( src, eqvClass->type, env ); 55 60 } // if 56 61 } // if 57 if ( dynamic_cast< VoidType* >( dest ) ) {62 if ( dynamic_cast< const VoidType* >( dest ) ) { 58 63 // void * = T * for any T is unsafe 59 64 // xxx - this should be safe, but that currently breaks the build … … 66 71 } 67 72 68 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}69 70 void PtrsAssignable::postvisit( VoidType * ) {73 PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 74 75 void PtrsAssignable::postvisit( const VoidType * ) { 71 76 // T * = void * is disallowed - this is a change from C, where any 72 77 // void * can be assigned or passed to a non-void pointer without a cast. 73 78 } 74 79 75 void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType) {}76 void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType) {}77 void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType) {}78 void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType) {}79 80 void PtrsAssignable::postvisit( __attribute__((unused)) StructInstType *inst) {}81 void PtrsAssignable::postvisit( __attribute__((unused)) UnionInstType *inst) {}82 83 void PtrsAssignable::postvisit( EnumInstType * ) {84 if ( dynamic_cast< BasicType* >( dest ) ) {80 void PtrsAssignable::postvisit( const BasicType * ) {} 81 void PtrsAssignable::postvisit( const PointerType * ) {} 82 void PtrsAssignable::postvisit( const ArrayType * ) {} 83 void PtrsAssignable::postvisit( const FunctionType * ) {} 84 85 void PtrsAssignable::postvisit( const StructInstType * ) {} 86 void PtrsAssignable::postvisit( const UnionInstType * ) {} 87 88 void PtrsAssignable::postvisit( const EnumInstType * ) { 89 if ( dynamic_cast< const BasicType* >( dest ) ) { 85 90 // int * = E *, etc. is safe. This isn't technically correct, as each 86 91 // enum has one basic type that it is compatible with, an that type can … … 92 97 } 93 98 94 void PtrsAssignable::postvisit( __attribute__((unused)) TraitInstType *inst) {}95 void PtrsAssignable::postvisit( TypeInstType *inst ) {96 if ( const EqvClass * eqvClass = env.lookup( inst->get_name()) ) {99 void PtrsAssignable::postvisit( const TraitInstType * ) {} 100 void PtrsAssignable::postvisit( const TypeInstType * inst ) { 101 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) { 97 102 if ( eqvClass->type ) { 98 103 // T * = S * for any S depends on the type bound to T … … 102 107 } 103 108 104 void PtrsAssignable::postvisit( __attribute__((unused)) TupleType *tupleType ) {} 105 void PtrsAssignable::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {} 106 void PtrsAssignable::postvisit( __attribute__((unused)) ZeroType *zeroType ) {} 107 void PtrsAssignable::postvisit( __attribute__((unused)) OneType *oneType ) {} 109 void PtrsAssignable::postvisit( const TupleType * ) {} 110 void PtrsAssignable::postvisit( const VarArgsType * ) {} 111 void PtrsAssignable::postvisit( const ZeroType * ) {} 112 void PtrsAssignable::postvisit( const OneType * ) {} 113 114 // TODO: Get rid of the `_new` suffix when the old version is removed. 115 struct PtrsAssignable_new : public ast::WithShortCircuiting { 116 const ast::Type * dst; 117 const ast::TypeEnvironment & typeEnv; 118 int result; 119 120 PtrsAssignable_new( const ast::Type * dst, const ast::TypeEnvironment & env ) : 121 dst( dst ), typeEnv( env ), result( 0 ) {} 122 123 void previsit( Type * ) { visit_children = false; } 124 125 void postvisit( const ast::EnumInstType * ) { 126 if ( dynamic_cast< const ast::BasicType * >( dst ) ) { 127 // int * = E *, etc. is safe. This isn't technically correct, as each 128 // enum has one basic type that it is compatible with, an that type can 129 // differ from enum to enum. Without replicating GCC's internal logic, 130 // there is no way to know which type this particular enum is compatible 131 // with, so punt on this for now. 132 result = 1; 133 } 134 } 135 void postvisit( const ast::TypeInstType * inst ) { 136 if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name ) ) { 137 if ( eqv->bound ) { 138 // T * = S * for any S depends on the type bound to T 139 result = ptrsAssignable( eqv->bound, dst, typeEnv ); 140 } 141 } 142 } 143 }; 144 145 int ptrsAssignable( const ast::Type * src, const ast::Type * dst, 146 const ast::TypeEnvironment & env ) { 147 if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 148 if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name ) ) { 149 return ptrsAssignable( src, eqv->bound, env ); 150 } 151 } 152 if ( dynamic_cast< const ast::VoidType * >( dst ) ) { 153 return -1; 154 } else { 155 ast::Pass<PtrsAssignable_new> visitor( dst, env ); 156 src->accept( visitor ); 157 return visitor.pass.result; 158 } 159 160 // see ticket #136 (this should be able to replace the visitor). 161 #if 0 162 if ( const ast::TypeInstType * dstAsTypeInst = 163 dynamic_cast< const ast::TypeInstType* >( dst ) ) { 164 if ( const ast::EqvClass * eqv = env.lookup( dstAsTypeInst->get_name() ) ) { 165 return ptrsAssignable( src, eqv->type, env ); 166 } // if 167 } // if 168 if ( dynamic_cast< VoidType* >( dst ) ) { 169 // void * = T * for any T is unsafe 170 // xxx - this should be safe, but that currently breaks the build 171 return -1; 172 } else if ( dynamic_cast< EnumInstType * >( src ) ) { 173 if ( dynamic_cast< BasicType * >( dst ) ) { 174 // int * = E *, etc. is safe. This isn't technically correct, as each 175 // enum has one basic type that it is compatible with, an that type can 176 // differ from enum to enum. Without replicating GCC's internal logic, 177 // there is no way to know which type this particular enum is compatible 178 // with, so punt on this for now. 179 return 1; 180 } 181 } else if ( const ast::TypeInstType * typeInstType = 182 dynamic_cast< const ast::TypeInstType * >( src ) ) { 183 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) { 184 if ( eqv->bound ) { 185 // T * = S * for any S depends on the type bound to T 186 return ptrsAssignable( eqv->bound, dst, env ); 187 } 188 } 189 } 190 return 0; 191 #endif 192 } 108 193 109 194 } // namespace ResolvExpr -
src/ResolvExpr/PtrsCastable.cc
r7951100 rb067d9b 14 14 // 15 15 16 #include "AST/Decl.hpp" 17 #include "AST/Pass.hpp" 18 #include "AST/Type.hpp" 19 #include "AST/TypeEnvironment.hpp" 16 20 #include "Common/PassVisitor.h" 17 21 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment … … 23 27 24 28 namespace ResolvExpr { 25 struct PtrsCastable : public WithShortCircuiting {29 struct PtrsCastable_old : public WithShortCircuiting { 26 30 public: 27 PtrsCastable ( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );31 PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 28 32 29 33 int get_result() const { return result; } 30 34 31 void previsit( Type * ) { visit_children = false; }32 33 void postvisit( VoidType * voidType );34 void postvisit( BasicType * basicType );35 void postvisit( PointerType * pointerType );36 void postvisit( ArrayType * arrayType );37 void postvisit( FunctionType * functionType );38 void postvisit( StructInstType * inst );39 void postvisit( UnionInstType * inst );40 void postvisit( EnumInstType * inst );41 void postvisit( TraitInstType * inst );42 void postvisit( TypeInstType * inst );43 void postvisit( TupleType * tupleType );44 void postvisit( VarArgsType * varArgsType );45 void postvisit( ZeroType * zeroType );46 void postvisit( OneType * oneType );35 void previsit( const Type * ) { visit_children = false; } 36 37 void postvisit( const VoidType * voidType ); 38 void postvisit( const BasicType * basicType ); 39 void postvisit( const PointerType * pointerType ); 40 void postvisit( const ArrayType * arrayType ); 41 void postvisit( const FunctionType * functionType ); 42 void postvisit( const StructInstType * inst ); 43 void postvisit( const UnionInstType * inst ); 44 void postvisit( const EnumInstType * inst ); 45 void postvisit( const TraitInstType * inst ); 46 void postvisit( const TypeInstType * inst ); 47 void postvisit( const TupleType * tupleType ); 48 void postvisit( const VarArgsType * varArgsType ); 49 void postvisit( const ZeroType * zeroType ); 50 void postvisit( const OneType * oneType ); 47 51 private: 48 Type *dest;52 const Type * dest; 49 53 int result; 50 54 const TypeEnvironment &env; … … 53 57 54 58 namespace { 55 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {56 if ( dynamic_cast< FunctionType* >( src ) ) {59 int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 60 if ( dynamic_cast< const FunctionType* >( src ) ) { 57 61 return -1; 58 } else if ( TypeInstType *typeInst = dynamic_cast<TypeInstType* >( src ) ) {59 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name()) ) {60 if ( TypeDecl *tyDecl = dynamic_cast<TypeDecl* >( ntDecl ) ) {61 if ( tyDecl-> get_kind()== TypeDecl::Ftype ) {62 } else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) { 63 if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) { 64 if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) { 65 if ( tyDecl->kind == TypeDecl::Ftype ) { 62 66 return -1; 63 67 } // if 64 68 } //if 65 } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {69 } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) { 66 70 if ( eqvClass->data.kind == TypeDecl::Ftype ) { 67 71 return -1; … … 71 75 return 1; 72 76 } 73 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {77 int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 74 78 return -1 * objectCast( src, env, indexer ); // reverse the sense of objectCast 75 79 } 76 80 } 77 81 78 int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {79 if ( TypeInstType *destAsTypeInst = dynamic_cast<TypeInstType* >( dest ) ) {80 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {82 int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 83 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) { 84 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) { 81 85 // xxx - should this be ptrsCastable? 82 86 return ptrsAssignable( src, eqvClass->type, env ); 83 87 } // if 84 88 } // if 85 if ( dynamic_cast< VoidType* >( dest ) ) {89 if ( dynamic_cast< const VoidType* >( dest ) ) { 86 90 return objectCast( src, env, indexer ); 87 91 } else { 88 PassVisitor<PtrsCastable > ptrs( dest, env, indexer );92 PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer ); 89 93 src->accept( ptrs ); 90 94 return ptrs.pass.get_result(); … … 92 96 } 93 97 94 PtrsCastable ::PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )98 PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) 95 99 : dest( dest ), result( 0 ), env( env ), indexer( indexer ) { 96 100 } 97 101 98 void PtrsCastable ::postvisit(VoidType * ) {99 result = objectCast( dest, env, indexer ); 100 } 101 102 void PtrsCastable ::postvisit(BasicType * ) {103 result = objectCast( dest, env, indexer ); 104 } 105 106 void PtrsCastable ::postvisit(PointerType * ) {107 result = objectCast( dest, env, indexer ); 108 } 109 110 void PtrsCastable ::postvisit(ArrayType * ) {111 result = objectCast( dest, env, indexer ); 112 } 113 114 void PtrsCastable ::postvisit(FunctionType * ) {102 void PtrsCastable_old::postvisit( const VoidType * ) { 103 result = objectCast( dest, env, indexer ); 104 } 105 106 void PtrsCastable_old::postvisit( const BasicType * ) { 107 result = objectCast( dest, env, indexer ); 108 } 109 110 void PtrsCastable_old::postvisit( const PointerType * ) { 111 result = objectCast( dest, env, indexer ); 112 } 113 114 void PtrsCastable_old::postvisit( const ArrayType * ) { 115 result = objectCast( dest, env, indexer ); 116 } 117 118 void PtrsCastable_old::postvisit( const FunctionType * ) { 115 119 // result = -1; 116 120 result = functionCast( dest, env, indexer ); 117 121 } 118 122 119 void PtrsCastable ::postvisit(StructInstType * ) {120 result = objectCast( dest, env, indexer ); 121 } 122 123 void PtrsCastable ::postvisit(UnionInstType * ) {124 result = objectCast( dest, env, indexer ); 125 } 126 127 void PtrsCastable ::postvisit(EnumInstType * ) {128 if ( dynamic_cast< EnumInstType* >( dest ) ) {123 void PtrsCastable_old::postvisit( const StructInstType * ) { 124 result = objectCast( dest, env, indexer ); 125 } 126 127 void PtrsCastable_old::postvisit( const UnionInstType * ) { 128 result = objectCast( dest, env, indexer ); 129 } 130 131 void PtrsCastable_old::postvisit( const EnumInstType * ) { 132 if ( dynamic_cast< const EnumInstType * >( dest ) ) { 129 133 result = 1; 130 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {131 if ( bt-> get_kind()== BasicType::SignedInt ) {134 } else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) { 135 if ( bt->kind == BasicType::SignedInt ) { 132 136 result = 0; 133 137 } else { … … 139 143 } 140 144 141 void PtrsCastable ::postvisit(TraitInstType * ) {}142 143 void PtrsCastable ::postvisit(TypeInstType *inst) {145 void PtrsCastable_old::postvisit( const TraitInstType * ) {} 146 147 void PtrsCastable_old::postvisit( const TypeInstType *inst ) { 144 148 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1; 145 149 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1; 146 150 } 147 151 148 void PtrsCastable::postvisit( TupleType * ) { 149 result = objectCast( dest, env, indexer ); 150 } 151 152 void PtrsCastable::postvisit( VarArgsType * ) { 153 result = objectCast( dest, env, indexer ); 154 } 155 156 void PtrsCastable::postvisit( ZeroType * ) { 157 result = objectCast( dest, env, indexer ); 158 } 159 160 void PtrsCastable::postvisit( OneType * ) { 161 result = objectCast( dest, env, indexer ); 162 } 152 void PtrsCastable_old::postvisit( const TupleType * ) { 153 result = objectCast( dest, env, indexer ); 154 } 155 156 void PtrsCastable_old::postvisit( const VarArgsType * ) { 157 result = objectCast( dest, env, indexer ); 158 } 159 160 void PtrsCastable_old::postvisit( const ZeroType * ) { 161 result = objectCast( dest, env, indexer ); 162 } 163 164 void PtrsCastable_old::postvisit( const OneType * ) { 165 result = objectCast( dest, env, indexer ); 166 } 167 168 namespace { 169 // can this type be cast to an object (1 for yes, -1 for no) 170 int objectCast( 171 const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 172 ) { 173 if ( dynamic_cast< const ast::FunctionType * >( src ) ) { 174 return -1; 175 } else if ( auto inst = dynamic_cast< const ast::TypeInstType * >( src ) ) { 176 if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) { 177 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( named ) ) { 178 if ( tyDecl->kind == ast::TypeVar::Ftype ) { 179 return -1; 180 } 181 } 182 } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) { 183 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) { 184 return -1; 185 } 186 } 187 } 188 189 return 1; 190 } 191 192 // can this type be cast to a function (inverse of objectCast) 193 int functionCast( 194 const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 195 ) { 196 return -1 * objectCast( src, env, symtab ); 197 } 198 199 class PtrsCastable_new : public ast::WithShortCircuiting { 200 const ast::Type * dst; 201 const ast::TypeEnvironment & env; 202 const ast::SymbolTable & symtab; 203 public: 204 int result; 205 206 PtrsCastable_new( 207 const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms ) 208 : dst( d ), env( e ), symtab( syms ), result( 0 ) {} 209 210 void previsit( const ast::Type * ) { visit_children = false; } 211 212 void postvisit( const ast::VoidType * ) { 213 result = objectCast( dst, env, symtab ); 214 } 215 216 void postvisit( const ast::BasicType * ) { 217 result = objectCast( dst, env, symtab ); 218 } 219 220 void postvisit( const ast::PointerType * ) { 221 result = objectCast( dst, env, symtab ); 222 } 223 224 void postvisit( const ast::ArrayType * ) { 225 result = objectCast( dst, env, symtab ); 226 } 227 228 void postvisit( const ast::FunctionType * ) { 229 result = functionCast( dst, env, symtab ); 230 } 231 232 void postvisit( const ast::StructInstType * ) { 233 result = objectCast( dst, env, symtab ); 234 } 235 236 void postvisit( const ast::UnionInstType * ) { 237 result = objectCast( dst, env, symtab ); 238 } 239 240 void postvisit( const ast::EnumInstType * ) { 241 if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) { 242 result = 1; 243 } else if ( auto bt = dynamic_cast< const ast::BasicType * >( dst ) ) { 244 if ( bt->kind == ast::BasicType::SignedInt ) { 245 result = 0; 246 } else { 247 result = 1; 248 } 249 } else { 250 result = objectCast( dst, env, symtab ); 251 } 252 } 253 254 void postvisit( const ast::TraitInstType * ) {} 255 256 void postvisit( const ast::TypeInstType * inst ) { 257 // check trait and destination type are both object or both function 258 result = objectCast( inst, env, symtab ) == objectCast( dst, env, symtab ) ? 1 : -1; 259 } 260 261 void postvisit( const ast::TupleType * ) { 262 result = objectCast( dst, env, symtab ); 263 } 264 265 void postvisit( const ast::VarArgsType * ) { 266 result = objectCast( dst, env, symtab ); 267 } 268 269 void postvisit( const ast::ZeroType * ) { 270 result = objectCast( dst, env, symtab ); 271 } 272 273 void postvisit( const ast::OneType * ) { 274 result = objectCast( dst, env, symtab ); 275 } 276 277 }; 278 } // anonymous namespace 279 280 int ptrsCastable( 281 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 282 const ast::TypeEnvironment & env 283 ) { 284 if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 285 if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) { 286 return ptrsAssignable( src, eqvClass->bound, env ); 287 } 288 } 289 290 if ( dynamic_cast< const ast::VoidType * >( dst ) ) { 291 return objectCast( src, env, symtab ); 292 } else { 293 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab }; 294 src->accept( ptrs ); 295 return ptrs.pass.result; 296 } 297 } 298 163 299 } // namespace ResolvExpr 164 300 -
src/ResolvExpr/RenameVars.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:05:18 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Mar 2 17:36:32 201613 // Update Count : 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Jun 20 17:39:00 2019 13 // Update Count : 8 14 14 // 15 15 … … 19 19 #include <utility> // for pair 20 20 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 21 23 #include "Common/PassVisitor.h" 24 #include "Common/ScopedMap.h" 22 25 #include "Common/SemanticError.h" // for SemanticError 23 26 #include "RenameVars.h" … … 28 31 29 32 namespace ResolvExpr { 30 namespace {31 struct RenameVars {32 RenameVars();33 void reset();34 33 35 void previsit( TypeInstType * instType ); 36 void previsit( Type * ); 37 void postvisit( Type * ); 34 namespace { 35 class RenamingData { 36 int level = 0; 37 int resetCount = 0; 38 ScopedMap< std::string, std::string > nameMap; 38 39 39 private: 40 int level, resetCount; 41 std::list< std::map< std::string, std::string > > mapStack; 42 }; 43 44 PassVisitor<RenameVars> global_renamer; 45 } // namespace 46 47 void renameTyVars( Type * t ) { 48 t->accept( global_renamer ); 49 } 50 51 void resetTyVarRenaming() { 52 global_renamer.pass.reset(); 53 } 54 55 namespace { 56 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 57 mapStack.push_front( std::map< std::string, std::string >() ); 40 public: 41 void reset() { 42 level = 0; 43 ++resetCount; 58 44 } 59 45 60 void RenameVars::reset() { 61 level = 0; 62 resetCount++; 46 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator; 47 48 void rename( TypeInstType * type ) { 49 mapConstIterator it = nameMap.find( type->name ); 50 if ( it != nameMap.end() ) { 51 type->name = it->second; 52 } 63 53 } 64 54 65 void RenameVars::previsit( TypeInstType * instType ) { 66 previsit( (Type *)instType ); 67 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name ); 68 if ( i != mapStack.front().end() ) { 69 instType->name = i->second; 70 } // if 71 } 72 73 void RenameVars::previsit( Type * type ) { 55 void openLevel( Type * type ) { 74 56 if ( ! type->forall.empty() ) { 75 // copies current name mapping into new mapping 76 mapStack.push_front( mapStack.front() ); 57 nameMap.beginScope(); 77 58 // renames all "forall" type names to `_${level}_${name}' 78 59 for ( auto td : type->forall ) { … … 80 61 output << "_" << resetCount << "_" << level << "_" << td->name; 81 62 std::string newname( output.str() ); 82 mapStack.front()[ td->get_name() ] = newname;63 nameMap[ td->get_name() ] = newname; 83 64 td->name = newname; 84 65 // ditto for assertion names, the next level in … … 89 70 } 90 71 91 void RenameVars::postvisit( Type * type ) { 92 // clears name mapping added by typeBefore() 93 if ( ! type->forall.empty() ) { 94 mapStack.pop_front(); 95 } // if 72 void closeLevel( Type * type ) { 73 if ( !type->forall.empty() ) { 74 nameMap.endScope(); 75 } 96 76 } 97 } // namespace 77 78 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 79 mapConstIterator it = nameMap.find( type->name ); 80 if ( it != nameMap.end() ) { 81 ast::TypeInstType * mutType = ast::mutate( type ); 82 mutType->name = it->second; 83 type = mutType; 84 } 85 return type; 86 } 87 88 template<typename NodeT> 89 const NodeT * openLevel( const NodeT * type ) { 90 if ( !type->forall.empty() ) { 91 nameMap.beginScope(); 92 // Load new names from this forall clause and perform renaming. 93 NodeT * mutType = ast::mutate( type ); 94 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 95 std::ostringstream output; 96 output << "_" << resetCount << "_" << level << "_" << td->name; 97 std::string newname( output.str() ); 98 nameMap[ td->name ] = newname; 99 ++level; 100 101 ast::TypeDecl * decl = ast::mutate( td.get() ); 102 decl->name = newname; 103 td = decl; 104 } 105 } 106 return type; 107 } 108 109 template<typename NodeT> 110 const NodeT * closeLevel( const NodeT * type ) { 111 if ( !type->forall.empty() ) { 112 nameMap.endScope(); 113 } 114 return type; 115 } 116 }; 117 118 // Global State: 119 RenamingData renaming; 120 121 struct RenameVars { 122 void previsit( TypeInstType * instType ) { 123 renaming.openLevel( (Type*)instType ); 124 renaming.rename( instType ); 125 } 126 void previsit( Type * type ) { 127 renaming.openLevel( type ); 128 } 129 void postvisit( Type * type ) { 130 renaming.closeLevel( type ); 131 } 132 133 const ast::FunctionType * previsit( const ast::FunctionType * type ) { 134 return renaming.openLevel( type ); 135 } 136 const ast::StructInstType * previsit( const ast::StructInstType * type ) { 137 return renaming.openLevel( type ); 138 } 139 const ast::UnionInstType * previsit( const ast::UnionInstType * type ) { 140 return renaming.openLevel( type ); 141 } 142 const ast::TraitInstType * previsit( const ast::TraitInstType * type ) { 143 return renaming.openLevel( type ); 144 } 145 const ast::TypeInstType * previsit( const ast::TypeInstType * type ) { 146 return renaming.rename( renaming.openLevel( type ) ); 147 } 148 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) { 149 return renaming.closeLevel( type ); 150 } 151 }; 152 153 } // namespace 154 155 void renameTyVars( Type * t ) { 156 PassVisitor<RenameVars> renamer; 157 t->accept( renamer ); 158 } 159 160 const ast::Type * renameTyVars( const ast::Type * t ) { 161 ast::Pass<RenameVars> renamer; 162 return t->accept( renamer ); 163 } 164 165 void resetTyVarRenaming() { 166 renaming.reset(); 167 } 168 98 169 } // namespace ResolvExpr 99 170 -
src/ResolvExpr/RenameVars.h
r7951100 rb067d9b 23 23 #include "SynTree/Visitor.h" // for Visitor 24 24 25 namespace ast { 26 class Type; 27 } 28 25 29 namespace ResolvExpr { 26 30 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 27 31 void renameTyVars( Type * ); 32 const ast::Type * renameTyVars( const ast::Type * ); 28 33 29 34 /// resets internal state of renamer to avoid overflow -
src/ResolvExpr/ResolveTypeof.cc
r7951100 rb067d9b 18 18 #include <cassert> // for assert 19 19 20 #include "AST/CVQualifiers.hpp" 21 #include "AST/Node.hpp" 22 #include "AST/Pass.hpp" 23 #include "AST/Type.hpp" 24 #include "AST/TypeEnvironment.hpp" 20 25 #include "Common/PassVisitor.h" // for PassVisitor 26 #include "Common/utility.h" // for copy 21 27 #include "Resolver.h" // for resolveInVoidContext 22 28 #include "SynTree/Expression.h" // for Expression … … 42 48 } 43 49 44 class ResolveTypeof : public WithShortCircuiting {50 class ResolveTypeof_old : public WithShortCircuiting { 45 51 public: 46 ResolveTypeof ( const SymTab::Indexer &indexer ) : indexer( indexer ) {}52 ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {} 47 53 void premutate( TypeofType *typeofType ); 48 54 Type * postmutate( TypeofType *typeofType ); … … 53 59 54 60 Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) { 55 PassVisitor<ResolveTypeof > mutator( indexer );61 PassVisitor<ResolveTypeof_old> mutator( indexer ); 56 62 return type->acceptMutator( mutator ); 57 63 } 58 64 59 void ResolveTypeof ::premutate( TypeofType * ) {65 void ResolveTypeof_old::premutate( TypeofType * ) { 60 66 visit_children = false; 61 67 } 62 68 63 Type * ResolveTypeof ::postmutate( TypeofType *typeofType ) {69 Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) { 64 70 #if 0 65 71 std::cerr << "resolving typeof: "; … … 67 73 std::cerr << std::endl; 68 74 #endif 69 if ( typeofType->expr ) { 75 // pass on null expression 76 if ( ! typeofType->expr ) return typeofType; 77 78 bool isBasetypeof = typeofType->is_basetypeof; 79 auto oldQuals = typeofType->get_qualifiers().val; 80 81 Type* newType; 82 if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) { 83 // typeof wrapping type 84 newType = tyExpr->type; 85 tyExpr->type = nullptr; 86 delete tyExpr; 87 } else { 88 // typeof wrapping expression 70 89 Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer ); 71 90 assert( newExpr->result && ! newExpr->result->isVoid() ); 72 Type *newType = newExpr->result;91 newType = newExpr->result; 73 92 newExpr->result = nullptr; 74 93 delete typeofType; 75 94 delete newExpr; 95 } 96 97 // clear qualifiers for base, combine with typeoftype quals in any case 98 if ( isBasetypeof ) { 99 // replace basetypeof(<enum>) by int 100 if ( dynamic_cast<EnumInstType*>(newType) ) { 101 Type* newerType = 102 new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 103 newType->attributes }; 104 delete newType; 105 newType = newerType; 106 } 107 newType->get_qualifiers().val 108 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals; 109 } else { 110 newType->get_qualifiers().val |= oldQuals; 111 } 112 113 return newType; 114 } 115 116 namespace { 117 struct ResolveTypeof_new : public ast::WithShortCircuiting { 118 const ast::SymbolTable & localSymtab; 119 120 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {} 121 122 void premutate( const ast::TypeofType * ) { visit_children = false; } 123 124 const ast::Type * postmutate( const ast::TypeofType * typeofType ) { 125 // pass on null expression 126 if ( ! typeofType->expr ) return typeofType; 127 128 ast::ptr< ast::Type > newType; 129 if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) { 130 // typeof wrapping type 131 newType = tyExpr->type; 132 } else { 133 // typeof wrapping expression 134 ast::TypeEnvironment dummy; 135 ast::ptr< ast::Expr > newExpr = 136 resolveInVoidContext( typeofType->expr, localSymtab, dummy ); 137 assert( newExpr->result && ! newExpr->result->isVoid() ); 138 newType = newExpr->result; 139 } 140 141 // clear qualifiers for base, combine with typeoftype quals regardless 142 if ( typeofType->kind == ast::TypeofType::Basetypeof ) { 143 // replace basetypeof(<enum>) by int 144 if ( newType.as< ast::EnumInstType >() ) { 145 newType = new ast::BasicType{ 146 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) }; 147 } 148 reset_qualifiers( 149 newType, 150 ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers ); 151 } else { 152 add_qualifiers( newType, typeofType->qualifiers ); 153 } 154 76 155 return newType; 77 } // if 78 return typeofType; 79 } 156 } 157 }; 158 } // anonymous namespace 159 160 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) { 161 ast::Pass< ResolveTypeof_new > mutator{ symtab }; 162 return type->accept( mutator ); 163 } 164 80 165 } // namespace ResolvExpr 81 166 -
src/ResolvExpr/ResolveTypeof.h
r7951100 rb067d9b 20 20 class Indexer; 21 21 } // namespace SymTab 22 namespace ast { 23 class Type; 24 class SymbolTable; 25 } 22 26 23 27 namespace ResolvExpr { 24 28 Type *resolveTypeof( Type*, const SymTab::Indexer &indexer ); 29 const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & ); 25 30 } // namespace ResolvExpr 26 31 -
src/ResolvExpr/Resolver.cc
r7951100 rb067d9b 7 7 // Resolver.cc -- 8 8 // 9 // Author : Richard C. Bilson9 // 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 : Sat Feb 17 11:19:40 201813 // Update Count : 2 1311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Wed May 29 11:00:00 2019 13 // Update Count : 241 14 14 // 15 15 16 #include <stddef.h> // for NULL17 16 #include <cassert> // for strict_dynamic_cast, assert 18 17 #include <memory> // for allocator, allocator_traits<... 19 18 #include <tuple> // for get 20 #include <vector> 19 #include <vector> // for vector 21 20 22 21 #include "Alternative.h" // for Alternative, AltList 23 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp" 24 #include "CandidateFinder.hpp" 25 #include "CurrentObject.h" // for CurrentObject 26 #include "RenameVars.h" // for RenameVars, global_renamer 27 #include "Resolver.h" 28 #include "ResolvMode.h" // for ResolvMode 29 #include "typeops.h" // for extractResultType 30 #include "Unify.h" // for unify 31 #include "AST/Chain.hpp" 32 #include "AST/Decl.hpp" 33 #include "AST/Init.hpp" 34 #include "AST/Pass.hpp" 35 #include "AST/Print.hpp" 36 #include "AST/SymbolTable.hpp" 37 #include "AST/Type.hpp" 24 38 #include "Common/PassVisitor.h" // for PassVisitor 25 39 #include "Common/SemanticError.h" // for SemanticError 26 40 #include "Common/utility.h" // for ValueGuard, group_iterate 27 #include "CurrentObject.h" // for CurrentObject28 41 #include "InitTweak/GenInit.h" 29 42 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt 30 #include "RenameVars.h" // for RenameVars, global_renamer31 43 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 #include "ResolveTypeof.h" // for resolveTypeof33 #include "Resolver.h"34 44 #include "SymTab/Autogen.h" // for SizeType 35 45 #include "SymTab/Indexer.h" // for Indexer … … 42 52 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 43 53 #include "Tuples/Tuples.h" 44 #include "typeops.h" // for extractResultType 45 #include "Unify.h" // for unify 54 #include "Validate/FindSpecialDecls.h" // for SizeType 46 55 47 56 using namespace std; 48 57 49 58 namespace ResolvExpr { 50 struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {51 Resolver () {}52 Resolver ( const SymTab::Indexer & other ) {59 struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd { 60 Resolver_old() {} 61 Resolver_old( const SymTab::Indexer & other ) { 53 62 indexer = other; 54 63 } 55 64 56 void previsit( FunctionDecl *functionDecl ); 57 void postvisit( FunctionDecl *functionDecl ); 58 void previsit( ObjectDecl *objectDecll ); 59 void previsit( TypeDecl *typeDecl ); 65 void previsit( FunctionDecl * functionDecl ); 66 void postvisit( FunctionDecl * functionDecl ); 67 void previsit( ObjectDecl * objectDecll ); 60 68 void previsit( EnumDecl * enumDecl ); 61 69 void previsit( StaticAssertDecl * assertDecl ); … … 64 72 void previsit( PointerType * at ); 65 73 66 void previsit( ExprStmt * exprStmt );67 void previsit( AsmExpr * asmExpr );68 void previsit( AsmStmt * asmStmt );69 void previsit( IfStmt * ifStmt );70 void previsit( WhileStmt * whileStmt );71 void previsit( ForStmt * forStmt );72 void previsit( SwitchStmt * switchStmt );73 void previsit( CaseStmt * caseStmt );74 void previsit( BranchStmt * branchStmt );75 void previsit( ReturnStmt * returnStmt );76 void previsit( ThrowStmt * throwStmt );77 void previsit( CatchStmt * catchStmt );74 void previsit( ExprStmt * exprStmt ); 75 void previsit( AsmExpr * asmExpr ); 76 void previsit( AsmStmt * asmStmt ); 77 void previsit( IfStmt * ifStmt ); 78 void previsit( WhileStmt * whileStmt ); 79 void previsit( ForStmt * forStmt ); 80 void previsit( SwitchStmt * switchStmt ); 81 void previsit( CaseStmt * caseStmt ); 82 void previsit( BranchStmt * branchStmt ); 83 void previsit( ReturnStmt * returnStmt ); 84 void previsit( ThrowStmt * throwStmt ); 85 void previsit( CatchStmt * catchStmt ); 78 86 void previsit( WaitForStmt * stmt ); 79 void previsit( WithStmt * withStmt ); 80 81 void previsit( SingleInit *singleInit ); 82 void previsit( ListInit *listInit ); 83 void previsit( ConstructorInit *ctorInit ); 87 88 void previsit( SingleInit * singleInit ); 89 void previsit( ListInit * listInit ); 90 void previsit( ConstructorInit * ctorInit ); 84 91 private: 85 92 typedef std::list< Initializer * >::iterator InitIterator; … … 88 95 void handlePtrType( PtrType * type ); 89 96 90 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );91 97 void fallbackInit( ConstructorInit * ctorInit ); 92 98 … … 96 102 }; 97 103 104 struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd { 105 void previsit( FunctionDecl * ); 106 void previsit( WithStmt * ); 107 108 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ); 109 }; 110 98 111 void resolve( std::list< Declaration * > translationUnit ) { 99 PassVisitor<Resolver > resolver;112 PassVisitor<Resolver_old> resolver; 100 113 acceptAll( translationUnit, resolver ); 101 114 } 102 115 103 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {104 PassVisitor<Resolver > resolver( indexer );116 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) { 117 PassVisitor<Resolver_old> resolver( indexer ); 105 118 maybeAccept( decl, resolver ); 106 119 } 107 120 108 121 namespace { 109 struct DeleteFinder : public WithShortCircuiting {122 struct DeleteFinder_old : public WithShortCircuiting { 110 123 DeletedExpr * delExpr = nullptr; 111 124 void previsit( DeletedExpr * expr ) { … … 121 134 122 135 DeletedExpr * findDeletedExpr( Expression * expr ) { 123 PassVisitor<DeleteFinder > finder;136 PassVisitor<DeleteFinder_old> finder; 124 137 expr->accept( finder ); 125 138 return finder.pass.delExpr; … … 127 140 128 141 namespace { 129 struct StripCasts {142 struct StripCasts_old { 130 143 Expression * postmutate( CastExpr * castExpr ) { 131 144 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 140 153 141 154 static void strip( Expression *& expr ) { 142 PassVisitor<StripCasts > stripper;155 PassVisitor<StripCasts_old> stripper; 143 156 expr = expr->acceptMutator( stripper ); 144 157 } 145 158 }; 146 159 147 void finishExpr( Expression *& expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {160 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) { 148 161 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 149 162 env.makeSubstitution( *expr->env ); 150 StripCasts ::strip( expr ); // remove unnecessary casts that may be buried in an expression163 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 151 164 } 152 165 153 166 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 154 167 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 155 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {168 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 156 169 // cast is to the same type as its argument, so it's unnecessary -- remove it 157 170 expr = castExpr->arg; … … 165 178 166 179 namespace { 167 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {180 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 168 181 assertf( untyped, "expected a non-null expression." ); 182 183 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 184 static unsigned recursion_level = 0; 185 186 ++recursion_level; 169 187 TypeEnvironment env; 170 188 AlternativeFinder finder( indexer, env ); 171 finder.find( untyped, adjust, prune, failFast ); 189 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 190 --recursion_level; 172 191 173 192 #if 0 … … 182 201 #endif 183 202 203 // produce filtered list of alternatives 184 204 AltList candidates; 185 205 for ( Alternative & alt : finder.get_alternatives() ) { … … 189 209 } 190 210 191 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 192 // choose the lowest cost expression among the candidates 211 // produce invalid error if no candidates 212 if ( candidates.empty() ) { 213 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 214 } 215 216 // search for cheapest candidate 193 217 AltList winners; 194 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 195 if ( winners.size() == 0 ) { 196 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 197 } else if ( winners.size() != 1 ) { 218 bool seen_undeleted = false; 219 for ( unsigned i = 0; i < candidates.size(); ++i ) { 220 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 221 222 if ( c > 0 ) continue; // skip more expensive than winner 223 224 if ( c < 0 ) { 225 // reset on new cheapest 226 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 227 winners.clear(); 228 } else /* if ( c == 0 ) */ { 229 if ( findDeletedExpr( candidates[i].expr ) ) { 230 // skip deleted expression if already seen one equivalent-cost not 231 if ( seen_undeleted ) continue; 232 } else if ( ! seen_undeleted ) { 233 // replace list of equivalent-cost deleted expressions with one non-deleted 234 winners.clear(); 235 seen_undeleted = true; 236 } 237 } 238 239 winners.emplace_back( std::move( candidates[i] ) ); 240 } 241 242 // promote alternative.cvtCost to .cost 243 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 244 for ( Alternative& winner : winners ) { 245 winner.cost = winner.cvtCost; 246 } 247 248 // produce ambiguous errors, if applicable 249 if ( winners.size() != 1 ) { 198 250 std::ostringstream stream; 199 251 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 204 256 } 205 257 206 // there is one unambiguous interpretation - move the expression into the with statement 207 Alternative & choice = winners.front(); 208 if ( findDeletedExpr( choice.expr ) ) { 258 // single selected choice 259 Alternative& choice = winners.front(); 260 261 // fail on only expression deleted 262 if ( ! seen_undeleted ) { 209 263 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 210 264 } 265 266 // xxx - check for ambiguous expressions 267 268 // output selected choice 211 269 alt = std::move( choice ); 212 270 } 213 271 214 272 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 215 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {273 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) { 216 274 if ( ! untyped ) return; 217 275 Alternative choice; 218 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast);276 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode ); 219 277 finishExpr( choice.expr, choice.env, untyped->env ); 220 278 delete untyped; … … 231 289 232 290 // used in resolveTypeof 233 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer ) {291 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) { 234 292 TypeEnvironment env; 235 293 return resolveInVoidContext( expr, indexer, env ); 236 294 } 237 295 238 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {296 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) { 239 297 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 240 298 // interpretations, an exception has already been thrown. 241 299 assertf( expr, "expected a non-null expression." ); 242 300 243 static CastExpr untyped( nullptr ); // cast to void244 untyped .location = expr->location;301 CastExpr * untyped = new CastExpr( expr ); // cast to void 302 untyped->location = expr->location; 245 303 246 304 // set up and resolve expression cast to void 247 untyped.arg = expr;248 305 Alternative choice; 249 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true);306 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() ); 250 307 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 308 assert( castExpr ); 251 309 env = std::move( choice.env ); 252 310 … … 256 314 257 315 // unlink the arg so that it isn't deleted twice at the end of the program 258 untyped .arg = nullptr;316 untyped->arg = nullptr; 259 317 return ret; 260 318 } 261 319 262 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {320 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 263 321 resetTyVarRenaming(); 264 322 TypeEnvironment env; … … 269 327 } 270 328 271 void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {329 void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 272 330 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 273 331 } … … 288 346 if ( dynamic_cast< EnumInstType * >( type ) ) { 289 347 return true; 290 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {348 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) { 291 349 return bt->isInteger(); 292 350 } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) { … … 297 355 } 298 356 299 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {357 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 300 358 findKindExpression( untyped, indexer, "condition", isIntegralType ); 301 359 } 302 360 } 303 361 304 void Resolver::previsit( ObjectDecl *objectDecl ) { 305 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer ); 306 objectDecl->set_type( new_type ); 307 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 308 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes 309 // initContext because of a function type can contain object declarations in the return and parameter types. So 310 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting 311 // the RHS. 312 GuardValue( currentObject ); 313 currentObject = CurrentObject( objectDecl->get_type() ); 314 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 315 // enumerator initializers should not use the enum type to initialize, since 316 // the enum type is still incomplete at this point. Use signed int instead. 317 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 318 } 319 } 320 321 template< typename PtrType > 322 void Resolver::handlePtrType( PtrType * type ) { 323 if ( type->get_dimension() ) { 324 findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer ); 325 } 326 } 327 328 void Resolver::previsit( ArrayType * at ) { 329 handlePtrType( at ); 330 } 331 332 void Resolver::previsit( PointerType * pt ) { 333 handlePtrType( pt ); 334 } 335 336 void Resolver::previsit( TypeDecl *typeDecl ) { 337 if ( typeDecl->get_base() ) { 338 Type *new_type = resolveTypeof( typeDecl->get_base(), indexer ); 339 typeDecl->set_base( new_type ); 340 } // if 341 } 342 343 void Resolver::previsit( FunctionDecl *functionDecl ) { 344 #if 0 345 std::cerr << "resolver visiting functiondecl "; 346 functionDecl->print( std::cerr ); 347 std::cerr << std::endl; 348 #endif 349 Type *new_type = resolveTypeof( functionDecl->type, indexer ); 350 functionDecl->set_type( new_type ); 351 GuardValue( functionReturn ); 352 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 353 362 363 bool isStructOrUnion( const Alternative & alt ) { 364 Type * t = alt.expr->result->stripReferences(); 365 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 366 } 367 368 void resolveWithExprs( std::list< Declaration * > & translationUnit ) { 369 PassVisitor<ResolveWithExprs> resolver; 370 acceptAll( translationUnit, resolver ); 371 } 372 373 void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 374 for ( Expression *& expr : withExprs ) { 375 // only struct- and union-typed expressions are viable candidates 376 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 377 378 // if with expression might be impure, create a temporary so that it is evaluated once 379 if ( Tuples::maybeImpure( expr ) ) { 380 static UniqueName tmpNamer( "_with_tmp_" ); 381 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 382 expr = new VariableExpr( tmp ); 383 newStmts.push_back( new DeclStmt( tmp ) ); 384 if ( InitTweak::isConstructable( tmp->type ) ) { 385 // generate ctor/dtor and resolve them 386 tmp->init = InitTweak::genCtorInit( tmp ); 387 tmp->accept( *visitor ); 388 } 389 } 390 } 391 } 392 393 void ResolveWithExprs::previsit( WithStmt * withStmt ) { 394 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 395 } 396 397 void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) { 354 398 { 355 399 // resolve with-exprs with parameters in scope and add any newly generated declarations to the … … 367 411 } 368 412 369 void Resolver::postvisit( FunctionDecl *functionDecl ) { 370 // default value expressions have an environment which shouldn't be there and trips up later passes. 371 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 372 // see how it's useful. 413 void Resolver_old::previsit( ObjectDecl * objectDecl ) { 414 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 415 // class-variable initContext is changed multiple time because the LHS is analysed twice. 416 // The second analysis changes initContext because of a function type can contain object 417 // declarations in the return and parameter types. So each value of initContext is 418 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 419 GuardValue( currentObject ); 420 currentObject = CurrentObject( objectDecl->get_type() ); 421 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 422 // enumerator initializers should not use the enum type to initialize, since 423 // the enum type is still incomplete at this point. Use signed int instead. 424 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 425 } 426 } 427 428 template< typename PtrType > 429 void Resolver_old::handlePtrType( PtrType * type ) { 430 if ( type->get_dimension() ) { 431 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); 432 } 433 } 434 435 void Resolver_old::previsit( ArrayType * at ) { 436 handlePtrType( at ); 437 } 438 439 void Resolver_old::previsit( PointerType * pt ) { 440 handlePtrType( pt ); 441 } 442 443 void Resolver_old::previsit( FunctionDecl * functionDecl ) { 444 #if 0 445 std::cerr << "resolver visiting functiondecl "; 446 functionDecl->print( std::cerr ); 447 std::cerr << std::endl; 448 #endif 449 GuardValue( functionReturn ); 450 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 451 } 452 453 void Resolver_old::postvisit( FunctionDecl * functionDecl ) { 454 // default value expressions have an environment which shouldn't be there and trips up 455 // later passes. 456 // xxx - it might be necessary to somehow keep the information from this environment, but I 457 // can't currently see how it's useful. 373 458 for ( Declaration * d : functionDecl->type->parameters ) { 374 459 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 381 466 } 382 467 383 void Resolver ::previsit( EnumDecl * ) {468 void Resolver_old::previsit( EnumDecl * ) { 384 469 // in case we decide to allow nested enums 385 470 GuardValue( inEnumDecl ); … … 387 472 } 388 473 389 void Resolver ::previsit( StaticAssertDecl * assertDecl ) {474 void Resolver_old::previsit( StaticAssertDecl * assertDecl ) { 390 475 findIntegralExpression( assertDecl->condition, indexer ); 391 476 } 392 477 393 void Resolver ::previsit( ExprStmt *exprStmt ) {478 void Resolver_old::previsit( ExprStmt * exprStmt ) { 394 479 visit_children = false; 395 480 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); … … 397 482 } 398 483 399 void Resolver ::previsit( AsmExpr *asmExpr ) {484 void Resolver_old::previsit( AsmExpr * asmExpr ) { 400 485 visit_children = false; 401 486 findVoidExpression( asmExpr->operand, indexer ); … … 405 490 } 406 491 407 void Resolver ::previsit( AsmStmt *asmStmt ) {492 void Resolver_old::previsit( AsmStmt * asmStmt ) { 408 493 visit_children = false; 409 494 acceptAll( asmStmt->get_input(), *visitor ); … … 411 496 } 412 497 413 void Resolver ::previsit( IfStmt *ifStmt ) {498 void Resolver_old::previsit( IfStmt * ifStmt ) { 414 499 findIntegralExpression( ifStmt->condition, indexer ); 415 500 } 416 501 417 void Resolver ::previsit( WhileStmt *whileStmt ) {502 void Resolver_old::previsit( WhileStmt * whileStmt ) { 418 503 findIntegralExpression( whileStmt->condition, indexer ); 419 504 } 420 505 421 void Resolver ::previsit( ForStmt *forStmt ) {506 void Resolver_old::previsit( ForStmt * forStmt ) { 422 507 if ( forStmt->condition ) { 423 508 findIntegralExpression( forStmt->condition, indexer ); … … 429 514 } 430 515 431 void Resolver ::previsit( SwitchStmt *switchStmt ) {516 void Resolver_old::previsit( SwitchStmt * switchStmt ) { 432 517 GuardValue( currentObject ); 433 518 findIntegralExpression( switchStmt->condition, indexer ); … … 436 521 } 437 522 438 void Resolver ::previsit( CaseStmt *caseStmt ) {523 void Resolver_old::previsit( CaseStmt * caseStmt ) { 439 524 if ( caseStmt->condition ) { 440 525 std::list< InitAlternative > initAlts = currentObject.getOptions(); … … 455 540 } 456 541 457 void Resolver ::previsit( BranchStmt *branchStmt ) {542 void Resolver_old::previsit( BranchStmt * branchStmt ) { 458 543 visit_children = false; 459 544 // must resolve the argument for a computed goto … … 466 551 } 467 552 468 void Resolver ::previsit( ReturnStmt *returnStmt ) {553 void Resolver_old::previsit( ReturnStmt * returnStmt ) { 469 554 visit_children = false; 470 555 if ( returnStmt->expr ) { … … 473 558 } 474 559 475 void Resolver ::previsit( ThrowStmt *throwStmt ) {560 void Resolver_old::previsit( ThrowStmt * throwStmt ) { 476 561 visit_children = false; 477 562 // TODO: Replace *exception type with &exception type. 478 563 if ( throwStmt->get_expr() ) { 479 StructDecl * exception_decl = 480 indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 564 const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 481 565 assert( exception_decl ); 482 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl) );566 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) ); 483 567 findSingleExpression( throwStmt->expr, exceptType, indexer ); 484 568 } 485 569 } 486 570 487 void Resolver ::previsit( CatchStmt *catchStmt ) {571 void Resolver_old::previsit( CatchStmt * catchStmt ) { 488 572 if ( catchStmt->cond ) { 489 573 findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer ); … … 500 584 } 501 585 502 void Resolver ::previsit( WaitForStmt * stmt ) {586 void Resolver_old::previsit( WaitForStmt * stmt ) { 503 587 visit_children = false; 504 588 … … 582 666 583 667 // Make sure we don't widen any existing bindings 584 for ( auto & i : resultEnv ) { 585 i.allowWidening = false; 586 } 668 resultEnv.forbidWidening(); 587 669 588 670 // Find any unbound type variables … … 592 674 auto param_end = function->parameters.end(); 593 675 594 int n_mutex_ arg= 0;676 int n_mutex_param = 0; 595 677 596 678 // For every arguments of its set, check if it matches one of the parameter … … 602 684 // We ran out of parameters but still have arguments 603 685 // this function doesn't match 604 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_ arg, "\n" ));686 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" )); 605 687 } 606 688 607 n_mutex_ arg++;689 n_mutex_param++; 608 690 609 691 // Check if the argument matches the parameter type in the current scope … … 628 710 // Check if parameters are missing 629 711 if( advance_to_mutex( param, param_end ) ) { 712 do { 713 n_mutex_param++; 714 param++; 715 } while( advance_to_mutex( param, param_end ) ); 716 630 717 // We ran out of arguments but still have parameters left 631 718 // this function doesn't match 632 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_ arg, "\n" ));719 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" )); 633 720 } 634 721 … … 646 733 647 734 } 648 catch( SemanticErrorException & e ) {735 catch( SemanticErrorException & e ) { 649 736 errors.append( e ); 650 737 } 651 738 } 652 739 } 653 catch( SemanticErrorException & e ) {740 catch( SemanticErrorException & e ) { 654 741 errors.append( e ); 655 742 } … … 694 781 } 695 782 696 bool isStructOrUnion( const Alternative & alt ) { 697 Type * t = alt.expr->result->stripReferences(); 698 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 699 } 700 701 void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 702 for ( Expression *& expr : withExprs ) { 703 // only struct- and union-typed expressions are viable candidates 704 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 705 706 // if with expression might be impure, create a temporary so that it is evaluated once 707 if ( Tuples::maybeImpure( expr ) ) { 708 static UniqueName tmpNamer( "_with_tmp_" ); 709 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 710 expr = new VariableExpr( tmp ); 711 newStmts.push_back( new DeclStmt( tmp ) ); 712 if ( InitTweak::isConstructable( tmp->type ) ) { 713 // generate ctor/dtor and resolve them 714 tmp->init = InitTweak::genCtorInit( tmp ); 715 tmp->accept( *visitor ); 716 } 717 } 718 } 719 } 720 721 void Resolver::previsit( WithStmt * withStmt ) { 722 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 723 } 724 725 template< typename T > 726 bool isCharType( T t ) { 783 bool isCharType( Type * t ) { 727 784 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) { 728 785 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || … … 732 789 } 733 790 734 void Resolver ::previsit( SingleInit *singleInit ) {791 void Resolver_old::previsit( SingleInit * singleInit ) { 735 792 visit_children = false; 736 793 // resolve initialization using the possibilities as determined by the currentObject cursor … … 746 803 initExpr->expr = nullptr; 747 804 std::swap( initExpr->env, newExpr->env ); 748 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 749 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 805 // InitExpr may have inferParams in the case where the expression specializes a function 806 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 807 // sufficient. 750 808 newExpr->spliceInferParams( initExpr ); 751 809 delete initExpr; 752 810 753 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 811 // get the actual object's type (may not exactly match what comes back from the resolver 812 // due to conversions) 754 813 Type * initContext = currentObject.getCurrentType(); 755 814 … … 762 821 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 763 822 if ( isCharType( pt->get_base() ) ) { 764 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 765 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 823 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) { 824 // strip cast if we're initializing a char[] with a char *, 825 // e.g. char x[] = "hello"; 766 826 newExpr = ce->get_arg(); 767 827 ce->set_arg( nullptr ); … … 781 841 } 782 842 783 void Resolver ::previsit( ListInit * listInit ) {843 void Resolver_old::previsit( ListInit * listInit ) { 784 844 visit_children = false; 785 845 // move cursor into brace-enclosed initializer-list 786 846 currentObject.enterListInit(); 787 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 847 // xxx - fix this so that the list isn't copied, iterator should be used to change current 848 // element 788 849 std::list<Designation *> newDesignations; 789 850 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 790 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving791 // the initializer against that object.851 // iterate designations and initializers in pairs, moving the cursor to the current 852 // designated object and resolving the initializer against that object. 792 853 Designation * des = std::get<0>(p); 793 854 Initializer * init = std::get<1>(p); … … 815 876 816 877 // ConstructorInit - fall back on C-style initializer 817 void Resolver ::fallbackInit( ConstructorInit * ctorInit ) {878 void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) { 818 879 // could not find valid constructor, or found an intrinsic constructor 819 880 // fall back on C-style initializer 820 881 delete ctorInit->get_ctor(); 821 ctorInit->set_ctor( NULL);882 ctorInit->set_ctor( nullptr ); 822 883 delete ctorInit->get_dtor(); 823 ctorInit->set_dtor( NULL);884 ctorInit->set_dtor( nullptr ); 824 885 maybeAccept( ctorInit->get_init(), *visitor ); 825 886 } … … 828 889 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) { 829 890 assert( ctorInit ); 830 PassVisitor<Resolver > resolver( indexer );891 PassVisitor<Resolver_old> resolver( indexer ); 831 892 ctorInit->accept( resolver ); 832 893 } … … 834 895 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) { 835 896 assert( stmtExpr ); 836 PassVisitor<Resolver > resolver( indexer );897 PassVisitor<Resolver_old> resolver( indexer ); 837 898 stmtExpr->accept( resolver ); 838 899 stmtExpr->computeResult(); … … 840 901 } 841 902 842 void Resolver ::previsit( ConstructorInit *ctorInit ) {903 void Resolver_old::previsit( ConstructorInit * ctorInit ) { 843 904 visit_children = false; 844 905 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit … … 864 925 865 926 // xxx - todo -- what about arrays? 866 // if ( dtor == NULL&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {927 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 867 928 // // can reduce the constructor down to a SingleInit using the 868 929 // // second argument from the ctor call, since 869 930 // delete ctorInit->get_ctor(); 870 // ctorInit->set_ctor( NULL);931 // ctorInit->set_ctor( nullptr ); 871 932 872 933 // Expression * arg = … … 874 935 // } 875 936 } 937 938 /////////////////////////////////////////////////////////////////////////// 939 // 940 // *** NEW RESOLVER *** 941 // 942 /////////////////////////////////////////////////////////////////////////// 943 944 namespace { 945 /// Finds deleted expressions in an expression tree 946 struct DeleteFinder_new final : public ast::WithShortCircuiting { 947 const ast::DeletedExpr * delExpr = nullptr; 948 949 void previsit( const ast::DeletedExpr * expr ) { 950 if ( delExpr ) { visit_children = false; } 951 else { delExpr = expr; } 952 } 953 954 void previsit( const ast::Expr * ) { 955 if ( delExpr ) { visit_children = false; } 956 } 957 }; 958 } // anonymous namespace 959 960 /// Check if this expression is or includes a deleted expression 961 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 962 ast::Pass<DeleteFinder_new> finder; 963 expr->accept( finder ); 964 return finder.pass.delExpr; 965 } 966 967 namespace { 968 /// always-accept candidate filter 969 bool anyCandidate( const Candidate & ) { return true; } 970 971 /// Calls the CandidateFinder and finds the single best candidate 972 CandidateRef findUnfinishedKindExpression( 973 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 974 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 975 ) { 976 if ( ! untyped ) return nullptr; 977 978 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 979 static unsigned recursion_level = 0; 980 981 ++recursion_level; 982 ast::TypeEnvironment env; 983 CandidateFinder finder{ symtab, env }; 984 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 985 --recursion_level; 986 987 // produce a filtered list of candidates 988 CandidateList candidates; 989 for ( auto & cand : finder.candidates ) { 990 if ( pred( *cand ) ) { candidates.emplace_back( cand ); } 991 } 992 993 // produce invalid error if no candidates 994 if ( candidates.empty() ) { 995 SemanticError( untyped, 996 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""), 997 "expression: ") ); 998 } 999 1000 // search for cheapest candidate 1001 CandidateList winners; 1002 bool seen_undeleted = false; 1003 for ( CandidateRef & cand : candidates ) { 1004 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost ); 1005 1006 if ( c > 0 ) continue; // skip more expensive than winner 1007 1008 if ( c < 0 ) { 1009 // reset on new cheapest 1010 seen_undeleted = ! findDeletedExpr( cand->expr ); 1011 winners.clear(); 1012 } else /* if ( c == 0 ) */ { 1013 if ( findDeletedExpr( cand->expr ) ) { 1014 // skip deleted expression if already seen one equivalent-cost not 1015 if ( seen_undeleted ) continue; 1016 } else if ( ! seen_undeleted ) { 1017 // replace list of equivalent-cost deleted expressions with one non-deleted 1018 winners.clear(); 1019 seen_undeleted = true; 1020 } 1021 } 1022 1023 winners.emplace_back( std::move( cand ) ); 1024 } 1025 1026 // promote candidate.cvtCost to .cost 1027 promoteCvtCost( winners ); 1028 1029 // produce ambiguous errors, if applicable 1030 if ( winners.size() != 1 ) { 1031 std::ostringstream stream; 1032 stream << "Cannot choose between " << winners.size() << " alternatives for " 1033 << kind << (kind != "" ? " " : "") << "expression\n"; 1034 ast::print( stream, untyped ); 1035 stream << " Alternatives are:\n"; 1036 print( stream, winners, 1 ); 1037 SemanticError( untyped->location, stream.str() ); 1038 } 1039 1040 // single selected choice 1041 CandidateRef & choice = winners.front(); 1042 1043 // fail on only expression deleted 1044 if ( ! seen_undeleted ) { 1045 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative " 1046 "includes deleted identifier in " ); 1047 } 1048 1049 return std::move( choice ); 1050 } 1051 1052 /// Strips extraneous casts out of an expression 1053 struct StripCasts_new final { 1054 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) { 1055 if ( 1056 castExpr->isGenerated 1057 && typesCompatible( castExpr->arg->result, castExpr->result ) 1058 ) { 1059 // generated cast is the same type as its argument, remove it after keeping env 1060 return ast::mutate_field( 1061 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 1062 } 1063 return castExpr; 1064 } 1065 1066 static void strip( ast::ptr< ast::Expr > & expr ) { 1067 ast::Pass< StripCasts_new > stripper; 1068 expr = expr->accept( stripper ); 1069 } 1070 }; 1071 1072 /// Swaps argument into expression pointer, saving original environment 1073 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) { 1074 ast::ptr< ast::TypeSubstitution > env = expr->env; 1075 expr.set_and_mutate( newExpr )->env = env; 1076 } 1077 1078 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 1079 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) { 1080 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1081 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) { 1082 // cast is to the same type as its argument, remove it 1083 swap_and_save_env( expr, castExpr->arg ); 1084 } 1085 } 1086 } 1087 1088 /// Establish post-resolver invariants for expressions 1089 void finishExpr( 1090 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, 1091 const ast::TypeSubstitution * oldenv = nullptr 1092 ) { 1093 // set up new type substitution for expression 1094 ast::ptr< ast::TypeSubstitution > newenv = 1095 oldenv ? oldenv : new ast::TypeSubstitution{}; 1096 env.writeToSubstitution( *newenv.get_and_mutate() ); 1097 expr.get_and_mutate()->env = std::move( newenv ); 1098 // remove unncecessary casts 1099 StripCasts_new::strip( expr ); 1100 } 1101 } // anonymous namespace 1102 1103 1104 ast::ptr< ast::Expr > resolveInVoidContext( 1105 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1106 ) { 1107 assertf( expr, "expected a non-null expression" ); 1108 1109 // set up and resolve expression cast to void 1110 ast::CastExpr * untyped = new ast::CastExpr{ expr }; 1111 CandidateRef choice = findUnfinishedKindExpression( 1112 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1113 1114 // a cast expression has either 0 or 1 interpretations (by language rules); 1115 // if 0, an exception has already been thrown, and this code will not run 1116 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1117 env = std::move( choice->env ); 1118 1119 return castExpr->arg; 1120 } 1121 1122 namespace { 1123 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1124 /// context. 1125 ast::ptr< ast::Expr > findVoidExpression( 1126 const ast::Expr * untyped, const ast::SymbolTable & symtab 1127 ) { 1128 resetTyVarRenaming(); 1129 ast::TypeEnvironment env; 1130 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env ); 1131 finishExpr( newExpr, env, untyped->env ); 1132 return newExpr; 1133 } 1134 1135 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 1136 /// lowest cost, returning the resolved version 1137 ast::ptr< ast::Expr > findKindExpression( 1138 const ast::Expr * untyped, const ast::SymbolTable & symtab, 1139 std::function<bool(const Candidate &)> pred = anyCandidate, 1140 const std::string & kind = "", ResolvMode mode = {} 1141 ) { 1142 if ( ! untyped ) return {}; 1143 CandidateRef choice = 1144 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode ); 1145 finishExpr( choice->expr, choice->env, untyped->env ); 1146 return std::move( choice->expr ); 1147 } 1148 1149 /// Resolve `untyped` to the single expression whose candidate is the best match 1150 ast::ptr< ast::Expr > findSingleExpression( 1151 const ast::Expr * untyped, const ast::SymbolTable & symtab 1152 ) { 1153 return findKindExpression( untyped, symtab ); 1154 } 1155 } // anonymous namespace 1156 1157 ast::ptr< ast::Expr > findSingleExpression( 1158 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1159 ) { 1160 assert( untyped && type ); 1161 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 1162 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab ); 1163 removeExtraneousCast( newExpr, symtab ); 1164 return newExpr; 1165 } 1166 1167 namespace { 1168 /// Predicate for "Candidate has integral type" 1169 bool hasIntegralType( const Candidate & i ) { 1170 const ast::Type * type = i.expr->result; 1171 1172 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) { 1173 return bt->isInteger(); 1174 } else if ( 1175 dynamic_cast< const ast::EnumInstType * >( type ) 1176 || dynamic_cast< const ast::ZeroType * >( type ) 1177 || dynamic_cast< const ast::OneType * >( type ) 1178 ) { 1179 return true; 1180 } else return false; 1181 } 1182 1183 /// Resolve `untyped` as an integral expression, returning the resolved version 1184 ast::ptr< ast::Expr > findIntegralExpression( 1185 const ast::Expr * untyped, const ast::SymbolTable & symtab 1186 ) { 1187 return findKindExpression( untyped, symtab, hasIntegralType, "condition" ); 1188 } 1189 1190 /// check if a type is a character type 1191 bool isCharType( const ast::Type * t ) { 1192 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) { 1193 return bt->kind == ast::BasicType::Char 1194 || bt->kind == ast::BasicType::SignedChar 1195 || bt->kind == ast::BasicType::UnsignedChar; 1196 } 1197 return false; 1198 } 1199 1200 /// Advance a type itertor to the next mutex parameter 1201 template<typename Iter> 1202 inline bool nextMutex( Iter & it, const Iter & end ) { 1203 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; } 1204 return it != end; 1205 } 1206 } 1207 1208 class Resolver_new final 1209 : public ast::WithSymbolTable, public ast::WithGuards, 1210 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 1211 public ast::WithStmtsToAdd<> { 1212 1213 ast::ptr< ast::Type > functionReturn = nullptr; 1214 ast::CurrentObject currentObject; 1215 bool inEnumDecl = false; 1216 1217 public: 1218 Resolver_new() = default; 1219 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 1220 1221 void previsit( const ast::FunctionDecl * ); 1222 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * ); 1223 void previsit( const ast::ObjectDecl * ); 1224 void previsit( const ast::EnumDecl * ); 1225 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * ); 1226 1227 const ast::ArrayType * previsit( const ast::ArrayType * ); 1228 const ast::PointerType * previsit( const ast::PointerType * ); 1229 1230 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1231 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1232 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1233 const ast::IfStmt * previsit( const ast::IfStmt * ); 1234 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1235 const ast::ForStmt * previsit( const ast::ForStmt * ); 1236 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1237 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1238 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1239 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1240 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1241 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1242 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 1243 1244 const ast::SingleInit * previsit( const ast::SingleInit * ); 1245 const ast::ListInit * previsit( const ast::ListInit * ); 1246 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 1247 }; 1248 1249 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) { 1250 ast::Pass< Resolver_new > resolver; 1251 accept_all( translationUnit, resolver ); 1252 } 1253 1254 ast::ptr< ast::Init > resolveCtorInit( 1255 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab 1256 ) { 1257 assert( ctorInit ); 1258 ast::Pass< Resolver_new > resolver{ symtab }; 1259 return ctorInit->accept( resolver ); 1260 } 1261 1262 ast::ptr< ast::Expr > resolveStmtExpr( 1263 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab 1264 ) { 1265 assert( stmtExpr ); 1266 ast::Pass< Resolver_new > resolver{ symtab }; 1267 ast::ptr< ast::Expr > ret = stmtExpr; 1268 ret = ret->accept( resolver ); 1269 strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult(); 1270 return ret; 1271 } 1272 1273 void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) { 1274 GuardValue( functionReturn ); 1275 functionReturn = extractResultType( functionDecl->type ); 1276 } 1277 1278 const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) { 1279 // default value expressions have an environment which shouldn't be there and trips up 1280 // later passes. 1281 ast::ptr< ast::FunctionDecl > ret = functionDecl; 1282 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) { 1283 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1284 1285 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) { 1286 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 1287 if ( init->value->env == nullptr ) continue; 1288 // clone initializer minus the initializer environment 1289 ast::chain_mutate( ret ) 1290 ( &ast::FunctionDecl::type ) 1291 ( &ast::FunctionType::params )[i] 1292 ( &ast::ObjectDecl::init ) 1293 ( &ast::SingleInit::value )->env = nullptr; 1294 1295 assert( functionDecl != ret.get() || functionDecl->unique() ); 1296 assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env ); 1297 } 1298 } 1299 } 1300 return ret.get(); 1301 } 1302 1303 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) { 1304 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 1305 // class-variable `initContext` is changed multiple times because the LHS is analyzed 1306 // twice. The second analysis changes `initContext` because a function type can contain 1307 // object declarations in the return and parameter types. Therefore each value of 1308 // `initContext` is retained so the type on the first analysis is preserved and used for 1309 // selecting the RHS. 1310 GuardValue( currentObject ); 1311 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() }; 1312 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 1313 // enumerator initializers should not use the enum type to initialize, since the 1314 // enum type is still incomplete at this point. Use `int` instead. 1315 currentObject = ast::CurrentObject{ 1316 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; 1317 } 1318 } 1319 1320 void Resolver_new::previsit( const ast::EnumDecl * ) { 1321 // in case we decide to allow nested enums 1322 GuardValue( inEnumDecl ); 1323 inEnumDecl = false; 1324 } 1325 1326 const ast::StaticAssertDecl * Resolver_new::previsit( 1327 const ast::StaticAssertDecl * assertDecl 1328 ) { 1329 return ast::mutate_field( 1330 assertDecl, &ast::StaticAssertDecl::cond, 1331 findIntegralExpression( assertDecl->cond, symtab ) ); 1332 } 1333 1334 template< typename PtrType > 1335 const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) { 1336 if ( type->dimension ) { 1337 #warning should use new equivalent to Validate::SizeType rather than sizeType here 1338 ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt }; 1339 ast::mutate_field( 1340 type, &PtrType::dimension, 1341 findSingleExpression( type->dimension, sizeType, symtab ) ); 1342 } 1343 return type; 1344 } 1345 1346 const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) { 1347 return handlePtrType( at, symtab ); 1348 } 1349 1350 const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) { 1351 return handlePtrType( pt, symtab ); 1352 } 1353 1354 const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1355 visit_children = false; 1356 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 1357 1358 return ast::mutate_field( 1359 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) ); 1360 } 1361 1362 const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1363 visit_children = false; 1364 1365 asmExpr = ast::mutate_field( 1366 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) ); 1367 1368 if ( asmExpr->inout ) { 1369 asmExpr = ast::mutate_field( 1370 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) ); 1371 } 1372 1373 return asmExpr; 1374 } 1375 1376 const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1377 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input ); 1378 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output ); 1379 visit_children = false; 1380 return asmStmt; 1381 } 1382 1383 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1384 return ast::mutate_field( 1385 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) ); 1386 } 1387 1388 const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1389 return ast::mutate_field( 1390 whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) ); 1391 } 1392 1393 const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1394 if ( forStmt->cond ) { 1395 forStmt = ast::mutate_field( 1396 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) ); 1397 } 1398 1399 if ( forStmt->inc ) { 1400 forStmt = ast::mutate_field( 1401 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) ); 1402 } 1403 1404 return forStmt; 1405 } 1406 1407 const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1408 GuardValue( currentObject ); 1409 switchStmt = ast::mutate_field( 1410 switchStmt, &ast::SwitchStmt::cond, 1411 findIntegralExpression( switchStmt->cond, symtab ) ); 1412 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 1413 return switchStmt; 1414 } 1415 1416 const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1417 if ( caseStmt->cond ) { 1418 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions(); 1419 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral " 1420 "expression." ); 1421 1422 ast::ptr< ast::Expr > untyped = 1423 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1424 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab ); 1425 1426 // case condition cannot have a cast in C, so it must be removed here, regardless of 1427 // whether it would perform a conversion. 1428 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) { 1429 swap_and_save_env( newExpr, castExpr->arg ); 1430 } 1431 1432 caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr ); 1433 } 1434 return caseStmt; 1435 } 1436 1437 const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1438 visit_children = false; 1439 // must resolve the argument of a computed goto 1440 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1441 // computed goto argument is void* 1442 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} }; 1443 branchStmt = ast::mutate_field( 1444 branchStmt, &ast::BranchStmt::computedTarget, 1445 findSingleExpression( branchStmt->computedTarget, target, symtab ) ); 1446 } 1447 return branchStmt; 1448 } 1449 1450 const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1451 visit_children = false; 1452 if ( returnStmt->expr ) { 1453 returnStmt = ast::mutate_field( 1454 returnStmt, &ast::ReturnStmt::expr, 1455 findSingleExpression( returnStmt->expr, functionReturn, symtab ) ); 1456 } 1457 return returnStmt; 1458 } 1459 1460 const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1461 visit_children = false; 1462 if ( throwStmt->expr ) { 1463 const ast::StructDecl * exceptionDecl = 1464 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 1465 assert( exceptionDecl ); 1466 ast::ptr< ast::Type > exceptType = 1467 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } }; 1468 throwStmt = ast::mutate_field( 1469 throwStmt, &ast::ThrowStmt::expr, 1470 findSingleExpression( throwStmt->expr, exceptType, symtab ) ); 1471 } 1472 return throwStmt; 1473 } 1474 1475 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1476 if ( catchStmt->cond ) { 1477 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool }; 1478 catchStmt = ast::mutate_field( 1479 catchStmt, &ast::CatchStmt::cond, 1480 findSingleExpression( catchStmt->cond, boolType, symtab ) ); 1481 } 1482 return catchStmt; 1483 } 1484 1485 const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1486 visit_children = false; 1487 1488 // Resolve all clauses first 1489 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 1490 const ast::WaitForStmt::Clause & clause = stmt->clauses[i]; 1491 1492 ast::TypeEnvironment env; 1493 CandidateFinder funcFinder{ symtab, env }; 1494 1495 // Find all candidates for a function in canonical form 1496 funcFinder.find( clause.target.func, ResolvMode::withAdjustment() ); 1497 1498 if ( funcFinder.candidates.empty() ) { 1499 stringstream ss; 1500 ss << "Use of undeclared indentifier '"; 1501 ss << clause.target.func.strict_as< ast::NameExpr >()->name; 1502 ss << "' in call to waitfor"; 1503 SemanticError( stmt->location, ss.str() ); 1504 } 1505 1506 if ( clause.target.args.empty() ) { 1507 SemanticError( stmt->location, 1508 "Waitfor clause must have at least one mutex parameter"); 1509 } 1510 1511 // Find all alternatives for all arguments in canonical form 1512 std::vector< CandidateFinder > argFinders = 1513 funcFinder.findSubExprs( clause.target.args ); 1514 1515 // List all combinations of arguments 1516 std::vector< CandidateList > possibilities; 1517 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 1518 1519 // For every possible function: 1520 // * try matching the arguments to the parameters, not the other way around because 1521 // more arguments than parameters 1522 CandidateList funcCandidates; 1523 std::vector< CandidateList > argsCandidates; 1524 SemanticErrorException errors; 1525 for ( CandidateRef & func : funcFinder.candidates ) { 1526 try { 1527 auto pointerType = dynamic_cast< const ast::PointerType * >( 1528 func->expr->result->stripReferences() ); 1529 if ( ! pointerType ) { 1530 SemanticError( stmt->location, func->expr->result.get(), 1531 "candidate not viable: not a pointer type\n" ); 1532 } 1533 1534 auto funcType = pointerType->base.as< ast::FunctionType >(); 1535 if ( ! funcType ) { 1536 SemanticError( stmt->location, func->expr->result.get(), 1537 "candidate not viable: not a function type\n" ); 1538 } 1539 1540 { 1541 auto param = funcType->params.begin(); 1542 auto paramEnd = funcType->params.end(); 1543 1544 if( ! nextMutex( param, paramEnd ) ) { 1545 SemanticError( stmt->location, funcType, 1546 "candidate function not viable: no mutex parameters\n"); 1547 } 1548 } 1549 1550 CandidateRef func2{ new Candidate{ *func } }; 1551 // strip reference from function 1552 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 1553 1554 // Each argument must be matched with a parameter of the current candidate 1555 for ( auto & argsList : possibilities ) { 1556 try { 1557 // Declare data structures needed for resolution 1558 ast::OpenVarSet open; 1559 ast::AssertionSet need, have; 1560 ast::TypeEnvironment resultEnv{ func->env }; 1561 // Add all type variables as open so that those not used in the 1562 // parameter list are still considered open 1563 resultEnv.add( funcType->forall ); 1564 1565 // load type variables from arguments into one shared space 1566 for ( auto & arg : argsList ) { 1567 resultEnv.simpleCombine( arg->env ); 1568 } 1569 1570 // Make sure we don't widen any existing bindings 1571 resultEnv.forbidWidening(); 1572 1573 // Find any unbound type variables 1574 resultEnv.extractOpenVars( open ); 1575 1576 auto param = funcType->params.begin(); 1577 auto paramEnd = funcType->params.end(); 1578 1579 unsigned n_mutex_param = 0; 1580 1581 // For every argument of its set, check if it matches one of the 1582 // parameters. The order is important 1583 for ( auto & arg : argsList ) { 1584 // Ignore non-mutex arguments 1585 if ( ! nextMutex( param, paramEnd ) ) { 1586 // We ran out of parameters but still have arguments. 1587 // This function doesn't match 1588 SemanticError( stmt->location, funcType, 1589 toString("candidate function not viable: too many mutex " 1590 "arguments, expected ", n_mutex_param, "\n" ) ); 1591 } 1592 1593 ++n_mutex_param; 1594 1595 // Check if the argument matches the parameter type in the current 1596 // scope 1597 ast::ptr< ast::Type > paramType = (*param)->get_type(); 1598 if ( 1599 ! unify( 1600 arg->expr->result, paramType, resultEnv, need, have, open, 1601 symtab ) 1602 ) { 1603 // Type doesn't match 1604 stringstream ss; 1605 ss << "candidate function not viable: no known conversion " 1606 "from '"; 1607 ast::print( ss, (*param)->get_type() ); 1608 ss << "' to '"; 1609 ast::print( ss, arg->expr->result ); 1610 ss << "' with env '"; 1611 ast::print( ss, resultEnv ); 1612 ss << "'\n"; 1613 SemanticError( stmt->location, funcType, ss.str() ); 1614 } 1615 1616 ++param; 1617 } 1618 1619 // All arguments match! 1620 1621 // Check if parameters are missing 1622 if ( nextMutex( param, paramEnd ) ) { 1623 do { 1624 ++n_mutex_param; 1625 ++param; 1626 } while ( nextMutex( param, paramEnd ) ); 1627 1628 // We ran out of arguments but still have parameters left; this 1629 // function doesn't match 1630 SemanticError( stmt->location, funcType, 1631 toString( "candidate function not viable: too few mutex " 1632 "arguments, expected ", n_mutex_param, "\n" ) ); 1633 } 1634 1635 // All parameters match! 1636 1637 // Finish the expressions to tie in proper environments 1638 finishExpr( func2->expr, resultEnv ); 1639 for ( CandidateRef & arg : argsList ) { 1640 finishExpr( arg->expr, resultEnv ); 1641 } 1642 1643 // This is a match, store it and save it for later 1644 funcCandidates.emplace_back( std::move( func2 ) ); 1645 argsCandidates.emplace_back( std::move( argsList ) ); 1646 1647 } catch ( SemanticErrorException & e ) { 1648 errors.append( e ); 1649 } 1650 } 1651 } catch ( SemanticErrorException & e ) { 1652 errors.append( e ); 1653 } 1654 } 1655 1656 // Make sure correct number of arguments 1657 if( funcCandidates.empty() ) { 1658 SemanticErrorException top( stmt->location, 1659 "No alternatives for function in call to waitfor" ); 1660 top.append( errors ); 1661 throw top; 1662 } 1663 1664 if( argsCandidates.empty() ) { 1665 SemanticErrorException top( stmt->location, 1666 "No alternatives for arguments in call to waitfor" ); 1667 top.append( errors ); 1668 throw top; 1669 } 1670 1671 if( funcCandidates.size() > 1 ) { 1672 SemanticErrorException top( stmt->location, 1673 "Ambiguous function in call to waitfor" ); 1674 top.append( errors ); 1675 throw top; 1676 } 1677 if( argsCandidates.size() > 1 ) { 1678 SemanticErrorException top( stmt->location, 1679 "Ambiguous arguments in call to waitfor" ); 1680 top.append( errors ); 1681 throw top; 1682 } 1683 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1684 1685 // build new clause 1686 ast::WaitForStmt::Clause clause2; 1687 1688 clause2.target.func = funcCandidates.front()->expr; 1689 1690 clause2.target.args.reserve( clause.target.args.size() ); 1691 for ( auto arg : argsCandidates.front() ) { 1692 clause2.target.args.emplace_back( std::move( arg->expr ) ); 1693 } 1694 1695 // Resolve the conditions as if it were an IfStmt, statements normally 1696 clause2.cond = findSingleExpression( clause.cond, symtab ); 1697 clause2.stmt = clause.stmt->accept( *visitor ); 1698 1699 // set results into stmt 1700 auto n = mutate( stmt ); 1701 n->clauses[i] = std::move( clause2 ); 1702 stmt = n; 1703 } 1704 1705 if ( stmt->timeout.stmt ) { 1706 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1707 ast::WaitForStmt::Timeout timeout2; 1708 1709 ast::ptr< ast::Type > target = 1710 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1711 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab ); 1712 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab ); 1713 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1714 1715 // set results into stmt 1716 auto n = mutate( stmt ); 1717 n->timeout = std::move( timeout2 ); 1718 stmt = n; 1719 } 1720 1721 if ( stmt->orElse.stmt ) { 1722 // resolve the condition like IfStmt, stmts normally 1723 ast::WaitForStmt::OrElse orElse2; 1724 1725 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab ); 1726 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1727 1728 // set results into stmt 1729 auto n = mutate( stmt ); 1730 n->orElse = std::move( orElse2 ); 1731 stmt = n; 1732 } 1733 1734 return stmt; 1735 } 1736 1737 1738 1739 const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) { 1740 visit_children = false; 1741 // resolve initialization using the possibilities as determined by the `currentObject` 1742 // cursor. 1743 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 1744 singleInit->location, singleInit->value, currentObject.getOptions() }; 1745 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab ); 1746 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1747 1748 // move cursor to the object that is actually initialized 1749 currentObject.setNext( initExpr->designation ); 1750 1751 // discard InitExpr wrapper and retain relevant pieces. 1752 // `initExpr` may have inferred params in the case where the expression specialized a 1753 // function pointer, and newExpr may already have inferParams of its own, so a simple 1754 // swap is not sufficient 1755 ast::Expr::InferUnion inferred = initExpr->inferred; 1756 swap_and_save_env( newExpr, initExpr->expr ); 1757 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) ); 1758 1759 // get the actual object's type (may not exactly match what comes back from the resolver 1760 // due to conversions) 1761 const ast::Type * initContext = currentObject.getCurrentType(); 1762 1763 removeExtraneousCast( newExpr, symtab ); 1764 1765 // check if actual object's type is char[] 1766 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) { 1767 if ( isCharType( at->base ) ) { 1768 // check if the resolved type is char* 1769 if ( auto pt = newExpr->result.as< ast::PointerType >() ) { 1770 if ( isCharType( pt->base ) ) { 1771 // strip cast if we're initializing a char[] with a char* 1772 // e.g. char x[] = "hello" 1773 if ( auto ce = newExpr.as< ast::CastExpr >() ) { 1774 swap_and_save_env( newExpr, ce->arg ); 1775 } 1776 } 1777 } 1778 } 1779 } 1780 1781 // move cursor to next object in preparation for next initializer 1782 currentObject.increment(); 1783 1784 // set initializer expression to resolved expression 1785 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) ); 1786 } 1787 1788 const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) { 1789 // move cursor into brace-enclosed initializer-list 1790 currentObject.enterListInit( listInit->location ); 1791 1792 assert( listInit->designations.size() == listInit->initializers.size() ); 1793 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) { 1794 // iterate designations and initializers in pairs, moving the cursor to the current 1795 // designated object and resolving the initializer against that object 1796 listInit = ast::mutate_field_index( 1797 listInit, &ast::ListInit::designations, i, 1798 currentObject.findNext( listInit->designations[i] ) ); 1799 listInit = ast::mutate_field_index( 1800 listInit, &ast::ListInit::initializers, i, 1801 listInit->initializers[i]->accept( *visitor ) ); 1802 } 1803 1804 // move cursor out of brace-enclosed initializer-list 1805 currentObject.exitListInit(); 1806 1807 visit_children = false; 1808 return listInit; 1809 } 1810 1811 const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1812 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor ); 1813 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor ); 1814 1815 // found a constructor - can get rid of C-style initializer 1816 // xxx - Rob suggests this field is dead code 1817 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1818 1819 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1820 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1821 // clean up generated code 1822 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 1823 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr ); 1824 } 1825 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 1826 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr ); 1827 } 1828 1829 return ctorInit; 1830 } 1831 876 1832 } // namespace ResolvExpr 877 1833 -
src/ResolvExpr/Resolver.h
r7951100 rb067d9b 10 10 // Created On : Sun May 17 12:18:34 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:36:57 201713 // Update Count : 312 // Last Modified On : Mon Feb 18 20:40:38 2019 13 // Update Count : 4 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <list> // for list 18 #include <list> // for list 19 20 #include "AST/Node.hpp" // for ptr 19 21 20 22 class ConstructorInit; … … 23 25 class StmtExpr; 24 26 namespace SymTab { 25 class Indexer; 26 } // namespace SymTab 27 class Indexer; 28 } // namespace SymTab 29 30 namespace ast { 31 class ConstructorInit; 32 class Decl; 33 class DeletedExpr; 34 class Init; 35 class StmtExpr; 36 class SymbolTable; 37 class Type; 38 class TypeEnvironment; 39 } // namespace ast 27 40 28 41 namespace ResolvExpr { 29 42 /// Checks types and binds syntactic constructs to typed representations 30 43 void resolve( std::list< Declaration * > translationUnit ); 31 void resolveDecl( Declaration *, const SymTab::Indexer & indexer );32 Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer );33 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer );34 void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer );35 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer );44 void resolveDecl( Declaration *, const SymTab::Indexer & indexer ); 45 Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ); 46 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ); 47 void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ); 48 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ); 36 49 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ); 37 50 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ); 51 /// Searches expr and returns the first DeletedExpr found, otherwise nullptr 52 DeletedExpr * findDeletedExpr( Expression * expr ); 53 /// Resolves with-stmts and with-clauses on functions 54 void resolveWithExprs( std::list< Declaration * > & translationUnit ); 55 56 /// Checks types and binds syntactic constructs to typed representations 57 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ); 58 /// Searches expr and returns the first DeletedExpr found, otherwise nullptr 59 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ); 60 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 61 /// context. 62 ast::ptr< ast::Expr > resolveInVoidContext( 63 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env ); 64 /// Resolve `untyped` to the single expression whose candidate is the best match for the 65 /// given type. 66 ast::ptr< ast::Expr > findSingleExpression( 67 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab ); 68 /// Resolves a constructor init expression 69 ast::ptr< ast::Init > resolveCtorInit( 70 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab ); 71 /// Resolves a statement expression 72 ast::ptr< ast::Expr > resolveStmtExpr( 73 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab ); 38 74 } // namespace ResolvExpr 39 75 -
src/ResolvExpr/TypeEnvironment.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:19:47 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun May 17 12:23:36 201513 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jun 18 14:27:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 17 17 #include <algorithm> // for copy, set_intersection 18 18 #include <iterator> // for ostream_iterator, insert_iterator 19 #include <memory> // for unique_ptr 19 20 #include <utility> // for pair, move 20 21 … … 22 23 #include "SynTree/Type.h" // for Type, FunctionType, Type::Fora... 23 24 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution 25 #include "Tuples/Tuples.h" // for isTtype 24 26 #include "TypeEnvironment.h" 27 #include "typeops.h" // for occurs 28 #include "Unify.h" // for unifyInexact 25 29 26 30 namespace ResolvExpr { … … 65 69 } 66 70 71 EqvClass::EqvClass( EqvClass &&other ) 72 : vars{std::move(other.vars)}, type{other.type}, 73 allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} { 74 other.type = nullptr; 75 } 76 67 77 EqvClass &EqvClass::operator=( const EqvClass &other ) { 68 78 if ( this == &other ) return *this; … … 72 82 } 73 83 84 EqvClass &EqvClass::operator=( EqvClass &&other ) { 85 if ( this == &other ) return *this; 86 delete type; 87 88 vars = std::move(other.vars); 89 type = other.type; 90 other.type = nullptr; 91 allowWidening = std::move(other.allowWidening); 92 data = std::move(other.data); 93 94 return *this; 95 } 96 74 97 EqvClass::~EqvClass() { 75 98 delete type; 99 } 100 101 void EqvClass::set_type( Type* ty ) { 102 if ( ty == type ) return; 103 delete type; 104 type = ty; 76 105 } 77 106 … … 91 120 92 121 const EqvClass* TypeEnvironment::lookup( const std::string &var ) const { 93 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) { 94 if ( i->vars.find( var ) != i->vars.end() ) { 95 /// std::cout << var << " is in class "; 96 /// i->print( std::cout ); 97 return &*i; 98 } 99 /// std::cout << var << " is not in class "; 100 /// i->print( std::cout ); 122 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) { 123 if ( i->vars.find( var ) != i->vars.end() ) return &*i; 101 124 } // for 102 125 return nullptr; … … 109 132 ++next; 110 133 std::set<std::string> intersection; 111 std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), 134 std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), 112 135 std::inserter( intersection, intersection.begin() ) ); 113 136 if ( ! intersection.empty() ) { env.erase( i ); } 114 137 i = next; 115 138 } 116 }117 118 void TypeEnvironment::add( const EqvClass &eqvClass ) {119 filterOverlappingClasses( env, eqvClass );120 env.push_back( eqvClass );121 139 } 122 140 … … 131 149 newClass.vars.insert( (*i)->get_name() ); 132 150 newClass.data = TypeDecl::Data{ (*i) }; 133 env.push_back( newClass);151 env.push_back( std::move(newClass) ); 134 152 } // for 135 153 } … … 145 163 // transition to TypeSubstitution 146 164 newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false }; 147 add( newClass);165 add( std::move(newClass) ); 148 166 } 149 167 } 150 168 151 169 void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const { 152 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {170 for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) { 153 171 for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) { 154 /// std::cerr << "adding " << *theVar;155 172 if ( theClass->type ) { 156 /// std::cerr << " bound to ";157 /// theClass->type->print( std::cerr );158 /// std::cerr << std::endl;159 173 sub.add( *theVar, theClass->type ); 160 174 } else if ( theVar != theClass->vars.begin() ) { 161 175 TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype ); 162 /// std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;163 176 sub.add( *theVar, newTypeInst ); 164 177 delete newTypeInst; … … 166 179 } // for 167 180 } // for 168 /// std::cerr << "input env is:" << std::endl;169 /// print( std::cerr, 8 );170 /// std::cerr << "sub is:" << std::endl;171 /// sub.print( std::cerr, 8 );172 181 sub.normalize(); 173 182 } … … 179 188 } 180 189 181 std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) { 182 for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) { 183 if ( i->vars.find( var ) == i->vars.end() ) { 184 return i; 185 } // if 190 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) { 191 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) { 192 if ( i->vars.count( var ) ) return i; 186 193 } // for 187 194 return env.end(); … … 192 199 } 193 200 194 void TypeEnvironment::combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ) { 195 TypeEnvironment secondCopy( second ); 196 for ( std::list< EqvClass >::iterator firstClass = env.begin(); firstClass != env.end(); ++firstClass ) { 197 EqvClass &newClass = *firstClass; 198 std::set< std::string > newVars; 199 for ( std::set< std::string >::const_iterator var = firstClass->vars.begin(); var != firstClass->vars.end(); ++var ) { 200 std::list< EqvClass >::iterator secondClass = secondCopy.internal_lookup( *var ); 201 if ( secondClass != secondCopy.env.end() ) { 202 newVars.insert( secondClass->vars.begin(), secondClass->vars.end() ); 203 if ( secondClass->type ) { 204 if ( newClass.type ) { 205 Type *newType = combineFunc( newClass.type, secondClass->type ); 206 delete newClass.type; 207 newClass.type = newType; 208 newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening; 209 } else { 210 newClass.type = secondClass->type->clone(); 211 newClass.allowWidening = secondClass->allowWidening; 212 } // if 213 } // if 214 secondCopy.env.erase( secondClass ); 215 } // if 216 } // for 217 newClass.vars.insert( newVars.begin(), newVars.end() ); 218 } // for 219 for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) { 220 env.push_back( *secondClass ); 221 } // for 201 // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto) 202 bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 203 if ( from.type ) { 204 if ( to.type ) { 205 // attempt to unify bound types 206 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() }; 207 WidenMode widen{ to.allowWidening, from.allowWidening }; 208 Type* common = nullptr; 209 AssertionSet need, have; 210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) { 211 // unifies, set common type if necessary 212 if ( common ) { 213 common->get_qualifiers() = Type::Qualifiers{}; 214 to.set_type( common ); 215 } 216 } else return false; // cannot unify 217 } else { 218 to.type = from.type->clone(); 219 } 220 } 221 222 // unify widening if matches 223 to.allowWidening &= from.allowWidening; 224 return true; 225 } 226 227 // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto) 228 bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 229 EqvClass& r = *to; 230 EqvClass& s = *from; 231 232 // ensure bounds match 233 if ( ! mergeBound( r, s, openVars, indexer ) ) return false; 234 235 // check safely bindable 236 if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false; 237 238 // merge classes in 239 r.vars.insert( s.vars.begin(), s.vars.end() ); 240 r.allowWidening &= s.allowWidening; 241 env.erase( from ); 242 243 return true; 244 } 245 246 bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 247 // short-circuit easy cases 248 if ( o.isEmpty() ) return true; 249 if ( isEmpty() ) { 250 simpleCombine( o ); 251 return true; 252 } 253 254 // merge classes 255 for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) { 256 const EqvClass& c = *ct; 257 258 // typeclass in local environment bound to c 259 auto rt = env.end(); 260 261 // look for first existing bound variable 262 auto vt = c.vars.begin(); 263 for ( ; vt != c.vars.end(); ++vt ) { 264 rt = internal_lookup( *vt ); 265 if ( rt != env.end() ) break; 266 } 267 268 if ( rt != env.end() ) { // c needs to be merged into *rt 269 EqvClass& r = *rt; 270 // merge bindings 271 if ( ! mergeBound( r, c, openVars, indexer ) ) return false; 272 // merge previous unbound variables into this class, checking occurs if needed 273 if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) { 274 if ( occurs( r.type, *ut, *this ) ) return false; 275 r.vars.insert( *ut ); 276 } else { r.vars.insert( c.vars.begin(), vt ); } 277 // merge subsequent variables into this class (skipping *vt, already there) 278 while ( ++vt != c.vars.end() ) { 279 auto st = internal_lookup( *vt ); 280 if ( st == env.end() ) { 281 // unbound, safe to add if passes occurs 282 if ( r.type && occurs( r.type, *vt, *this ) ) return false; 283 r.vars.insert( *vt ); 284 } else if ( st != rt ) { 285 // bound, but not to the same class 286 if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false; 287 } // ignore bound into the same class 288 } 289 } else { // no variables in c bound; just copy up 290 env.push_back( c ); 291 } 292 } 293 294 // merged all classes 295 return true; 222 296 } 223 297 224 298 void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const { 225 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {299 for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) { 226 300 for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) { 227 301 openVars[ *var ] = eqvClass->data; … … 241 315 } 242 316 317 bool isFtype( const Type * type ) { 318 if ( dynamic_cast< const FunctionType * >( type ) ) { 319 return true; 320 } else if ( const TypeInstType *typeInst = dynamic_cast< const TypeInstType * >( type ) ) { 321 return typeInst->get_isFtype(); 322 } // if 323 return false; 324 } 325 326 bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) { 327 switch ( data.kind ) { 328 case TypeDecl::Dtype: 329 // to bind to an object type variable, the type must not be a function type. 330 // if the type variable is specified to be a complete type then the incoming 331 // type must also be complete 332 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 333 return ! isFtype( type ) && (! data.isComplete || type->isComplete() ); 334 case TypeDecl::Ftype: 335 return isFtype( type ); 336 case TypeDecl::Ttype: 337 // ttype unifies with any tuple type 338 return dynamic_cast< const TupleType * >( type ) || Tuples::isTtype( type ); 339 default: 340 assertf(false, "Unhandled tyvar kind: %d", data.kind); 341 } // switch 342 return false; 343 } 344 345 bool TypeEnvironment::bindVar( const TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 346 347 // remove references from other, so that type variables can only bind to value types 348 bindTo = bindTo->stripReferences(); 349 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 350 assert( tyvar != openVars.end() ); 351 if ( ! tyVarCompatible( tyvar->second, bindTo ) ) { 352 return false; 353 } // if 354 if ( occurs( bindTo, typeInst->get_name(), *this ) ) { 355 return false; 356 } // if 357 auto curClass = internal_lookup( typeInst->get_name() ); 358 if ( curClass != env.end() ) { 359 if ( curClass->type ) { 360 Type *common = 0; 361 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to 362 std::unique_ptr< Type > newType( curClass->type->clone() ); 363 newType->tq = typeInst->tq; 364 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) { 365 if ( common ) { 366 common->get_qualifiers() = Type::Qualifiers{}; 367 curClass->set_type( common ); 368 } // if 369 } else return false; 370 } else { 371 Type* newType = bindTo->clone(); 372 newType->get_qualifiers() = Type::Qualifiers{}; 373 curClass->set_type( newType ); 374 curClass->allowWidening = widen.first && widen.second; 375 } // if 376 } else { 377 EqvClass newClass; 378 newClass.vars.insert( typeInst->get_name() ); 379 newClass.type = bindTo->clone(); 380 newClass.type->get_qualifiers() = Type::Qualifiers(); 381 newClass.allowWidening = widen.first && widen.second; 382 newClass.data = data; 383 env.push_back( std::move(newClass) ); 384 } // if 385 return true; 386 } 387 388 bool TypeEnvironment::bindVarToVar( const TypeInstType * var1, const TypeInstType * var2, 389 TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, 390 const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 391 392 auto class1 = internal_lookup( var1->get_name() ); 393 auto class2 = internal_lookup( var2->get_name() ); 394 395 // exit early if variables already bound together 396 if ( class1 != env.end() && class1 == class2 ) { 397 class1->allowWidening &= widen; 398 return true; 399 } 400 401 bool widen1 = false, widen2 = false; 402 const Type *type1 = nullptr, *type2 = nullptr; 403 404 // check for existing bindings, perform occurs check 405 if ( class1 != env.end() ) { 406 if ( class1->type ) { 407 if ( occurs( class1->type, var2->get_name(), *this ) ) return false; 408 type1 = class1->type; 409 } // if 410 widen1 = widen.first && class1->allowWidening; 411 } // if 412 if ( class2 != env.end() ) { 413 if ( class2->type ) { 414 if ( occurs( class2->type, var1->get_name(), *this ) ) return false; 415 type2 = class2->type; 416 } // if 417 widen2 = widen.second && class2->allowWidening; 418 } // if 419 420 if ( type1 && type2 ) { 421 // both classes bound, merge if bound types can be unified 422 std::unique_ptr<Type> newType1{ type1->clone() }, newType2{ type2->clone() }; 423 WidenMode newWidenMode{ widen1, widen2 }; 424 Type *common = 0; 425 if ( unifyInexact( newType1.get(), newType2.get(), *this, need, have, openVars, newWidenMode, indexer, common ) ) { 426 class1->vars.insert( class2->vars.begin(), class2->vars.end() ); 427 class1->allowWidening = widen1 && widen2; 428 if ( common ) { 429 common->get_qualifiers() = Type::Qualifiers{}; 430 class1->set_type( common ); 431 } 432 class1->data.isComplete |= data.isComplete; 433 env.erase( class2 ); 434 } else return false; 435 } else if ( class1 != env.end() && class2 != env.end() ) { 436 // both classes exist, at least one unbound, merge unconditionally 437 if ( type1 ) { 438 class1->vars.insert( class2->vars.begin(), class2->vars.end() ); 439 class1->allowWidening = widen1; 440 class1->data.isComplete |= data.isComplete; 441 env.erase( class2 ); 442 } else { 443 class2->vars.insert( class1->vars.begin(), class1->vars.end() ); 444 class2->allowWidening = widen2; 445 class2->data.isComplete |= data.isComplete; 446 env.erase( class1 ); 447 } // if 448 } else if ( class1 != env.end() ) { 449 // var2 unbound, add to class1 450 class1->vars.insert( var2->get_name() ); 451 class1->allowWidening = widen1; 452 class1->data.isComplete |= data.isComplete; 453 } else if ( class2 != env.end() ) { 454 // var1 unbound, add to class2 455 class2->vars.insert( var1->get_name() ); 456 class2->allowWidening = widen2; 457 class2->data.isComplete |= data.isComplete; 458 } else { 459 // neither var bound, create new class 460 EqvClass newClass; 461 newClass.vars.insert( var1->get_name() ); 462 newClass.vars.insert( var2->get_name() ); 463 newClass.allowWidening = widen1 && widen2; 464 newClass.data = data; 465 env.push_back( std::move(newClass) ); 466 } // if 467 return true; 468 } 469 470 void TypeEnvironment::forbidWidening() { 471 for ( EqvClass& c : env ) c.allowWidening = false; 472 } 473 243 474 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) { 244 475 env.print( out ); -
src/ResolvExpr/TypeEnvironment.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:24:58 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:35:45 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 19 17:00:10 2019 13 // Update Count : 10 14 14 // 15 15 … … 18 18 #include <iostream> // for ostream 19 19 #include <list> // for list, list<>::iterator, list<>... 20 #include <map> // for map, map<>::value_compare 21 #include <set> // for set 20 #include <map> // for map, map<>::value_compare 21 #include <unordered_map> 22 #include <set> // for set 22 23 #include <string> // for string 24 #include <utility> // for move, swap 25 26 #include "WidenMode.h" // for WidenMode 23 27 24 28 #include "SynTree/Declaration.h" // for TypeDecl::Data, DeclarationWit... … … 36 40 // declarations. 37 41 // 38 // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator. 42 // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 43 // comparator. 39 44 // 40 45 // Note: since this compares pointers for position, minor changes in the source file that affect 41 46 // memory layout can alter compilation time in unpredictable ways. For example, the placement 42 47 // of a line directive can reorder type pointers with respect to each other so that assertions 43 // are seen in different orders, causing a potentially different number of unification calls when 44 // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives 45 // alone, so it would be nice to fix this comparison so that assertions compare more consistently. 46 // I've tried to modify this to compare on mangle name instead of type as the second comparator, but 47 // this causes some assertions to never be recorded. More investigation is needed. 48 // are seen in different orders, causing a potentially different number of unification calls 49 // when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering 50 // line directives alone, so it would be nice to fix this comparison so that assertions compare 51 // more consistently. I've tried to modify this to compare on mangle name instead of type as 52 // the second comparator, but this causes some assertions to never be recorded. More 53 // investigation is needed. 48 54 struct AssertCompare { 49 bool operator()( DeclarationWithType * d1,DeclarationWithType * d2 ) const {55 bool operator()( const DeclarationWithType * d1, const DeclarationWithType * d2 ) const { 50 56 int cmp = d1->get_name().compare( d2->get_name() ); 51 57 return cmp < 0 || … … 54 60 }; 55 61 struct AssertionSetValue { 56 bool isUsed; 57 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type, 58 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is 59 // the ID of the assertion that pulled in the current assertion. 60 std::list< UniqueId > idChain; 62 bool isUsed; ///< True if assertion needs to be resolved 63 UniqueId resnSlot; ///< ID of slot assertion belongs to 64 65 AssertionSetValue() : isUsed(false), resnSlot(0) {} 61 66 }; 62 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 63 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 67 typedef std::map< const DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet; 68 typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet; 69 70 /// merges one set of open vars into another 71 static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) { 72 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; } 73 } 64 74 65 75 void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 ); … … 68 78 struct EqvClass { 69 79 std::set< std::string > vars; 70 Type * type;80 Type * type; 71 81 bool allowWidening; 72 82 TypeDecl::Data data; … … 77 87 EqvClass( const EqvClass &other ); 78 88 EqvClass( const EqvClass &other, const Type *ty ); 89 EqvClass( EqvClass &&other ); 79 90 EqvClass &operator=( const EqvClass &other ); 91 EqvClass &operator=( EqvClass &&other ); 80 92 ~EqvClass(); 81 93 void print( std::ostream &os, Indenter indent = {} ) const; 94 95 /// Takes ownership of `ty`, freeing old `type` 96 void set_type(Type* ty); 82 97 }; 83 98 84 99 class TypeEnvironment { 100 using ClassList = std::list< EqvClass >; 85 101 public: 86 102 const EqvClass* lookup( const std::string &var ) const; 87 void add( const EqvClass &eqvClass );103 private: 88 104 void add( EqvClass &&eqvClass ); 105 public: 89 106 void add( const Type::ForallList &tyDecls ); 90 107 void add( const TypeSubstitution & sub ); … … 94 111 bool isEmpty() const { return env.empty(); } 95 112 void print( std::ostream &os, Indenter indent = {} ) const; 96 void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ); 113 114 /// Simply concatenate the second environment onto this one; no safety checks performed 97 115 void simpleCombine( const TypeEnvironment &second ); 116 117 private: 118 /// Unifies the type bound of to with the type bound of from, returning false if fails 119 bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 120 121 /// Merges two type classes from local environment, returning false if fails 122 bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 123 124 public: 125 /// Merges the second environment with this one, checking compatibility. 126 /// Returns false if fails, but does NOT roll back partial changes. 127 bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 128 98 129 void extractOpenVars( OpenVarSet &openVars ) const; 99 130 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } … … 103 134 void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ); 104 135 105 typedef std::list< EqvClass >::iterator iterator; 106 iterator begin() { return env.begin(); } 107 iterator end() { return env.end(); } 108 typedef std::list< EqvClass >::const_iterator const_iterator; 109 const_iterator begin() const { return env.begin(); } 110 const_iterator end() const { return env.end(); } 136 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add 137 /// the class if needed. Returns false on failure. 138 bool bindVar( const TypeInstType * typeInst, Type * bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 139 140 /// Binds the type classes represented by `var1` and `var2` together; will add 141 /// one or both classes if needed. Returns false on failure. 142 bool bindVarToVar( const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 143 144 /// Disallows widening for all bindings in the environment 145 void forbidWidening(); 146 147 using iterator = ClassList::const_iterator; 148 iterator begin() const { return env.begin(); } 149 iterator end() const { return env.end(); } 150 111 151 private: 112 std::list< EqvClass > env; 113 std::list< EqvClass >::iterator internal_lookup( const std::string &var ); 152 ClassList env; 153 154 ClassList::iterator internal_lookup( const std::string &var ); 114 155 }; 115 156 -
src/ResolvExpr/Unify.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:27:10 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 16:22:54 201713 // Update Count : 4 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 4 10:00:00 2019 13 // Update Count : 44 14 14 // 15 15 16 #include <cassert> // for assertf, assert17 #include <iterator> // for back_insert_iterator, back_inserter18 #include <map> // for _Rb_tree_const_iterator, _Rb_tree_i...19 #include <memory> // for unique_ptr20 #include <set> // for set21 #include <string> // for string, operator==, operator!=, bas...22 #include <utility> // for pair, move23 24 #include "Common/PassVisitor.h" // for PassVisitor25 #include "FindOpenVars.h" // for findOpenVars26 #include "Parser/LinkageSpec.h" // for C27 #include "SynTree/Constant.h" // for Constant28 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Declarati...29 #include "SynTree/Expression.h" // for TypeExpr, Expression, ConstantExpr30 #include "SynTree/Mutator.h" // for Mutator31 #include "SynTree/Type.h" // for Type, TypeInstType, FunctionType32 #include "SynTree/Visitor.h" // for Visitor33 #include "Tuples/Tuples.h" // for isTtype34 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet35 16 #include "Unify.h" 36 #include "typeops.h" // for flatten, occurs, commonType 17 18 #include <cassert> // for assertf, assert 19 #include <iterator> // for back_insert_iterator, back_inserter 20 #include <map> // for _Rb_tree_const_iterator, _Rb_tree_i... 21 #include <memory> // for unique_ptr 22 #include <set> // for set 23 #include <string> // for string, operator==, operator!=, bas... 24 #include <utility> // for pair, move 25 #include <vector> 26 27 #include "AST/Decl.hpp" 28 #include "AST/Node.hpp" 29 #include "AST/Pass.hpp" 30 #include "AST/Type.hpp" 31 #include "AST/TypeEnvironment.hpp" 32 #include "Common/PassVisitor.h" // for PassVisitor 33 #include "FindOpenVars.h" // for findOpenVars 34 #include "Parser/LinkageSpec.h" // for C 35 #include "SynTree/Constant.h" // for Constant 36 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Declarati... 37 #include "SynTree/Expression.h" // for TypeExpr, Expression, ConstantExpr 38 #include "SynTree/Mutator.h" // for Mutator 39 #include "SynTree/Type.h" // for Type, TypeInstType, FunctionType 40 #include "SynTree/Visitor.h" // for Visitor 41 #include "Tuples/Tuples.h" // for isTtype 42 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 43 #include "typeops.h" // for flatten, occurs, commonType 44 45 namespace ast { 46 class SymbolTable; 47 } 37 48 38 49 namespace SymTab { … … 44 55 namespace ResolvExpr { 45 56 46 struct Unify : public WithShortCircuiting {47 Unify ( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );57 struct Unify_old : public WithShortCircuiting { 58 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 48 59 49 60 bool get_result() const { return result; } … … 77 88 AssertionSet &haveAssertions; 78 89 const OpenVarSet &openVars; 79 WidenMode widen Mode;90 WidenMode widen; 80 91 const SymTab::Indexer &indexer; 81 92 }; … … 83 94 /// Attempts an inexact unification of type1 and type2. 84 95 /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers) 85 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ); 86 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 87 88 bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 96 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 97 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 98 99 bool unifyExact( 100 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 101 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 102 WidenMode widen, const ast::SymbolTable & symtab ); 103 104 bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 89 105 TypeEnvironment newEnv; 90 106 OpenVarSet openVars, closedVars; // added closedVars 91 107 AssertionSet needAssertions, haveAssertions; 92 Type * newFirst = first->clone(), *newSecond = second->clone();108 Type * newFirst = first->clone(), * newSecond = second->clone(); 93 109 env.apply( newFirst ); 94 110 env.apply( newSecond ); … … 105 121 } 106 122 107 bool typesCompatibleIgnoreQualifiers( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 123 bool typesCompatible( 124 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 125 const ast::TypeEnvironment & env ) { 126 ast::TypeEnvironment newEnv; 127 ast::OpenVarSet open, closed; 128 ast::AssertionSet need, have; 129 130 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 131 env.apply( newFirst ); 132 env.apply( newSecond ); 133 134 findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 135 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 136 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 139 } 140 141 bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 108 142 TypeEnvironment newEnv; 109 143 OpenVarSet openVars; … … 129 163 } 130 164 131 bool isFtype( Type *type ) { 132 if ( dynamic_cast< FunctionType* >( type ) ) { 133 return true; 134 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) { 135 return typeInst->get_isFtype(); 136 } // if 137 return false; 138 } 139 140 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) { 141 switch ( data.kind ) { 142 case TypeDecl::Dtype: 143 // to bind to an object type variable, the type must not be a function type. 144 // if the type variable is specified to be a complete type then the incoming 145 // type must also be complete 146 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 147 return ! isFtype( type ) && (! data.isComplete || type->isComplete() ); 148 case TypeDecl::Ftype: 149 return isFtype( type ); 150 case TypeDecl::Ttype: 151 // ttype unifies with any tuple type 152 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type ); 153 } // switch 154 return false; 155 } 156 157 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 158 // remove references from other, so that type variables can only bind to value types 159 other = other->stripReferences(); 160 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 161 assert( tyvar != openVars.end() ); 162 if ( ! tyVarCompatible( tyvar->second, other ) ) { 163 return false; 164 } // if 165 if ( occurs( other, typeInst->get_name(), env ) ) { 166 return false; 167 } // if 168 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) { 169 if ( curClass->type ) { 170 Type *common = 0; 171 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to 172 std::unique_ptr< Type > newType( curClass->type->clone() ); 173 newType->get_qualifiers() = typeInst->get_qualifiers(); 174 if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) { 175 if ( common ) { 176 common->get_qualifiers() = Type::Qualifiers(); 177 env.add( EqvClass{ *curClass, common } ); 178 } // if 179 return true; 180 } else { 181 return false; 182 } // if 183 } else { 184 EqvClass newClass { *curClass, other }; 185 newClass.type->get_qualifiers() = Type::Qualifiers(); 186 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 187 env.add( std::move(newClass) ); 188 } // if 189 } else { 190 EqvClass newClass; 191 newClass.vars.insert( typeInst->get_name() ); 192 newClass.type = other->clone(); 193 newClass.type->get_qualifiers() = Type::Qualifiers(); 194 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 195 newClass.data = data; 196 env.add( newClass ); 197 } // if 198 return true; 199 } 200 201 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 202 bool result = true; 203 const EqvClass *class1 = env.lookup( var1->get_name() ); 204 const EqvClass *class2 = env.lookup( var2->get_name() ); 205 bool widen1 = false, widen2 = false; 206 Type *type1 = nullptr, *type2 = nullptr; 207 208 if ( class1 ) { 209 if ( class1->type ) { 210 if ( occurs( class1->type, var2->get_name(), env ) ) { 211 return false; 212 } // if 213 type1 = class1->type->clone(); 214 } // if 215 widen1 = widenMode.widenFirst && class1->allowWidening; 216 } // if 217 if ( class2 ) { 218 if ( class2->type ) { 219 if ( occurs( class2->type, var1->get_name(), env ) ) { 220 return false; 221 } // if 222 type2 = class2->type->clone(); 223 } // if 224 widen2 = widenMode.widenSecond && class2->allowWidening; 225 } // if 226 227 if ( type1 && type2 ) { 228 // std::cerr << "has type1 && type2" << std::endl; 229 WidenMode newWidenMode ( widen1, widen2 ); 230 Type *common = 0; 231 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) { 232 EqvClass newClass1 = *class1; 233 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() ); 234 newClass1.allowWidening = widen1 && widen2; 235 if ( common ) { 236 common->get_qualifiers() = Type::Qualifiers(); 237 delete newClass1.type; 238 newClass1.type = common; 239 } // if 240 env.add( std::move(newClass1) ); 241 } else { 242 result = false; 243 } // if 244 } else if ( class1 && class2 ) { 245 if ( type1 ) { 246 EqvClass newClass1 = *class1; 247 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() ); 248 newClass1.allowWidening = widen1; 249 env.add( std::move(newClass1) ); 250 } else { 251 EqvClass newClass2 = *class2; 252 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() ); 253 newClass2.allowWidening = widen2; 254 env.add( std::move(newClass2) ); 255 } // if 256 } else if ( class1 ) { 257 EqvClass newClass1 = *class1; 258 newClass1.vars.insert( var2->get_name() ); 259 newClass1.allowWidening = widen1; 260 env.add( std::move(newClass1) ); 261 } else if ( class2 ) { 262 EqvClass newClass2 = *class2; 263 newClass2.vars.insert( var1->get_name() ); 264 newClass2.allowWidening = widen2; 265 env.add( std::move(newClass2) ); 266 } else { 267 EqvClass newClass; 268 newClass.vars.insert( var1->get_name() ); 269 newClass.vars.insert( var2->get_name() ); 270 newClass.allowWidening = widen1 && widen2; 271 newClass.data = data; 272 env.add( newClass ); 273 } // if 274 delete type1; 275 delete type2; 276 return result; 165 bool typesCompatibleIgnoreQualifiers( 166 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 167 const ast::TypeEnvironment & env ) { 168 ast::TypeEnvironment newEnv; 169 ast::OpenVarSet open; 170 ast::AssertionSet need, have; 171 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 177 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 277 180 } 278 181 … … 299 202 } 300 203 301 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer ) {204 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 302 205 #ifdef DEBUG 303 206 TypeEnvironment debugEnv( env ); … … 320 223 bool isopen2 = var2 && ( entry2 != openVars.end() ); 321 224 322 if ( isopen1 && isopen2 && entry1->second == entry2->second ) { 323 result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 225 if ( isopen1 && isopen2 ) { 226 if ( entry1->second.kind != entry2->second.kind ) { 227 result = false; 228 } else { 229 result = env.bindVarToVar( 230 var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions, 231 haveAssertions, openVars, widen, indexer ); 232 } 324 233 } else if ( isopen1 ) { 325 result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );326 } else if ( isopen2 ) { // TODO: swap widen Modevalues in call, since type positions are flipped?327 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );234 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer ); 235 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped? 236 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer ); 328 237 } else { 329 PassVisitor<Unify > comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );238 PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer ); 330 239 type1->accept( comparator ); 331 240 result = comparator.pass.get_result(); … … 352 261 } 353 262 354 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen Mode, const SymTab::Indexer &indexer, Type *&common ) {263 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) { 355 264 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers(); 356 265 type1->get_qualifiers() = Type::Qualifiers(); … … 364 273 std::cerr << std::endl; 365 274 #endif 366 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen Mode, indexer ) ) {275 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) { 367 276 #ifdef DEBUG 368 277 std::cerr << "unifyInexact: no exact unification found" << std::endl; 369 278 #endif 370 if ( ( common = commonType( type1, type2, widen Mode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {371 common-> get_qualifiers() = tq1 | tq2;279 if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) { 280 common->tq = tq1.unify( tq2 ); 372 281 #ifdef DEBUG 373 282 std::cerr << "unifyInexact: common type is "; … … 384 293 } else { 385 294 if ( tq1 != tq2 ) { 386 if ( ( tq1 > tq2 || widen Mode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {295 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) { 387 296 common = type1->clone(); 388 common-> get_qualifiers() = tq1 | tq2;297 common->tq = tq1.unify( tq2 ); 389 298 result = true; 390 299 } else { … … 393 302 } else { 394 303 common = type1->clone(); 395 common-> get_qualifiers() = tq1 | tq2;304 common->tq = tq1.unify( tq2 ); 396 305 result = true; 397 306 } // if … … 402 311 } 403 312 404 Unify ::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )405 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen Mode( widenMode), indexer( indexer ) {406 } 407 408 void Unify ::postvisit( __attribute__((unused)) VoidType *voidType) {313 Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) 314 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) { 315 } 316 317 void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) { 409 318 result = dynamic_cast< VoidType* >( type2 ); 410 319 } 411 320 412 void Unify ::postvisit(BasicType *basicType) {321 void Unify_old::postvisit(BasicType *basicType) { 413 322 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 414 323 result = basicType->get_kind() == otherBasic->get_kind(); … … 438 347 } 439 348 440 void Unify ::postvisit(PointerType *pointerType) {349 void Unify_old::postvisit(PointerType *pointerType) { 441 350 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 442 351 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 446 355 } 447 356 448 void Unify ::postvisit(ReferenceType *refType) {357 void Unify_old::postvisit(ReferenceType *refType) { 449 358 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 450 359 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 454 363 } 455 364 456 void Unify ::postvisit(ArrayType *arrayType) {365 void Unify_old::postvisit(ArrayType *arrayType) { 457 366 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 458 367 // to unify, array types must both be VLA or both not VLA … … 534 443 /// If this isn't done then argument lists can have wildly different 535 444 /// size and structure, when they should be compatible. 536 struct TtypeExpander : public WithShortCircuiting {445 struct TtypeExpander_old : public WithShortCircuiting { 537 446 TypeEnvironment & tenv; 538 TtypeExpander ( TypeEnvironment & tenv ) : tenv( tenv ) {}447 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {} 539 448 void premutate( TypeInstType * ) { visit_children = false; } 540 449 Type * postmutate( TypeInstType * typeInst ) { … … 555 464 dst.clear(); 556 465 for ( DeclarationWithType * dcl : src ) { 557 PassVisitor<TtypeExpander > expander( env );466 PassVisitor<TtypeExpander_old> expander( env ); 558 467 dcl->acceptMutator( expander ); 559 468 std::list< Type * > types; … … 570 479 } 571 480 572 void Unify ::postvisit(FunctionType *functionType) {481 void Unify_old::postvisit(FunctionType *functionType) { 573 482 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 574 483 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 581 490 582 491 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 583 if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 492 if ( 493 (flatFunc->parameters.size() == flatOther->parameters.size() && 494 flatFunc->returnVals.size() == flatOther->returnVals.size()) 495 || flatFunc->isTtype() 496 || flatOther->isTtype() 497 ) { 584 498 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 585 499 if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { … … 597 511 598 512 template< typename RefType > 599 void Unify ::handleRefType( RefType *inst, Type *other ) {513 void Unify_old::handleRefType( RefType *inst, Type *other ) { 600 514 // check that other type is compatible and named the same 601 515 RefType *otherStruct = dynamic_cast< RefType* >( other ); … … 604 518 605 519 template< typename RefType > 606 void Unify ::handleGenericRefType( RefType *inst, Type *other ) {520 void Unify_old::handleGenericRefType( RefType *inst, Type *other ) { 607 521 // Check that other type is compatible and named the same 608 522 handleRefType( inst, other ); … … 672 586 } 673 587 674 void Unify ::postvisit(StructInstType *structInst) {588 void Unify_old::postvisit(StructInstType *structInst) { 675 589 handleGenericRefType( structInst, type2 ); 676 590 } 677 591 678 void Unify ::postvisit(UnionInstType *unionInst) {592 void Unify_old::postvisit(UnionInstType *unionInst) { 679 593 handleGenericRefType( unionInst, type2 ); 680 594 } 681 595 682 void Unify ::postvisit(EnumInstType *enumInst) {596 void Unify_old::postvisit(EnumInstType *enumInst) { 683 597 handleRefType( enumInst, type2 ); 684 598 } 685 599 686 void Unify ::postvisit(TraitInstType *contextInst) {600 void Unify_old::postvisit(TraitInstType *contextInst) { 687 601 handleRefType( contextInst, type2 ); 688 602 } 689 603 690 void Unify ::postvisit(TypeInstType *typeInst) {604 void Unify_old::postvisit(TypeInstType *typeInst) { 691 605 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 692 606 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 743 657 } 744 658 745 void Unify ::postvisit(TupleType *tupleType) {659 void Unify_old::postvisit(TupleType *tupleType) { 746 660 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 747 661 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 749 663 std::list<Type *> types1, types2; 750 664 751 PassVisitor<TtypeExpander > expander( env );665 PassVisitor<TtypeExpander_old> expander( env ); 752 666 flat1->acceptMutator( expander ); 753 667 flat2->acceptMutator( expander ); … … 760 674 } 761 675 762 void Unify ::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {676 void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 763 677 result = dynamic_cast< VarArgsType* >( type2 ); 764 678 } 765 679 766 void Unify ::postvisit( __attribute__((unused)) ZeroType *zeroType ) {680 void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 767 681 result = dynamic_cast< ZeroType* >( type2 ); 768 682 } 769 683 770 void Unify ::postvisit( __attribute__((unused)) OneType *oneType ) {684 void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) { 771 685 result = dynamic_cast< OneType* >( type2 ); 772 686 } 773 687 774 // xxx - compute once and store in the FunctionType?775 688 Type * extractResultType( FunctionType * function ) { 776 689 if ( function->get_returnVals().size() == 0 ) { … … 786 699 } 787 700 } 701 702 class Unify_new final : public ast::WithShortCircuiting { 703 const ast::Type * type2; 704 ast::TypeEnvironment & tenv; 705 ast::AssertionSet & need; 706 ast::AssertionSet & have; 707 const ast::OpenVarSet & open; 708 WidenMode widen; 709 const ast::SymbolTable & symtab; 710 public: 711 bool result; 712 713 Unify_new( 714 const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need, 715 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen, 716 const ast::SymbolTable & symtab ) 717 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen), 718 symtab(symtab), result(false) {} 719 720 void previsit( const ast::Node * ) { visit_children = false; } 721 722 void postvisit( const ast::VoidType * ) { 723 result = dynamic_cast< const ast::VoidType * >( type2 ); 724 } 725 726 void postvisit( const ast::BasicType * basic ) { 727 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 728 result = basic->kind == basic2->kind; 729 } 730 } 731 732 void postvisit( const ast::PointerType * pointer ) { 733 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) { 734 result = unifyExact( 735 pointer->base, pointer2->base, tenv, need, have, open, 736 noWiden(), symtab ); 737 } 738 } 739 740 void postvisit( const ast::ArrayType * array ) { 741 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 ); 742 if ( ! array2 ) return; 743 744 // to unify, array types must both be VLA or both not VLA and both must have a 745 // dimension expression or not have a dimension 746 if ( array->isVarLen != array2->isVarLen ) return; 747 if ( ! array->isVarLen && ! array2->isVarLen 748 && array->dimension && array2->dimension ) { 749 auto ce1 = array->dimension.as< ast::ConstantExpr >(); 750 auto ce2 = array2->dimension.as< ast::ConstantExpr >(); 751 752 // see C11 Reference Manual 6.7.6.2.6 753 // two array types with size specifiers that are integer constant expressions are 754 // compatible if both size specifiers have the same constant value 755 if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return; 756 } 757 758 result = unifyExact( 759 array->base, array2->base, tenv, need, have, open, noWiden(), 760 symtab ); 761 } 762 763 void postvisit( const ast::ReferenceType * ref ) { 764 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 765 result = unifyExact( 766 ref->base, ref2->base, tenv, need, have, open, noWiden(), 767 symtab ); 768 } 769 } 770 771 private: 772 /// Replaces ttype variables with their bound types. 773 /// If this isn't done when satifying ttype assertions, then argument lists can have 774 /// different size and structure when they should be compatible. 775 struct TtypeExpander_new : public ast::WithShortCircuiting { 776 ast::TypeEnvironment & tenv; 777 778 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 779 780 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 781 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 782 // expand ttype parameter into its actual type 783 if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) { 784 return clz->bound; 785 } 786 } 787 return typeInst; 788 } 789 }; 790 791 /// returns flattened version of `src` 792 static std::vector< ast::ptr< ast::DeclWithType > > flattenList( 793 const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env 794 ) { 795 std::vector< ast::ptr< ast::DeclWithType > > dst; 796 dst.reserve( src.size() ); 797 for ( const ast::DeclWithType * d : src ) { 798 ast::Pass<TtypeExpander_new> expander{ env }; 799 d = d->accept( expander ); 800 auto types = flatten( d->get_type() ); 801 for ( ast::ptr< ast::Type > & t : types ) { 802 // outermost const, volatile, _Atomic qualifiers in parameters should not play 803 // a role in the unification of function types, since they do not determine 804 // whether a function is callable. 805 // NOTE: **must** consider at least mutex qualifier, since functions can be 806 // overloaded on outermost mutex and a mutex function has different 807 // requirements than a non-mutex function 808 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 809 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 810 } 811 } 812 return dst; 813 } 814 815 /// Creates a tuple type based on a list of DeclWithType 816 template< typename Iter > 817 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) { 818 std::vector< ast::ptr< ast::Type > > types; 819 while ( crnt != end ) { 820 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 821 // that this results in a flat tuple 822 flatten( (*crnt)->get_type(), types ); 823 824 ++crnt; 825 } 826 827 return { new ast::TupleType{ std::move(types) } }; 828 } 829 830 template< typename Iter > 831 static bool unifyDeclList( 832 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 833 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 834 const ast::SymbolTable & symtab 835 ) { 836 while ( crnt1 != end1 && crnt2 != end2 ) { 837 const ast::Type * t1 = (*crnt1)->get_type(); 838 const ast::Type * t2 = (*crnt2)->get_type(); 839 bool isTuple1 = Tuples::isTtype( t1 ); 840 bool isTuple2 = Tuples::isTtype( t2 ); 841 842 // assumes here that ttype *must* be last parameter 843 if ( isTuple1 && ! isTuple2 ) { 844 // combine remainder of list2, then unify 845 return unifyExact( 846 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 847 noWiden(), symtab ); 848 } else if ( ! isTuple1 && isTuple2 ) { 849 // combine remainder of list1, then unify 850 return unifyExact( 851 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 852 noWiden(), symtab ); 853 } 854 855 if ( ! unifyExact( 856 t1, t2, env, need, have, open, noWiden(), symtab ) 857 ) return false; 858 859 ++crnt1; ++crnt2; 860 } 861 862 // May get to the end of one argument list before the other. This is only okay if the 863 // other is a ttype 864 if ( crnt1 != end1 ) { 865 // try unifying empty tuple with ttype 866 const ast::Type * t1 = (*crnt1)->get_type(); 867 if ( ! Tuples::isTtype( t1 ) ) return false; 868 return unifyExact( 869 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 870 noWiden(), symtab ); 871 } else if ( crnt2 != end2 ) { 872 // try unifying empty tuple with ttype 873 const ast::Type * t2 = (*crnt2)->get_type(); 874 if ( ! Tuples::isTtype( t2 ) ) return false; 875 return unifyExact( 876 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 877 noWiden(), symtab ); 878 } 879 880 return true; 881 } 882 883 static bool unifyDeclList( 884 const std::vector< ast::ptr< ast::DeclWithType > > & list1, 885 const std::vector< ast::ptr< ast::DeclWithType > > & list2, 886 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 887 const ast::OpenVarSet & open, const ast::SymbolTable & symtab 888 ) { 889 return unifyDeclList( 890 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 891 symtab ); 892 } 893 894 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) { 895 auto i = assns.find( assn ); 896 if ( i != assns.end() ) { 897 i->second.isUsed = true; 898 } 899 } 900 901 /// mark all assertions in `type` used in both `assn1` and `assn2` 902 static void markAssertions( 903 ast::AssertionSet & assn1, ast::AssertionSet & assn2, 904 const ast::ParameterizedType * type 905 ) { 906 for ( const auto & tyvar : type->forall ) { 907 for ( const ast::DeclWithType * assert : tyvar->assertions ) { 908 markAssertionSet( assn1, assert ); 909 markAssertionSet( assn2, assert ); 910 } 911 } 912 } 913 914 public: 915 void postvisit( const ast::FunctionType * func ) { 916 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 ); 917 if ( ! func2 ) return; 918 919 if ( func->isVarArgs != func2->isVarArgs ) return; 920 921 // Flatten the parameter lists for both functions so that tuple structure does not 922 // affect unification. Does not actually mutate function parameters. 923 auto params = flattenList( func->params, tenv ); 924 auto params2 = flattenList( func2->params, tenv ); 925 926 // sizes don't have to match if ttypes are involved; need to be more precise w.r.t. 927 // where the ttype is to prevent errors 928 if ( 929 ( params.size() != params2.size() || func->returns.size() != func2->returns.size() ) 930 && ! func->isTtype() 931 && ! func2->isTtype() 932 ) return; 933 934 if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return; 935 if ( ! unifyDeclList( 936 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return; 937 938 markAssertions( have, need, func ); 939 markAssertions( have, need, func2 ); 940 941 result = true; 942 } 943 944 private: 945 template< typename RefType > 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 947 // check that the other type is compatible and named the same 948 auto otherInst = dynamic_cast< const RefType * >( other ); 949 result = otherInst && inst->name == otherInst->name; 950 return otherInst; 951 } 952 953 /// Creates a tuple type based on a list of TypeExpr 954 template< typename Iter > 955 static const ast::Type * tupleFromExprs( 956 const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs 957 ) { 958 std::vector< ast::ptr< ast::Type > > types; 959 do { 960 types.emplace_back( param->type ); 961 962 ++crnt; 963 if ( crnt == end ) break; 964 param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() ); 965 } while(true); 966 967 return new ast::TupleType{ std::move(types), qs }; 968 } 969 970 template< typename RefType > 971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) { 972 // check that other type is compatible and named the same 973 const RefType * inst2 = handleRefType( inst, other ); 974 if ( ! inst2 ) return; 975 976 // check that parameters of types unify, if any 977 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params; 979 980 auto it = params.begin(); 981 auto jt = params2.begin(); 982 for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) { 983 auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() ); 984 auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() ); 985 986 ast::ptr< ast::Type > pty = param->type; 987 ast::ptr< ast::Type > pty2 = param2->type; 988 989 bool isTuple = Tuples::isTtype( pty ); 990 bool isTuple2 = Tuples::isTtype( pty2 ); 991 992 if ( isTuple && isTuple2 ) { 993 ++it; ++jt; // skip ttype parameters before break 994 } else if ( isTuple ) { 995 // bundle remaining params into tuple 996 pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers ); 997 ++it; // skip ttype parameter for break 998 } else if ( isTuple2 ) { 999 // bundle remaining params into tuple 1000 pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers ); 1001 ++jt; // skip ttype parameter for break 1002 } 1003 1004 if ( ! unifyExact( 1005 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) { 1006 result = false; 1007 return; 1008 } 1009 1010 // ttype parameter should be last 1011 if ( isTuple || isTuple2 ) break; 1012 } 1013 result = it == params.end() && jt == params2.end(); 1014 } 1015 1016 public: 1017 void postvisit( const ast::StructInstType * aggrType ) { 1018 handleGenericRefType( aggrType, type2 ); 1019 } 1020 1021 void postvisit( const ast::UnionInstType * aggrType ) { 1022 handleGenericRefType( aggrType, type2 ); 1023 } 1024 1025 void postvisit( const ast::EnumInstType * aggrType ) { 1026 handleRefType( aggrType, type2 ); 1027 } 1028 1029 void postvisit( const ast::TraitInstType * aggrType ) { 1030 handleRefType( aggrType, type2 ); 1031 } 1032 1033 void postvisit( const ast::TypeInstType * typeInst ) { 1034 assert( open.find( typeInst->name ) == open.end() ); 1035 handleRefType( typeInst, type2 ); 1036 } 1037 1038 private: 1039 /// Creates a tuple type based on a list of Type 1040 static ast::ptr< ast::Type > tupleFromTypes( 1041 const std::vector< ast::ptr< ast::Type > > & tys 1042 ) { 1043 std::vector< ast::ptr< ast::Type > > out; 1044 for ( const ast::Type * ty : tys ) { 1045 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 1046 // that this results in a flat tuple 1047 flatten( ty, out ); 1048 } 1049 1050 return { new ast::TupleType{ std::move(out) } }; 1051 } 1052 1053 static bool unifyList( 1054 const std::vector< ast::ptr< ast::Type > > & list1, 1055 const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env, 1056 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1057 const ast::SymbolTable & symtab 1058 ) { 1059 auto crnt1 = list1.begin(); 1060 auto crnt2 = list2.begin(); 1061 while ( crnt1 != list1.end() && crnt2 != list2.end() ) { 1062 const ast::Type * t1 = *crnt1; 1063 const ast::Type * t2 = *crnt2; 1064 bool isTuple1 = Tuples::isTtype( t1 ); 1065 bool isTuple2 = Tuples::isTtype( t2 ); 1066 1067 // assumes ttype must be last parameter 1068 if ( isTuple1 && ! isTuple2 ) { 1069 // combine entirety of list2, then unify 1070 return unifyExact( 1071 t1, tupleFromTypes( list2 ), env, need, have, open, 1072 noWiden(), symtab ); 1073 } else if ( ! isTuple1 && isTuple2 ) { 1074 // combine entirety of list1, then unify 1075 return unifyExact( 1076 tupleFromTypes( list1 ), t2, env, need, have, open, 1077 noWiden(), symtab ); 1078 } 1079 1080 if ( ! unifyExact( 1081 t1, t2, env, need, have, open, noWiden(), symtab ) 1082 ) return false; 1083 1084 ++crnt1; ++crnt2; 1085 } 1086 1087 if ( crnt1 != list1.end() ) { 1088 // try unifying empty tuple type with ttype 1089 const ast::Type * t1 = *crnt1; 1090 if ( ! Tuples::isTtype( t1 ) ) return false; 1091 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported 1092 // from Rob's code 1093 return unifyExact( 1094 t1, tupleFromTypes( list2 ), env, need, have, open, 1095 noWiden(), symtab ); 1096 } else if ( crnt2 != list2.end() ) { 1097 // try unifying empty tuple with ttype 1098 const ast::Type * t2 = *crnt2; 1099 if ( ! Tuples::isTtype( t2 ) ) return false; 1100 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported 1101 // from Rob's code 1102 return unifyExact( 1103 tupleFromTypes( list1 ), t2, env, need, have, open, 1104 noWiden(), symtab ); 1105 } 1106 1107 return true; 1108 } 1109 1110 public: 1111 void postvisit( const ast::TupleType * tuple ) { 1112 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 ); 1113 if ( ! tuple2 ) return; 1114 1115 ast::Pass<TtypeExpander_new> expander{ tenv }; 1116 const ast::Type * flat = tuple->accept( expander ); 1117 const ast::Type * flat2 = tuple2->accept( expander ); 1118 1119 auto types = flatten( flat ); 1120 auto types2 = flatten( flat2 ); 1121 1122 result = unifyList( types, types2, tenv, need, have, open, symtab ); 1123 } 1124 1125 void postvisit( const ast::VarArgsType * ) { 1126 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 1127 } 1128 1129 void postvisit( const ast::ZeroType * ) { 1130 result = dynamic_cast< const ast::ZeroType * >( type2 ); 1131 } 1132 1133 void postvisit( const ast::OneType * ) { 1134 result = dynamic_cast< const ast::OneType * >( type2 ); 1135 } 1136 1137 private: 1138 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 1139 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 1140 }; 1141 1142 bool unify( 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1144 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab 1146 ) { 1147 ast::ptr<ast::Type> common; 1148 return unify( type1, type2, env, need, have, open, symtab, common ); 1149 } 1150 1151 bool unify( 1152 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1153 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1154 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1155 ) { 1156 ast::OpenVarSet closed; 1157 findOpenVars( type1, open, closed, need, have, FirstClosed ); 1158 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1159 return unifyInexact( 1160 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common ); 1161 } 1162 1163 bool unifyExact( 1164 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 1165 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1166 WidenMode widen, const ast::SymbolTable & symtab 1167 ) { 1168 if ( type1->qualifiers != type2->qualifiers ) return false; 1169 1170 auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 ); 1171 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 ); 1172 ast::OpenVarSet::const_iterator 1173 entry1 = var1 ? open.find( var1->name ) : open.end(), 1174 entry2 = var2 ? open.find( var2->name ) : open.end(); 1175 bool isopen1 = entry1 != open.end(); 1176 bool isopen2 = entry2 != open.end(); 1177 1178 if ( isopen1 && isopen2 ) { 1179 if ( entry1->second.kind != entry2->second.kind ) return false; 1180 return env.bindVarToVar( 1181 var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have, 1182 open, widen, symtab ); 1183 } else if ( isopen1 ) { 1184 return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab ); 1185 } else if ( isopen2 ) { 1186 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); 1187 } else { 1188 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab }; 1189 type1->accept( comparator ); 1190 return comparator.pass.result; 1191 } 1192 } 1193 1194 bool unifyInexact( 1195 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1196 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1197 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 1198 ast::ptr<ast::Type> & common 1199 ) { 1200 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 1201 1202 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1203 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2 ); 1207 1208 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1209 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1210 1211 // if exact unification on unqualified types, try to merge qualifiers 1212 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1213 common = type1; 1214 reset_qualifiers( common, q1 | q2 ); 1215 return true; 1216 } else { 1217 return false; 1218 } 1219 1220 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1221 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1222 1223 // no exact unification, but common type 1224 reset_qualifiers( common, q1 | q2 ); 1225 return true; 1226 } else { 1227 return false; 1228 } 1229 } 1230 1231 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 1232 if ( func->returns.empty() ) return new ast::VoidType{}; 1233 if ( func->returns.size() == 1 ) return func->returns[0]->get_type(); 1234 1235 std::vector<ast::ptr<ast::Type>> tys; 1236 for ( const ast::DeclWithType * decl : func->returns ) { 1237 tys.emplace_back( decl->get_type() ); 1238 } 1239 return new ast::TupleType{ std::move(tys) }; 1240 } 788 1241 } // namespace ResolvExpr 789 1242 -
src/ResolvExpr/Unify.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 13:09:04 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 21 23:09:34 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 18 18 #include <list> // for list 19 19 20 #include "AST/Node.hpp" // for ptr 21 #include "AST/TypeEnvironment.hpp" // for TypeEnvironment, AssertionSet, OpenVarSet 20 22 #include "Common/utility.h" // for deleteAll 21 23 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data 22 24 #include "TypeEnvironment.h" // for AssertionSet, OpenVarSet 25 #include "WidenMode.h" // for WidenMode 23 26 24 27 class Type; 25 28 class TypeInstType; 26 29 namespace SymTab { 27 class Indexer; 28 } // namespace SymTab 30 class Indexer; 31 } 32 33 namespace ast { 34 class SymbolTable; 35 class Type; 36 } 29 37 30 38 namespace ResolvExpr { 31 struct WidenMode {32 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}33 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }34 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }35 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }36 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }37 operator bool() { return widenFirst && widenSecond; }38 39 bool widenFirst : 1, widenSecond : 1;40 };41 42 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );43 39 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 44 40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ); 45 41 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 42 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 46 43 47 44 template< typename Iterator1, typename Iterator2 > … … 72 69 } 73 70 71 bool unify( 72 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 73 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 74 ast::OpenVarSet & open, const ast::SymbolTable & symtab ); 75 76 bool unify( 77 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 78 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 79 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 80 81 bool unifyExact( 82 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 83 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 84 WidenMode widen, const ast::SymbolTable & symtab ); 85 86 bool unifyInexact( 87 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 88 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 89 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 90 ast::ptr<ast::Type> & common ); 91 74 92 } // namespace ResolvExpr 75 93 -
src/ResolvExpr/module.mk
r7951100 rb067d9b 15 15 ############################################################################### 16 16 17 SRC += ResolvExpr/AlternativeFinder.cc \ 18 ResolvExpr/Alternative.cc \ 19 ResolvExpr/Unify.cc \ 20 ResolvExpr/PtrsAssignable.cc \ 21 ResolvExpr/CommonType.cc \ 22 ResolvExpr/ConversionCost.cc \ 23 ResolvExpr/CastCost.cc \ 24 ResolvExpr/PtrsCastable.cc \ 25 ResolvExpr/AdjustExprType.cc \ 26 ResolvExpr/AlternativePrinter.cc \ 27 ResolvExpr/Resolver.cc \ 28 ResolvExpr/ResolveTypeof.cc \ 29 ResolvExpr/RenameVars.cc \ 30 ResolvExpr/FindOpenVars.cc \ 31 ResolvExpr/PolyCost.cc \ 32 ResolvExpr/Occurs.cc \ 33 ResolvExpr/TypeEnvironment.cc \ 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc 17 SRC_RESOLVEXPR = \ 18 ResolvExpr/AdjustExprType.cc \ 19 ResolvExpr/Alternative.cc \ 20 ResolvExpr/AlternativeFinder.cc \ 21 ResolvExpr/Candidate.cpp \ 22 ResolvExpr/CandidateFinder.cpp \ 23 ResolvExpr/CastCost.cc \ 24 ResolvExpr/CommonType.cc \ 25 ResolvExpr/ConversionCost.cc \ 26 ResolvExpr/CurrentObject.cc \ 27 ResolvExpr/ExplodedActual.cc \ 28 ResolvExpr/ExplodedArg.cpp \ 29 ResolvExpr/FindOpenVars.cc \ 30 ResolvExpr/Occurs.cc \ 31 ResolvExpr/PolyCost.cc \ 32 ResolvExpr/PtrsAssignable.cc \ 33 ResolvExpr/PtrsCastable.cc \ 34 ResolvExpr/RenameVars.cc \ 35 ResolvExpr/ResolveAssertions.cc \ 36 ResolvExpr/Resolver.cc \ 37 ResolvExpr/ResolveTypeof.cc \ 38 ResolvExpr/SatisfyAssertions.cpp \ 39 ResolvExpr/SpecCost.cc \ 40 ResolvExpr/TypeEnvironment.cc \ 41 ResolvExpr/Unify.cc 42 43 SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc 44 SRCDEMANGLE += $(SRC_RESOLVEXPR) -
src/ResolvExpr/typeops.h
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 07:28:22 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:18 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Aug 8 16:36:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 18 18 #include <vector> 19 19 20 #include "Cost.h" 21 #include "TypeEnvironment.h" 22 #include "WidenMode.h" 23 #include "AST/Fwd.hpp" 24 #include "AST/Node.hpp" 25 #include "AST/SymbolTable.hpp" 26 #include "AST/Type.hpp" 27 #include "AST/TypeEnvironment.hpp" 20 28 #include "SynTree/SynTree.h" 21 29 #include "SynTree/Type.h" 22 #include "SymTab/Indexer.h" 23 #include "Cost.h" 24 #include "TypeEnvironment.h" 30 31 namespace SymTab { 32 class Indexer; 33 } 25 34 26 35 namespace ResolvExpr { … … 54 63 // in AdjustExprType.cc 55 64 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function 56 void adjustExprType( Type *& type, const TypeEnvironment &env, const SymTab::Indexer &indexer );65 void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 57 66 58 67 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer … … 60 69 61 70 template< typename ForwardIterator > 62 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {71 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) { 63 72 while ( begin != end ) { 64 73 adjustExprType( *begin++, env, indexer ); … … 66 75 } 67 76 77 /// Replaces array types with equivalent pointer, and function types with a pointer-to-function 78 const ast::Type * adjustExprType( 79 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab ); 80 68 81 // in CastCost.cc 69 Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 82 Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue, 83 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 84 Cost castCost( 85 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 86 const ast::TypeEnvironment & env ); 70 87 71 88 // in ConversionCost.cc 72 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 89 Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue, 90 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 91 Cost conversionCost( 92 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 93 const ast::TypeEnvironment & env ); 94 95 // in AlternativeFinder.cc 96 Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue, 97 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 73 98 74 99 // in PtrsAssignable.cc 75 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ); 100 int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env ); 101 int ptrsAssignable( const ast::Type * src, const ast::Type * dst, 102 const ast::TypeEnvironment & env ); 76 103 77 104 // in PtrsCastable.cc 78 int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 105 int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 106 int ptrsCastable( 107 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 108 const ast::TypeEnvironment & env ); 79 109 80 110 // in Unify.cc 81 bool isFtype( Type *type ); 82 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 83 bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 84 85 inline bool typesCompatible( Type *t1, Type *t2, const SymTab::Indexer &indexer ) { 111 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 112 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 113 114 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 86 115 TypeEnvironment env; 87 116 return typesCompatible( t1, t2, indexer, env ); 88 117 } 89 118 90 inline bool typesCompatibleIgnoreQualifiers( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {119 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 91 120 TypeEnvironment env; 92 121 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env ); 93 122 } 94 123 124 bool typesCompatible( 125 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {}, 126 const ast::TypeEnvironment & env = {} ); 127 128 bool typesCompatibleIgnoreQualifiers( 129 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 130 const ast::TypeEnvironment & env = {} ); 131 95 132 /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value. 96 133 Type * extractResultType( FunctionType * functionType ); 134 /// Creates or extracts the type represented by the list of returns in a `FunctionType`. 135 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ); 97 136 98 137 // in CommonType.cc 99 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 138 Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars ); 139 ast::ptr< ast::Type > commonType( 140 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen, 141 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 100 142 101 143 // in PolyCost.cc 102 int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 144 int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 145 int polyCost( 146 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 147 148 // in SpecCost.cc 149 int specCost( Type * type ); 150 int specCost( const ast::Type * type ); 103 151 104 152 // in Occurs.cc 105 bool occurs( Type *type, std::string varName, const TypeEnvironment &env ); 153 bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env ); 154 // new AST version in TypeEnvironment.cpp (only place it was used in old AST) 155 156 template<typename Iter> 157 bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) { 158 while ( begin != end ) { 159 if ( occurs( ty, *begin, env ) ) return true; 160 ++begin; 161 } 162 return false; 163 } 106 164 107 165 // in AlternativeFinder.cc 108 166 void referenceToRvalueConversion( Expression *& expr, Cost & cost ); 109 110 // flatten tuple type into list of types 167 // in CandidateFinder.cpp 168 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ); 169 170 /// flatten tuple type into list of types 111 171 template< typename OutputIterator > 112 172 void flatten( Type * type, OutputIterator out ) { … … 119 179 } 120 180 } 181 182 /// flatten tuple type into existing list of types 183 static inline void flatten( 184 const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out 185 ) { 186 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) { 187 for ( const ast::Type * t : tupleType->types ) { 188 flatten( t, out ); 189 } 190 } else { 191 out.emplace_back( type ); 192 } 193 } 194 195 /// flatten tuple type into list of types 196 static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) { 197 std::vector< ast::ptr< ast::Type > > out; 198 out.reserve( type->size() ); 199 flatten( type, out ); 200 return out; 201 } 202 203 // in TypeEnvironment.cc 204 bool isFtype( const Type * type ); 121 205 } // namespace ResolvExpr 206 207 namespace ast { 208 // in TypeEnvironment.cpp 209 bool isFtype( const ast::Type * type ); 210 } // namespace ast 122 211 123 212 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.