Changeset 3f7e12cb for src/SymTab
- Timestamp:
- Nov 8, 2017, 5:43:33 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, stuck-waitfor-destruct, with_gc
- Children:
- 954908d
- Parents:
- 78315272 (diff), e35f30a (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/SymTab
- Files:
-
- 9 edited
-
Autogen.cc (modified) (16 diffs)
-
Autogen.h (modified) (10 diffs)
-
FixFunction.cc (modified) (1 diff)
-
FixFunction.h (modified) (1 diff)
-
Indexer.cc (modified) (5 diffs)
-
Indexer.h (modified) (3 diffs)
-
Mangler.cc (modified) (17 diffs)
-
Mangler.h (modified) (3 diffs)
-
Validate.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
r78315272 r3f7e12cb 16 16 #include "Autogen.h" 17 17 18 #include <cstddef> // for NULL19 18 #include <algorithm> // for count_if 20 19 #include <cassert> // for strict_dynamic_cast, assert, assertf … … 27 26 #include "AddVisit.h" // for addVisit 28 27 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 28 #include "Common/PassVisitor.h" // for PassVisitor 29 29 #include "Common/ScopedMap.h" // for ScopedMap<>::const_iterator, Scope... 30 30 #include "Common/utility.h" // for cloneAll, operator+ 31 #include "GenPoly/DeclMutator.h" // for DeclMutator32 31 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 32 #include "InitTweak/GenInit.h" // for fixReturnStatements 33 #include "ResolvExpr/Resolver.h" // for resolveDecl 33 34 #include "SymTab/Mangler.h" // for Mangler 34 35 #include "SynTree/Attribute.h" // For Attribute … … 42 43 namespace SymTab { 43 44 Type * SizeType = 0; 44 typedef ScopedMap< std::string, bool > TypeMap; 45 46 /// Data used to generate functions generically. Specifically, the name of the generated function, a function which generates the routine protoype, and a map which contains data to determine whether a function should be generated. 45 46 /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype 47 47 struct FuncData { 48 48 typedef FunctionType * (*TypeGen)( Type * ); 49 FuncData( const std::string & fname, const TypeGen & genType , TypeMap & map ) : fname( fname ), genType( genType ), map( map) {}49 FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {} 50 50 std::string fname; 51 51 TypeGen genType; 52 TypeMap & map; 53 }; 54 55 class AutogenerateRoutines final : public Visitor { 56 template< typename Visitor > 57 friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor ); 58 template< typename Visitor > 59 friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor ); 60 public: 61 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; } 62 63 typedef Visitor Parent; 64 using Parent::visit; 65 52 }; 53 54 struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting, public WithIndexer { 66 55 AutogenerateRoutines(); 67 56 68 virtual void visit( EnumDecl *enumDecl ); 69 virtual void visit( StructDecl *structDecl ); 70 virtual void visit( UnionDecl *structDecl ); 71 virtual void visit( TypeDecl *typeDecl ); 72 virtual void visit( TraitDecl *ctxDecl ); 73 virtual void visit( FunctionDecl *functionDecl ); 74 75 virtual void visit( FunctionType *ftype ); 76 virtual void visit( PointerType *ftype ); 77 78 virtual void visit( CompoundStmt *compoundStmt ); 79 virtual void visit( SwitchStmt *switchStmt ); 57 void previsit( EnumDecl * enumDecl ); 58 void previsit( StructDecl * structDecl ); 59 void previsit( UnionDecl * structDecl ); 60 void previsit( TypeDecl * typeDecl ); 61 void previsit( TraitDecl * traitDecl ); 62 void previsit( FunctionDecl * functionDecl ); 63 64 void previsit( FunctionType * ftype ); 65 void previsit( PointerType * ptype ); 66 67 void previsit( CompoundStmt * compoundStmt ); 80 68 81 69 private: 82 template< typename StmtClass > void visitStatement( StmtClass *stmt ); 83 84 std::list< Declaration * > declsToAdd, declsToAddAfter; 85 std::set< std::string > structsDone; 70 71 GenPoly::ScopedSet< std::string > structsDone; 86 72 unsigned int functionNesting = 0; // current level of nested functions 87 /// Note: the following maps could be ScopedSets, but it should be easier to work 88 /// deleted functions in if they are maps, since the value false can be inserted 89 /// at the current scope without affecting outer scopes or requiring copies. 90 TypeMap copyable, assignable, constructable, destructable; 73 74 InitTweak::ManagedTypes managedTypes; 91 75 std::vector< FuncData > data; 92 76 }; 93 77 94 78 /// generates routines for tuple types. 95 /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit 96 /// or anything we currently have that supports adding new declarations for visitors 97 class AutogenTupleRoutines : public GenPoly::DeclMutator { 98 public: 99 typedef GenPoly::DeclMutator Parent; 100 using Parent::mutate; 101 102 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 103 104 virtual Type * mutate( TupleType *tupleType ); 105 106 virtual CompoundStmt * mutate( CompoundStmt *compoundStmt ); 79 struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting { 80 void previsit( FunctionDecl * functionDecl ); 81 82 void postvisit( TupleType * tupleType ); 83 84 void previsit( CompoundStmt * compoundStmt ); 107 85 108 86 private: … … 112 90 113 91 void autogenerateRoutines( std::list< Declaration * > &translationUnit ) { 114 AutogenerateRoutinesgenerator;115 acceptA ndAdd( translationUnit, generator );92 PassVisitor<AutogenerateRoutines> generator; 93 acceptAll( translationUnit, generator ); 116 94 117 95 // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc. 118 96 // AutogenTupleRoutines tupleGenerator; 119 // tupleGenerator.mutateDeclarationList( translationUnit ); 97 // acceptAll( translationUnit, tupleGenerator ); 98 } 99 100 //============================================================================================= 101 // FuncGenerator definitions 102 //============================================================================================= 103 class FuncGenerator { 104 public: 105 std::list< Declaration * > definitions, forwards; 106 107 FuncGenerator( Type * type, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : type( type ), data( data ), functionNesting( functionNesting ), indexer( indexer ) {} 108 109 virtual bool shouldAutogen() const = 0; 110 void genStandardFuncs(); 111 virtual void genFieldCtors() = 0; 112 protected: 113 Type * type; 114 const std::vector< FuncData > & data; 115 unsigned int functionNesting; 116 SymTab::Indexer & indexer; 117 118 virtual void genFuncBody( FunctionDecl * dcl ) = 0; 119 virtual bool isConcurrentType() const = 0; 120 121 void resolve( FunctionDecl * dcl ); 122 void generatePrototypes( std::list< FunctionDecl * > & newFuncs ); 123 }; 124 125 class StructFuncGenerator : public FuncGenerator { 126 StructDecl * aggregateDecl; 127 public: 128 StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {} 129 130 virtual bool shouldAutogen() const override; 131 virtual bool isConcurrentType() const override; 132 133 virtual void genFuncBody( FunctionDecl * dcl ) override; 134 virtual void genFieldCtors() override; 135 136 private: 137 /// generates a single struct member operation (constructor call, destructor call, assignment call) 138 void makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ); 139 140 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 141 template<typename Iterator> 142 void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ); 143 144 /// generate the body of a constructor which takes parameters that match fields, e.g. 145 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 146 template<typename Iterator> 147 void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ); 148 }; 149 150 class UnionFuncGenerator : public FuncGenerator { 151 UnionDecl * aggregateDecl; 152 public: 153 UnionFuncGenerator( UnionDecl * aggregateDecl, UnionInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {} 154 155 virtual bool shouldAutogen() const override; 156 virtual bool isConcurrentType() const override; 157 158 virtual void genFuncBody( FunctionDecl * dcl ) override; 159 virtual void genFieldCtors() override; 160 161 private: 162 /// generates a single struct member operation (constructor call, destructor call, assignment call) 163 template<typename OutputIterator> 164 void makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ); 165 166 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 167 template<typename Iterator> 168 void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ); 169 170 /// generate the body of a constructor which takes parameters that match fields, e.g. 171 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 172 template<typename Iterator> 173 void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ); 174 }; 175 176 class EnumFuncGenerator : public FuncGenerator { 177 public: 178 EnumFuncGenerator( EnumInstType * refType, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ) {} 179 180 virtual bool shouldAutogen() const override; 181 virtual bool isConcurrentType() const override; 182 183 virtual void genFuncBody( FunctionDecl * dcl ) override; 184 virtual void genFieldCtors() override; 185 186 private: 187 }; 188 189 class TypeFuncGenerator : public FuncGenerator { 190 TypeDecl * typeDecl; 191 public: 192 TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, const std::vector<FuncData> & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), typeDecl( typeDecl ) {} 193 194 virtual bool shouldAutogen() const override; 195 virtual void genFuncBody( FunctionDecl * dcl ) override; 196 virtual bool isConcurrentType() const override; 197 virtual void genFieldCtors() override; 198 }; 199 200 //============================================================================================= 201 // helper functions 202 //============================================================================================= 203 void generateFunctions( FuncGenerator & gen, std::list< Declaration * > & declsToAdd ) { 204 if ( ! gen.shouldAutogen() ) return; 205 206 // generate each of the functions based on the supplied FuncData objects 207 gen.genStandardFuncs(); 208 gen.genFieldCtors(); 209 210 declsToAdd.splice( declsToAdd.end(), gen.forwards ); 211 declsToAdd.splice( declsToAdd.end(), gen.definitions ); 120 212 } 121 213 122 214 bool isUnnamedBitfield( ObjectDecl * obj ) { 123 return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;215 return obj != nullptr && obj->name == "" && obj->bitfieldWidth != nullptr; 124 216 } 125 217 … … 127 219 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { 128 220 FunctionDecl * decl = functionDecl->clone(); 129 delete decl-> get_statements();130 decl->s et_statements( NULL );221 delete decl->statements; 222 decl->statements = nullptr; 131 223 declsToAdd.push_back( decl ); 132 224 decl->fixUniqueId(); 133 225 } 134 226 227 const std::list< TypeDecl * > getGenericParams( Type * t ) { 228 std::list< TypeDecl * > * ret = nullptr; 229 if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) { 230 ret = inst->get_baseParameters(); 231 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 232 ret = inst->get_baseParameters(); 233 } 234 return ret ? *ret : std::list< TypeDecl * >(); 235 } 236 135 237 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 136 238 FunctionType * genDefaultType( Type * paramType ) { 239 const auto & typeParams = getGenericParams( paramType ); 137 240 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 241 cloneAll( typeParams, ftype->forall ); 138 242 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr ); 139 ftype->get_parameters().push_back( dstParam ); 140 243 ftype->parameters.push_back( dstParam ); 141 244 return ftype; 142 245 } … … 146 249 FunctionType *ftype = genDefaultType( paramType ); 147 250 ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 148 ftype-> get_parameters().push_back( srcParam );251 ftype->parameters.push_back( srcParam ); 149 252 return ftype; 150 253 } … … 154 257 FunctionType *ftype = genCopyType( paramType ); 155 258 ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 156 ftype-> get_returnVals().push_back( returnVal );259 ftype->returnVals.push_back( returnVal ); 157 260 return ftype; 158 261 } … … 171 274 } 172 275 173 /// inserts base type of first argument into map if pred(funcDecl) is true 174 void insert( FunctionDecl *funcDecl, TypeMap & map, FunctionDecl * (*pred)(Declaration *) ) { 175 // insert type into constructable, etc. map if appropriate 176 if ( pred( funcDecl ) ) { 177 FunctionType * ftype = funcDecl->get_functionType(); 178 assert( ! ftype->get_parameters().empty() ); 179 Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() ); 180 assert( t ); 181 map.insert( Mangler::mangleType( t ), true ); 182 } 183 } 184 185 /// using map and t, determines if is constructable, etc. 186 bool lookup( const TypeMap & map, Type * t ) { 187 assertf( t, "Autogenerate lookup was given non-type: %s", toString( t ).c_str() ); 188 if ( dynamic_cast< PointerType * >( t ) ) { 189 // will need more complicated checking if we want this to work with pointer types, since currently 190 return true; 191 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) { 192 // an array's constructor, etc. is generated on the fly based on the base type's constructor, etc. 193 return lookup( map, at->get_base() ); 194 } 195 TypeMap::const_iterator it = map.find( Mangler::mangleType( t ) ); 196 if ( it != map.end() ) return it->second; 197 // something that does not appear in the map is by default not constructable, etc. 198 return false; 199 } 200 201 /// using map and aggr, examines each member to determine if constructor, etc. should be generated 202 template<typename Container> 203 bool shouldGenerate( const TypeMap & map, const Container & container ) { 204 for ( Type * t : container ) { 205 if ( ! lookup( map, t ) ) return false; 206 } 207 return true; 208 } 209 210 /// data structure for abstracting the generation of special functions 211 template< typename OutputIterator, typename Container > 212 struct FuncGenerator { 213 const Container & container; 214 Type *refType; 215 unsigned int functionNesting; 216 const std::list< TypeDecl* > & typeParams; 217 OutputIterator out; 218 FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {} 219 220 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map. 221 void gen( const FuncData & data, bool concurrent_type ) { 222 if ( ! shouldGenerate( data.map, container ) ) return; 223 FunctionType * ftype = data.genType( refType ); 224 225 if ( concurrent_type && CodeGen::isDestructor( data.fname ) ) { 276 Type * declToType( Declaration * decl ) { 277 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 278 return dwt->get_type(); 279 } 280 return nullptr; 281 } 282 283 Type * declToTypeDeclBase( Declaration * decl ) { 284 if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) { 285 return td->base; 286 } 287 return nullptr; 288 } 289 290 //============================================================================================= 291 // FuncGenerator member definitions 292 //============================================================================================= 293 void FuncGenerator::genStandardFuncs() { 294 std::list< FunctionDecl * > newFuncs; 295 generatePrototypes( newFuncs ); 296 297 for ( FunctionDecl * dcl : newFuncs ) { 298 genFuncBody( dcl ); 299 if ( CodeGen::isAssignment( dcl->name ) ) { 300 // assignment needs to return a value 301 FunctionType * assignType = dcl->type; 302 assert( assignType->parameters.size() == 2 ); 303 assert( assignType->returnVals.size() == 1 ); 304 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.front() ); 305 dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( dstParam ) ) ); 306 } 307 resolve( dcl ); 308 } 309 } 310 311 void FuncGenerator::generatePrototypes( std::list< FunctionDecl * > & newFuncs ) { 312 bool concurrent_type = isConcurrentType(); 313 for ( const FuncData & d : data ) { 314 // generate a function (?{}, ?=?, ^?{}) based on the current FuncData. 315 FunctionType * ftype = d.genType( type ); 316 317 // destructor for concurrent type must be mutex 318 if ( concurrent_type && CodeGen::isDestructor( d.fname ) ) { 226 319 ftype->parameters.front()->get_type()->set_mutex( true ); 227 320 } 228 321 229 cloneAll( typeParams, ftype->forall ); 230 *out++ = genFunc( data.fname, ftype, functionNesting ); 231 data.map.insert( Mangler::mangleType( refType ), true ); 232 } 233 }; 234 235 template< typename OutputIterator, typename Container > 236 FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) { 237 return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, typeParams, out ); 238 } 239 240 /// generates a single enumeration assignment expression 241 ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) { 242 // enum copy construct and assignment is just C-style assignment. 243 // this looks like a bad recursive call, but code gen will turn it into 244 // a C-style assignment. 245 // This happens before function pointer type conversion, so need to do it manually here 246 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the 247 // type of the function that this expression is being generated for (so that the correct 248 // parameters) are using in the variable exprs 249 assert( ftype->get_parameters().size() == 2 ); 250 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 251 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 252 253 VariableExpr * assignVarExpr = new VariableExpr( assignDecl ); 254 Type * assignVarExprType = assignVarExpr->get_result(); 255 assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType ); 256 assignVarExpr->set_result( assignVarExprType ); 257 ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr ); 258 assignExpr->get_args().push_back( new VariableExpr( dstParam ) ); 259 assignExpr->get_args().push_back( new VariableExpr( srcParam ) ); 260 return assignExpr; 261 } 262 263 // E ?=?(E volatile*, int), 264 // ?=?(E _Atomic volatile*, int); 265 void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) { 266 267 // T ?=?(E *, E); 268 FunctionType *assignType = genAssignType( refType ); 269 270 // void ?{}(E *); void ^?{}(E *); 271 FunctionType * ctorType = genDefaultType( refType->clone() ); 272 FunctionType * dtorType = genDefaultType( refType->clone() ); 273 274 // void ?{}(E *, E); 275 FunctionType *copyCtorType = genCopyType( refType->clone() ); 276 277 // add unused attribute to parameters of default constructor and destructor 278 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 279 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 280 281 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 282 // right now these cases work, but that might change. 283 284 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment. 285 // Really they're something of a cross between instrinsic and autogen, so should 286 // probably make a new linkage type 287 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true ); 288 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true ); 289 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true ); 290 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true ); 291 292 // body is either return stmt or expr stmt 293 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) ); 294 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) ); 295 296 declsToAdd.push_back( ctorDecl ); 297 declsToAdd.push_back( copyCtorDecl ); 298 declsToAdd.push_back( dtorDecl ); 299 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 300 } 301 302 /// generates a single struct member operation (constructor call, destructor call, assignment call) 303 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) { 322 newFuncs.push_back( genFunc( d.fname, ftype, functionNesting ) ); 323 } 324 } 325 326 void FuncGenerator::resolve( FunctionDecl * dcl ) { 327 try { 328 ResolvExpr::resolveDecl( dcl, indexer ); 329 if ( functionNesting == 0 ) { 330 // forward declare if top-level struct, so that 331 // type is complete as soon as its body ends 332 // Note: this is necessary if we want structs which contain 333 // generic (otype) structs as members. 334 addForwardDecl( dcl, forwards ); 335 } 336 definitions.push_back( dcl ); 337 indexer.addId( dcl ); 338 } catch ( SemanticError err ) { 339 // okay if decl does not resolve - that means the function should not be generated 340 delete dcl; 341 } 342 } 343 344 bool StructFuncGenerator::shouldAutogen() const { 345 // Builtins do not use autogeneration. 346 return ! aggregateDecl->linkage.is_builtin; 347 } 348 bool StructFuncGenerator::isConcurrentType() const { return aggregateDecl->is_thread() || aggregateDecl->is_monitor(); } 349 350 void StructFuncGenerator::genFuncBody( FunctionDecl * dcl ) { 351 // generate appropriate calls to member ctor, assignment 352 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 353 if ( ! CodeGen::isDestructor( dcl->name ) ) { 354 makeFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl ); 355 } else { 356 makeFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false ); 357 } 358 } 359 360 void StructFuncGenerator::genFieldCtors() { 361 // field ctors are only generated if default constructor and copy constructor are both generated 362 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->name ); } ); 363 364 // Field constructors are only generated if default and copy constructor 365 // are generated, since they need access to both 366 if ( numCtors != 2 ) return; 367 368 // create constructors which take each member type as a parameter. 369 // for example, for struct A { int x, y; }; generate 370 // void ?{}(A *, int) and void ?{}(A *, int, int) 371 FunctionType * memCtorType = genDefaultType( type ); 372 for ( Declaration * member : aggregateDecl->members ) { 373 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 374 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 375 // don't make a function whose parameter is an unnamed bitfield 376 continue; 377 } 378 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) ); 379 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 380 makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor ); 381 resolve( ctor ); 382 } 383 delete memCtorType; 384 } 385 386 void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) { 304 387 InitTweak::InitExpander srcParam( src ); 305 388 306 389 // assign to destination 307 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) ); 308 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 309 } 310 311 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 390 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->base->clone() ) ); 391 genImplicitCall( srcParam, dstselect, func->name, back_inserter( func->statements->kids ), field, forward ); 392 } 393 312 394 template<typename Iterator> 313 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true) {395 void StructFuncGenerator::makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward ) { 314 396 for ( ; member != end; ++member ) { 315 397 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate … … 321 403 } 322 404 323 if ( type->get_const() && func->get_name() == "?=?") {405 if ( type->get_const() && CodeGen::isAssignment( func->name ) ) { 324 406 // don't assign const members, but do construct/destruct 325 407 continue; 326 408 } 327 409 328 if ( field->get_name() == "" ) {329 // don't assign to anonymous members330 // xxx - this is a temporary fix. Anonymous members tie into331 // our inheritance model. I think the correct way to handle this is to332 // cast the structure to the type of the member and let the resolver333 // figure out whether it's valid and have a pass afterwards that fixes334 // the assignment to use pointer arithmetic with the offset of the335 // member, much like how generic type members are handled.336 continue;337 }338 339 410 assert( ! func->get_functionType()->get_parameters().empty() ); 340 411 ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() ); 341 ObjectDecl * srcParam = NULL;412 ObjectDecl * srcParam = nullptr; 342 413 if ( func->get_functionType()->get_parameters().size() == 2 ) { 343 414 srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() ); 344 415 } 416 345 417 // srcParam may be NULL, in which case we have default ctor/dtor 346 418 assert( dstParam ); 347 419 348 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;349 make StructMemberOp( dstParam, srcselect, field, func, forward );420 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr; 421 makeMemberOp( dstParam, srcselect, field, func, forward ); 350 422 } // if 351 423 } // for 352 } // makeStructFunctionBody 353 354 /// generate the body of a constructor which takes parameters that match fields, e.g. 355 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 424 } // makeFunctionBody 425 356 426 template<typename Iterator> 357 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {358 FunctionType * ftype = func-> get_functionType();359 std::list<DeclarationWithType*> & params = ftype-> get_parameters();427 void StructFuncGenerator::makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) { 428 FunctionType * ftype = func->type; 429 std::list<DeclarationWithType*> & params = ftype->parameters; 360 430 assert( params.size() >= 2 ); // should not call this function for default ctor, etc. 361 431 … … 369 439 // don't make a function whose parameter is an unnamed bitfield 370 440 continue; 371 } else if ( field->get_name() == "" ) {372 // don't assign to anonymous members373 // xxx - this is a temporary fix. Anonymous members tie into374 // our inheritance model. I think the correct way to handle this is to375 // cast the structure to the type of the member and let the resolver376 // figure out whether it's valid and have a pass afterwards that fixes377 // the assignment to use pointer arithmetic with the offset of the378 // member, much like how generic type members are handled.379 continue;380 441 } else if ( parameter != params.end() ) { 381 442 // matching parameter, initialize field with copy ctor 382 443 Expression *srcselect = new VariableExpr(*parameter); 383 make StructMemberOp( dstParam, srcselect, field, func );444 makeMemberOp( dstParam, srcselect, field, func ); 384 445 ++parameter; 385 446 } else { 386 447 // no matching parameter, initialize field with default ctor 387 make StructMemberOp( dstParam, NULL, field, func );448 makeMemberOp( dstParam, nullptr, field, func ); 388 449 } 389 450 } … … 391 452 } 392 453 393 Type * declToType( Declaration * decl ) { 394 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 395 return dwt->get_type(); 396 } 397 return nullptr; 398 } 399 400 /// generates struct constructors, destructor, and assignment functions 401 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) { 454 bool UnionFuncGenerator::shouldAutogen() const { 402 455 // Builtins do not use autogeneration. 403 if ( aggregateDecl->get_linkage() == LinkageSpec::BuiltinCFA || 404 aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) { 405 return; 406 } 407 408 // Make function polymorphic in same parameters as generic struct, if applicable 409 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 410 411 // generate each of the functions based on the supplied FuncData objects 412 std::list< FunctionDecl * > newFuncs; 413 // structure that iterates aggregate decl members, returning their types 414 auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, typeParams, back_inserter( newFuncs ) ); 415 for ( const FuncData & d : data ) { 416 generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() ); 417 } 418 456 return ! aggregateDecl->linkage.is_builtin; 457 } 458 459 // xxx - is this right? 460 bool UnionFuncGenerator::isConcurrentType() const { return false; }; 461 462 /// generate a single union assignment expression (using memcpy) 463 template< typename OutputIterator > 464 void UnionFuncGenerator::makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 465 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 466 copy->args.push_back( new AddressExpr( new VariableExpr( dstParam ) ) ); 467 copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 468 copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); 469 *out++ = new ExprStmt( noLabels, copy ); 470 } 471 472 /// generates the body of a union assignment/copy constructor/field constructor 473 void UnionFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) { 474 FunctionType * ftype = funcDecl->type; 475 if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) { 476 assert( ftype->parameters.size() == 2 ); 477 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 478 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() ); 479 makeMemberOp( srcParam, dstParam, back_inserter( funcDecl->statements->kids ) ); 480 } else { 481 // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings 482 assert( ftype->parameters.size() == 1 ); 483 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 484 dstParam->attributes.push_back( new Attribute( "unused" ) ); 485 } 486 } 487 488 /// generate the body of a constructor which takes parameters that match fields, e.g. 489 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 490 void UnionFuncGenerator::genFieldCtors() { 419 491 // field ctors are only generated if default constructor and copy constructor are both generated 420 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 421 422 if ( functionNesting == 0 ) { 423 // forward declare if top-level struct, so that 424 // type is complete as soon as its body ends 425 // Note: this is necessary if we want structs which contain 426 // generic (otype) structs as members. 427 for ( FunctionDecl * dcl : newFuncs ) { 428 addForwardDecl( dcl, declsToAdd ); 429 } 430 } 431 432 for ( FunctionDecl * dcl : newFuncs ) { 433 // generate appropriate calls to member ctor, assignment 434 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 435 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) { 436 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl ); 437 } else { 438 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false ); 439 } 440 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 441 // assignment needs to return a value 442 FunctionType * assignType = dcl->get_functionType(); 443 assert( assignType->get_parameters().size() == 2 ); 444 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 445 dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 446 } 447 declsToAdd.push_back( dcl ); 448 } 449 450 // create constructors which take each member type as a parameter. 451 // for example, for struct A { int x, y; }; generate 452 // void ?{}(A *, int) and void ?{}(A *, int, int) 492 unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 493 453 494 // Field constructors are only generated if default and copy constructor 454 495 // are generated, since they need access to both 455 if ( numCtors == 2 ) { 456 FunctionType * memCtorType = genDefaultType( refType ); 457 cloneAll( typeParams, memCtorType->get_forall() ); 458 for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) { 459 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i ); 460 assert( member ); 461 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) { 462 // don't make a function whose parameter is an unnamed bitfield 463 continue; 464 } else if ( member->get_name() == "" ) { 465 // don't assign to anonymous members 466 // xxx - this is a temporary fix. Anonymous members tie into 467 // our inheritance model. I think the correct way to handle this is to 468 // cast the structure to the type of the member and let the resolver 469 // figure out whether it's valid/choose the correct unnamed member 470 continue; 471 } 472 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 473 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 474 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor ); 475 declsToAdd.push_back( ctor ); 476 } 477 delete memCtorType; 478 } 479 } 480 481 /// generate a single union assignment expression (using memcpy) 482 template< typename OutputIterator > 483 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 484 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 485 copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) ); 486 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 487 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); 488 *out++ = new ExprStmt( noLabels, copy ); 489 } 490 491 /// generates the body of a union assignment/copy constructor/field constructor 492 void makeUnionAssignBody( FunctionDecl * funcDecl ) { 493 FunctionType * ftype = funcDecl->get_functionType(); 494 assert( ftype->get_parameters().size() == 2 ); 495 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 496 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 497 498 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) ); 499 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) { 500 // also generate return statement in assignment 501 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 502 } 503 } 504 505 /// generates union constructors, destructors, and assignment operator 506 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 507 // Make function polymorphic in same parameters as generic union, if applicable 508 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 509 510 // default ctor/dtor need only first parameter 511 // void ?{}(T *); void ^?{}(T *); 512 FunctionType *ctorType = genDefaultType( refType ); 513 FunctionType *dtorType = genDefaultType( refType ); 514 515 // copy ctor needs both parameters 516 // void ?{}(T *, T); 517 FunctionType *copyCtorType = genCopyType( refType ); 518 519 // assignment needs both and return value 520 // T ?=?(T *, T); 521 FunctionType *assignType = genAssignType( refType ); 522 523 cloneAll( typeParams, ctorType->get_forall() ); 524 cloneAll( typeParams, dtorType->get_forall() ); 525 cloneAll( typeParams, copyCtorType->get_forall() ); 526 cloneAll( typeParams, assignType->get_forall() ); 527 528 // add unused attribute to parameters of default constructor and destructor 529 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 530 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 531 532 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 533 // because each unit generates copies of the default routines for each aggregate. 534 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 535 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 536 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 537 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 538 539 makeUnionAssignBody( assignDecl ); 540 541 // body of assignment and copy ctor is the same 542 makeUnionAssignBody( copyCtorDecl ); 496 if ( numCtors != 2 ) return; 543 497 544 498 // create a constructor which takes the first member type as a parameter. … … 546 500 // void ?{}(A *, int) 547 501 // This is to mimic C's behaviour which initializes the first member of the union. 548 std::list<Declaration *> memCtors; 549 for ( Declaration * member : aggregateDecl->get_members() ) { 550 if ( DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member ) ) { 551 ObjectDecl * srcParam = new ObjectDecl( "src", Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ); 552 553 FunctionType * memCtorType = ctorType->clone(); 554 memCtorType->get_parameters().push_back( srcParam ); 555 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting ); 556 557 makeUnionAssignBody( ctor ); 558 memCtors.push_back( ctor ); 559 // only generate a ctor for the first field 502 FunctionType * memCtorType = genDefaultType( type ); 503 for ( Declaration * member : aggregateDecl->members ) { 504 DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member ); 505 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) { 506 // don't make a function whose parameter is an unnamed bitfield 560 507 break; 561 508 } 562 } 563 564 declsToAdd.push_back( ctorDecl ); 565 declsToAdd.push_back( copyCtorDecl ); 566 declsToAdd.push_back( dtorDecl ); 567 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 568 declsToAdd.splice( declsToAdd.end(), memCtors ); 569 } 570 509 memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, field->get_type()->clone(), nullptr ) ); 510 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 511 ObjectDecl * srcParam = strict_dynamic_cast<ObjectDecl *>( ctor->type->parameters.back() ); 512 srcParam->fixUniqueId(); 513 ObjectDecl * dstParam = InitTweak::getParamThis( ctor->type ); 514 makeMemberOp( srcParam, dstParam, back_inserter( ctor->statements->kids ) ); 515 resolve( ctor ); 516 // only generate one field ctor for unions 517 break; 518 } 519 delete memCtorType; 520 } 521 522 void EnumFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) { 523 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment. 524 // Really they're something of a cross between instrinsic and autogen, so should 525 // probably make a new linkage type 526 funcDecl->linkage = LinkageSpec::Intrinsic; 527 FunctionType * ftype = funcDecl->type; 528 if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) { 529 assert( ftype->parameters.size() == 2 ); 530 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 531 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() ); 532 533 // enum copy construct and assignment is just C-style assignment. 534 // this looks like a bad recursive call, but code gen will turn it into 535 // a C-style assignment. 536 // This happens before function pointer type conversion, so need to do it manually here 537 ApplicationExpr * callExpr = new ApplicationExpr( VariableExpr::functionPointer( funcDecl ) ); 538 callExpr->get_args().push_back( new VariableExpr( dstParam ) ); 539 callExpr->get_args().push_back( new VariableExpr( srcParam ) ); 540 funcDecl->statements->push_back( new ExprStmt( noLabels, callExpr ) ); 541 } else { 542 // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings 543 assert( ftype->parameters.size() == 1 ); 544 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() ); 545 dstParam->attributes.push_back( new Attribute( "unused" ) ); 546 } 547 } 548 549 bool EnumFuncGenerator::shouldAutogen() const { return true; } 550 bool EnumFuncGenerator::isConcurrentType() const { return false; } 551 // enums do not have field constructors 552 void EnumFuncGenerator::genFieldCtors() {} 553 554 bool TypeFuncGenerator::shouldAutogen() const { return true; }; 555 556 void TypeFuncGenerator::genFuncBody( FunctionDecl * dcl ) { 557 FunctionType * ftype = dcl->type; 558 assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() ); 559 DeclarationWithType * dst = ftype->parameters.front(); 560 DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr; 561 // generate appropriate calls to member ctor, assignment 562 UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) ); 563 expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) ); 564 if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) ); 565 dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) ); 566 }; 567 568 // xxx - should reach in and determine if base type is concurrent? 569 bool TypeFuncGenerator::isConcurrentType() const { return false; }; 570 571 // opaque types do not have field constructors 572 void TypeFuncGenerator::genFieldCtors() {}; 573 574 //============================================================================================= 575 // Visitor definitions 576 //============================================================================================= 571 577 AutogenerateRoutines::AutogenerateRoutines() { 572 578 // the order here determines the order that these functions are generated. 573 579 // assignment should come last since it uses copy constructor in return. 574 data.push_back( FuncData( "?{}", genDefaultType, constructable ) ); 575 data.push_back( FuncData( "?{}", genCopyType, copyable ) ); 576 data.push_back( FuncData( "^?{}", genDefaultType, destructable ) ); 577 data.push_back( FuncData( "?=?", genAssignType, assignable ) ); 578 } 579 580 void AutogenerateRoutines::visit( EnumDecl *enumDecl ) { 581 if ( ! enumDecl->get_members().empty() ) { 582 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() ); 583 // enumInst->set_baseEnum( enumDecl ); 584 makeEnumFunctions( enumInst, functionNesting, declsToAddAfter ); 585 } 586 } 587 588 void AutogenerateRoutines::visit( StructDecl *structDecl ) { 589 if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) { 590 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 591 for ( TypeDecl * typeDecl : structDecl->get_parameters() ) { 592 // need to visit assertions so that they are added to the appropriate maps 593 acceptAll( typeDecl->get_assertions(), *this ); 594 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 595 } 580 data.emplace_back( "?{}", genDefaultType ); 581 data.emplace_back( "?{}", genCopyType ); 582 data.emplace_back( "^?{}", genDefaultType ); 583 data.emplace_back( "?=?", genAssignType ); 584 } 585 586 void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) { 587 // must visit children (enum constants) to add them to the indexer 588 if ( enumDecl->has_body() ) { 589 EnumInstType enumInst( Type::Qualifiers(), enumDecl->get_name() ); 590 enumInst.set_baseEnum( enumDecl ); 591 EnumFuncGenerator gen( &enumInst, data, functionNesting, indexer ); 592 generateFunctions( gen, declsToAddAfter ); 593 } 594 } 595 596 void AutogenerateRoutines::previsit( StructDecl * structDecl ) { 597 visit_children = false; 598 if ( structDecl->has_body() ) { 599 StructInstType structInst( Type::Qualifiers(), structDecl->name ); 596 600 structInst.set_baseStruct( structDecl ); 597 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data ); 598 structsDone.insert( structDecl->get_name() ); 601 for ( TypeDecl * typeDecl : structDecl->parameters ) { 602 structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) ); 603 } 604 StructFuncGenerator gen( structDecl, &structInst, data, functionNesting, indexer ); 605 generateFunctions( gen, declsToAddAfter ); 599 606 } // if 600 607 } 601 608 602 void AutogenerateRoutines::visit( UnionDecl *unionDecl ) { 603 if ( ! unionDecl->get_members().empty() ) { 609 void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) { 610 visit_children = false; 611 if ( unionDecl->has_body() ) { 604 612 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 605 613 unionInst.set_baseUnion( unionDecl ); … … 607 615 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 608 616 } 609 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter ); 617 UnionFuncGenerator gen( unionDecl, &unionInst, data, functionNesting, indexer ); 618 generateFunctions( gen, declsToAddAfter ); 610 619 } // if 611 620 } 612 621 613 Type * declToTypeDeclBase( Declaration * decl ) {614 if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {615 return td->base;616 }617 return nullptr;618 }619 620 622 // generate ctor/dtors/assign for typedecls, e.g., otype T = int *; 621 void AutogenerateRoutines::visit( TypeDecl *typeDecl ) { 623 void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) { 624 visit_children = false; 622 625 if ( ! typeDecl->base ) return; 623 626 624 // generate each of the functions based on the supplied FuncData objects625 std::list< FunctionDecl * > newFuncs;626 std::list< Declaration * > tds { typeDecl };627 std::list< TypeDecl * > typeParams;628 627 TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl ); 629 auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, typeParams, back_inserter( newFuncs ) ); 630 for ( const FuncData & d : data ) { 631 generator.gen( d, false ); 632 } 633 634 if ( functionNesting == 0 ) { 635 // forward declare if top-level struct, so that 636 // type is complete as soon as its body ends 637 // Note: this is necessary if we want structs which contain 638 // generic (otype) structs as members. 639 for ( FunctionDecl * dcl : newFuncs ) { 640 addForwardDecl( dcl, declsToAddAfter ); 641 } 642 } 643 644 for ( FunctionDecl * dcl : newFuncs ) { 645 FunctionType * ftype = dcl->type; 646 assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() ); 647 DeclarationWithType * dst = ftype->parameters.front(); 648 DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr; 649 // generate appropriate calls to member ctor, assignment 650 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 651 UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) ); 652 expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) ); 653 if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) ); 654 dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) ); 655 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 656 // assignment needs to return a value 657 FunctionType * assignType = dcl->type; 658 assert( assignType->parameters.size() == 2 ); 659 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() ); 660 dcl->statements->kids.push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 661 } 662 declsToAddAfter.push_back( dcl ); 663 } 664 } 665 666 void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) { 667 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) { 668 statements.insert( i, new DeclStmt( noLabels, *decl ) ); 669 } // for 670 declsToAdd.clear(); 671 } 672 673 void AutogenerateRoutines::visit( FunctionType *) { 628 TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer ); 629 generateFunctions( gen, declsToAddAfter ); 630 } 631 632 void AutogenerateRoutines::previsit( FunctionType *) { 674 633 // ensure that we don't add assignment ops for types defined as part of the function 675 } 676 677 void AutogenerateRoutines::visit( PointerType *) { 634 visit_children = false; 635 } 636 637 void AutogenerateRoutines::previsit( PointerType *) { 678 638 // ensure that we don't add assignment ops for types defined as part of the pointer 679 } 680 681 void AutogenerateRoutines::visit( TraitDecl *) { 639 visit_children = false; 640 } 641 642 void AutogenerateRoutines::previsit( TraitDecl * ) { 682 643 // ensure that we don't add assignment ops for types defined as part of the trait 683 } 684 685 template< typename StmtClass > 686 inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) { 687 std::set< std::string > oldStructs = structsDone; 688 addVisit( stmt, *this ); 689 structsDone = oldStructs; 690 } 691 692 void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) { 644 visit_children = false; 645 } 646 647 void AutogenerateRoutines::previsit( FunctionDecl * functionDecl ) { 648 visit_children = false; 693 649 // record the existence of this function as appropriate 694 insert( functionDecl, constructable, InitTweak::isDefaultConstructor ); 695 insert( functionDecl, assignable, InitTweak::isAssignment ); 696 insert( functionDecl, copyable, InitTweak::isCopyConstructor ); 697 insert( functionDecl, destructable, InitTweak::isDestructor ); 698 699 maybeAccept( functionDecl->get_functionType(), *this ); 650 managedTypes.handleDWT( functionDecl ); 651 652 maybeAccept( functionDecl->type, *visitor ); 700 653 functionNesting += 1; 701 maybeAccept( functionDecl-> get_statements(), *this);654 maybeAccept( functionDecl->statements, *visitor ); 702 655 functionNesting -= 1; 703 656 } 704 657 705 void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) { 706 constructable.beginScope(); 707 assignable.beginScope(); 708 copyable.beginScope(); 709 destructable.beginScope(); 710 visitStatement( compoundStmt ); 711 constructable.endScope(); 712 assignable.endScope(); 713 copyable.endScope(); 714 destructable.endScope(); 715 } 716 717 void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) { 718 visitStatement( switchStmt ); 658 void AutogenerateRoutines::previsit( CompoundStmt * ) { 659 GuardScope( managedTypes ); 660 GuardScope( structsDone ); 719 661 } 720 662 … … 734 676 } 735 677 736 Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) { 737 tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) ); 678 void AutogenTupleRoutines::postvisit( TupleType * tupleType ) { 738 679 std::string mangleName = SymTab::Mangler::mangleType( tupleType ); 739 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;680 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return; 740 681 seenTuples.insert( mangleName ); 741 682 … … 755 696 if ( TypeInstType * ty = dynamic_cast< TypeInstType * >( t ) ) { 756 697 if ( ! done.count( ty->get_baseType() ) ) { 757 TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), Type::StorageClasses(), nullptr, TypeDecl:: Any);698 TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), Type::StorageClasses(), nullptr, TypeDecl::Dtype, true ); 758 699 TypeInstType * inst = new TypeInstType( Type::Qualifiers(), newDecl->get_name(), newDecl ); 759 700 newDecl->get_assertions().push_back( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, genAssignType( inst ), nullptr, … … 785 726 makeTupleFunctionBody( dtorDecl ); 786 727 787 addDeclaration( ctorDecl ); 788 addDeclaration( copyCtorDecl ); 789 addDeclaration( dtorDecl ); 790 addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return 791 792 return tupleType; 793 } 794 795 DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) { 796 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) ); 728 declsToAddBefore.push_back( ctorDecl ); 729 declsToAddBefore.push_back( copyCtorDecl ); 730 declsToAddBefore.push_back( dtorDecl ); 731 declsToAddBefore.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 732 } 733 734 void AutogenTupleRoutines::previsit( FunctionDecl *functionDecl ) { 735 visit_children = false; 736 maybeAccept( functionDecl->type, *visitor ); 797 737 functionNesting += 1; 798 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ));738 maybeAccept( functionDecl->statements, *visitor ); 799 739 functionNesting -= 1; 800 return functionDecl; 801 } 802 803 CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) { 804 seenTuples.beginScope(); 805 compoundStmt = strict_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) ); 806 seenTuples.endScope(); 807 return compoundStmt; 740 } 741 742 void AutogenTupleRoutines::previsit( CompoundStmt * ) { 743 GuardScope( seenTuples ); 808 744 } 809 745 } // SymTab -
src/SymTab/Autogen.h
r78315272 r3f7e12cb 19 19 #include <string> // for string 20 20 21 #include "CodeGen/OperatorTable.h" 21 22 #include "Common/UniqueName.h" // for UniqueName 22 23 #include "InitTweak/InitTweak.h" // for InitExpander … … 44 45 extern FunctionDecl * dereferenceOperator; 45 46 46 // temporary47 // generate the type of an assignment function for paramType 47 48 FunctionType * genAssignType( Type * paramType ); 49 50 // generate the type of a default constructor or destructor for paramType 51 FunctionType * genDefaultType( Type * paramType ); 52 53 // generate the type of a copy constructor for paramType 54 FunctionType * genCopyType( Type * paramType ); 48 55 49 56 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. … … 54 61 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one 55 62 template< typename OutputIterator > 56 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 63 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, bool addCast = false ) { 64 bool isReferenceCtorDtor = false; 65 if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { 66 // reference constructors are essentially application of the rebind operator. 67 // apply & to both arguments, do not need a cast 68 fname = "?=?"; 69 dstParam = new AddressExpr( dstParam ); 70 addCast = false; 71 isReferenceCtorDtor = true; 72 } 73 57 74 // want to be able to generate assignment, ctor, and dtor generically, 58 75 // so fname is either ?=?, ?{}, or ^?{} 59 UntypedExpr * fExpr = new UntypedExpr( new NameExpr( fname ) );76 UntypedExpr * fExpr = new UntypedExpr( new NameExpr( fname ) ); 60 77 61 78 if ( addCast ) { … … 72 89 dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) ); 73 90 } 74 fExpr-> get_args().push_back( dstParam );91 fExpr->args.push_back( dstParam ); 75 92 76 93 Statement * listInit = srcParam.buildListInit( fExpr ); 77 94 78 std::list< Expression * > args = *++srcParam; 79 fExpr->get_args().splice( fExpr->get_args().end(), args ); 95 // fetch next set of arguments 96 ++srcParam; 97 98 // return if adding reference fails - will happen on default constructor and destructor 99 if ( isReferenceCtorDtor && ! srcParam.addReference() ) { 100 delete fExpr; 101 return listInit; 102 } 103 104 std::list< Expression * > args = *srcParam; 105 fExpr->args.splice( fExpr->args.end(), args ); 80 106 81 107 *out++ = new ExprStmt( noLabels, fExpr ); … … 99 125 // generate: for ( int i = 0; i < N; ++i ) 100 126 begin = new ConstantExpr( Constant::from_int( 0 ) ); 101 end = array-> get_dimension()->clone();127 end = array->dimension->clone(); 102 128 cmp = new NameExpr( "?<?" ); 103 129 update = new NameExpr( "++?" ); … … 105 131 // generate: for ( int i = N-1; i >= 0; --i ) 106 132 begin = new UntypedExpr( new NameExpr( "?-?" ) ); 107 ((UntypedExpr*)begin)-> get_args().push_back( array->get_dimension()->clone() );108 ((UntypedExpr*)begin)-> get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );133 ((UntypedExpr*)begin)->args.push_back( array->dimension->clone() ); 134 ((UntypedExpr*)begin)->args.push_back( new ConstantExpr( Constant::from_int( 1 ) ) ); 109 135 end = new ConstantExpr( Constant::from_int( 0 ) ); 110 136 cmp = new NameExpr( "?>=?" ); … … 115 141 116 142 UntypedExpr *cond = new UntypedExpr( cmp ); 117 cond-> get_args().push_back( new VariableExpr( index ) );118 cond-> get_args().push_back( end );143 cond->args.push_back( new VariableExpr( index ) ); 144 cond->args.push_back( end ); 119 145 120 146 UntypedExpr *inc = new UntypedExpr( update ); 121 inc-> get_args().push_back( new VariableExpr( index ) );147 inc->args.push_back( new VariableExpr( index ) ); 122 148 123 149 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 124 dstIndex-> get_args().push_back( dstParam );125 dstIndex-> get_args().push_back( new VariableExpr( index ) );150 dstIndex->args.push_back( dstParam ); 151 dstIndex->args.push_back( new VariableExpr( index ) ); 126 152 dstParam = dstIndex; 127 153 128 154 // srcParam must keep track of the array indices to build the 129 155 // source parameter and/or array list initializer 130 srcParam.addArrayIndex( new VariableExpr( index ), array-> get_dimension()->clone() );156 srcParam.addArrayIndex( new VariableExpr( index ), array->dimension->clone() ); 131 157 132 158 // for stmt's body, eventually containing call 133 159 CompoundStmt * body = new CompoundStmt( noLabels ); 134 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body-> get_kids() ), array->get_base(), addCast, forward );160 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward ); 135 161 136 162 // block containing for stmt and index variable 137 163 std::list<Statement *> initList; 138 164 CompoundStmt * block = new CompoundStmt( noLabels ); 139 block-> get_kids().push_back( new DeclStmt( noLabels, index ) );165 block->push_back( new DeclStmt( noLabels, index ) ); 140 166 if ( listInit ) block->get_kids().push_back( listInit ); 141 block-> get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );167 block->push_back( new ForStmt( noLabels, initList, cond, inc, body ) ); 142 168 143 169 *out++ = block; … … 145 171 146 172 template< typename OutputIterator > 147 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {173 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) { 148 174 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 149 175 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); … … 159 185 /// ImplicitCtorDtorStmt node. 160 186 template< typename OutputIterator > 161 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {187 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 162 188 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 163 189 assert( obj ); … … 167 193 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ); 168 194 std::list< Statement * > stmts; 169 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj-> get_type(), addCast, forward );195 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward ); 170 196 171 197 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call -
src/SymTab/FixFunction.cc
r78315272 r3f7e12cb 26 26 FixFunction::FixFunction() : isVoid( false ) {} 27 27 28 DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) { 29 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() ); 30 functionDecl->get_attributes().clear(); 31 // can't delete function type because it may contain assertions, but can't transfer ownership without a clone since set_type checks for nullptr 32 functionDecl->set_type( functionDecl->get_type()->clone() ); 28 29 DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) { 30 // can't delete function type because it may contain assertions, so transfer ownership to new object 31 ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes ); 32 functionDecl->attributes.clear(); 33 functionDecl->type = nullptr; 33 34 delete functionDecl; 34 35 return pointer; 35 36 } 36 37 37 Type * FixFunction::mutate(VoidType *voidType) { 38 isVoid = true; 39 return voidType; 40 } 41 42 Type * FixFunction::mutate(BasicType *basicType) { 43 return basicType; 44 } 45 46 Type * FixFunction::mutate(PointerType *pointerType) { 47 return pointerType; 48 } 49 50 Type * FixFunction::mutate(ArrayType *arrayType) { 38 Type * FixFunction::postmutate(ArrayType *arrayType) { 51 39 // need to recursively mutate the base type in order for multi-dimensional arrays to work. 52 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() ); 40 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic ); 41 arrayType->base = nullptr; 42 arrayType->dimension = nullptr; 53 43 delete arrayType; 54 44 return pointerType; 55 45 } 56 46 57 Type * FixFunction::mutate(StructInstType *aggregateUseType) {58 return aggregateUseType;47 void FixFunction::premutate(VoidType *) { 48 isVoid = true; 59 49 } 60 50 61 Type * FixFunction::mutate(UnionInstType *aggregateUseType) { 62 return aggregateUseType; 63 } 64 65 Type * FixFunction::mutate(EnumInstType *aggregateUseType) { 66 return aggregateUseType; 67 } 68 69 Type * FixFunction::mutate(TraitInstType *aggregateUseType) { 70 return aggregateUseType; 71 } 72 73 Type * FixFunction::mutate(TypeInstType *aggregateUseType) { 74 return aggregateUseType; 75 } 76 77 Type * FixFunction::mutate(TupleType *tupleType) { 78 return tupleType; 79 } 80 81 Type * FixFunction::mutate(VarArgsType *varArgsType) { 82 return varArgsType; 83 } 84 85 Type * FixFunction::mutate(ZeroType *zeroType) { 86 return zeroType; 87 } 88 89 Type * FixFunction::mutate(OneType *oneType) { 90 return oneType; 91 } 51 void FixFunction::premutate(FunctionDecl *) { visit_children = false; } 52 void FixFunction::premutate(ArrayType *) { visit_children = false; } 53 void FixFunction::premutate(BasicType *) { visit_children = false; } 54 void FixFunction::premutate(PointerType *) { visit_children = false; } 55 void FixFunction::premutate(StructInstType *) { visit_children = false; } 56 void FixFunction::premutate(UnionInstType *) { visit_children = false; } 57 void FixFunction::premutate(EnumInstType *) { visit_children = false; } 58 void FixFunction::premutate(TraitInstType *) { visit_children = false; } 59 void FixFunction::premutate(TypeInstType *) { visit_children = false; } 60 void FixFunction::premutate(TupleType *) { visit_children = false; } 61 void FixFunction::premutate(VarArgsType *) { visit_children = false; } 62 void FixFunction::premutate(ZeroType *) { visit_children = false; } 63 void FixFunction::premutate(OneType *) { visit_children = false; } 92 64 } // namespace SymTab 93 65 -
src/SymTab/FixFunction.h
r78315272 r3f7e12cb 16 16 #pragma once 17 17 18 #include " SynTree/Mutator.h" // for Mutator19 #include "SynTree/SynTree.h" // for Types18 #include "Common/PassVisitor.h" // for PassVisitor 19 #include "SynTree/SynTree.h" // for Types 20 20 21 21 namespace SymTab { 22 22 /// Replaces function and array types by equivalent pointer types. 23 class FixFunction : public Mutator{23 class FixFunction : public WithShortCircuiting { 24 24 typedef Mutator Parent; 25 25 public: 26 26 FixFunction(); 27 27 28 bool get_isVoid() const { return isVoid; } 29 void set_isVoid( bool newValue ) { isVoid = newValue; } 30 private: 31 virtual DeclarationWithType* mutate(FunctionDecl *functionDecl); 28 void premutate(FunctionDecl *functionDecl); 29 DeclarationWithType* postmutate(FunctionDecl *functionDecl); 32 30 33 virtual Type* mutate(VoidType *voidType); 34 virtual Type* mutate(BasicType *basicType); 35 virtual Type* mutate(PointerType *pointerType); 36 virtual Type* mutate(ArrayType *arrayType); 37 virtual Type* mutate(StructInstType *aggregateUseType); 38 virtual Type* mutate(UnionInstType *aggregateUseType); 39 virtual Type* mutate(EnumInstType *aggregateUseType); 40 virtual Type* mutate(TraitInstType *aggregateUseType); 41 virtual Type* mutate(TypeInstType *aggregateUseType); 42 virtual Type* mutate(TupleType *tupleType); 43 virtual Type* mutate(VarArgsType *varArgsType); 44 virtual Type* mutate(ZeroType *zeroType); 45 virtual Type* mutate(OneType *oneType); 31 Type * postmutate(ArrayType * arrayType); 32 33 void premutate(ArrayType * arrayType); 34 void premutate(VoidType * voidType); 35 void premutate(BasicType * basicType); 36 void premutate(PointerType * pointerType); 37 void premutate(StructInstType * aggregateUseType); 38 void premutate(UnionInstType * aggregateUseType); 39 void premutate(EnumInstType * aggregateUseType); 40 void premutate(TraitInstType * aggregateUseType); 41 void premutate(TypeInstType * aggregateUseType); 42 void premutate(TupleType * tupleType); 43 void premutate(VarArgsType * varArgsType); 44 void premutate(ZeroType * zeroType); 45 void premutate(OneType * oneType); 46 46 47 47 bool isVoid; -
src/SymTab/Indexer.cc
r78315272 r3f7e12cb 40 40 41 41 namespace SymTab { 42 struct NewScope {43 NewScope( SymTab::Indexer & indexer ) : indexer( indexer ) { indexer.enterScope(); }44 ~NewScope() { indexer.leaveScope(); }45 SymTab::Indexer & indexer;46 };47 48 template< typename TreeType, typename VisitorType >49 inline void acceptNewScope( TreeType *tree, VisitorType &visitor ) {50 visitor.enterScope();51 maybeAccept( tree, visitor );52 visitor.leaveScope();53 }54 55 42 typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable; 56 43 typedef std::unordered_map< std::string, MangleTable > IdTable; … … 198 185 } 199 186 200 Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug) {}201 202 Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug) {}203 204 Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug) {187 Indexer::Indexer() : tables( 0 ), scope( 0 ) {} 188 189 Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {} 190 191 Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) { 205 192 that.tables = 0; 206 193 } … … 420 407 makeWritable(); 421 408 422 const std::string &name = decl-> get_name();409 const std::string &name = decl->name; 423 410 std::string mangleName; 424 if ( LinkageSpec::isOverridable( decl-> get_linkage()) ) {411 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 425 412 // mangle the name without including the appropriate suffix, so overridable routines are placed into the 426 413 // same "bucket" as their user defined versions. … … 431 418 432 419 // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage 433 if ( ! LinkageSpec::isMangled( decl-> get_linkage()) ) {420 if ( ! LinkageSpec::isMangled( decl->linkage ) ) { 434 421 // NOTE this is broken in Richard's original code in such a way that it never triggers (it 435 422 // doesn't check decls that have the same manglename, and all C-linkage decls are defined to … … 584 571 585 572 if ( doDebug ) { 586 std::c out<< "--- Entering scope " << scope << std::endl;573 std::cerr << "--- Entering scope " << scope << std::endl; 587 574 } 588 575 } 589 576 590 577 void Indexer::leaveScope() { 591 using std::c out;578 using std::cerr; 592 579 593 580 assert( scope > 0 && "cannot leave initial scope" ); 581 if ( doDebug ) { 582 cerr << "--- Leaving scope " << scope << " containing" << std::endl; 583 } 594 584 --scope; 595 585 596 586 while ( tables && tables->scope > scope ) { 597 587 if ( doDebug ) { 598 cout << "--- Leaving scope " << tables->scope << " containing" << std::endl; 599 dump( tables->idTable, cout ); 600 dump( tables->typeTable, cout ); 601 dump( tables->structTable, cout ); 602 dump( tables->enumTable, cout ); 603 dump( tables->unionTable, cout ); 604 dump( tables->traitTable, cout ); 588 dump( tables->idTable, cerr ); 589 dump( tables->typeTable, cerr ); 590 dump( tables->structTable, cerr ); 591 dump( tables->enumTable, cerr ); 592 dump( tables->unionTable, cerr ); 593 dump( tables->traitTable, cerr ); 605 594 } 606 595 -
src/SymTab/Indexer.h
r78315272 r3f7e12cb 26 26 class Indexer { 27 27 public: 28 explicit Indexer( bool useDebug = false);28 explicit Indexer(); 29 29 30 30 Indexer( const Indexer &that ); … … 76 76 void addTrait( TraitDecl *decl ); 77 77 78 bool doDebug = false; ///< Display debugging trace? 78 79 private: 79 80 struct Impl; … … 81 82 Impl *tables; ///< Copy-on-write instance of table data structure 82 83 unsigned long scope; ///< Scope index of this pointer 83 bool doDebug; ///< Display debugging trace?84 84 85 85 /// Takes a new ref to a table (returns null if null) -
src/SymTab/Mangler.cc
r78315272 r3f7e12cb 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:40:29 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Jun 28 15:31:00201713 // Update Count : 2 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 25 15:49:26 2017 13 // Update Count : 23 14 14 // 15 15 #include "Mangler.h" … … 31 31 32 32 namespace SymTab { 33 std::string Mangler::mangleType( Type * ty ) {34 Mangler mangler( false, true );33 std::string Mangler::mangleType( Type * ty ) { 34 Mangler mangler( false, true, true ); 35 35 maybeAccept( ty, mangler ); 36 36 return mangler.get_mangleName(); 37 37 } 38 38 39 Mangler::Mangler( bool mangleOverridable, bool typeMode ) 40 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ) {} 39 std::string Mangler::mangleConcrete( Type* ty ) { 40 Mangler mangler( false, false, false ); 41 maybeAccept( ty, mangler ); 42 return mangler.get_mangleName(); 43 } 44 45 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 46 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {} 41 47 42 48 Mangler::Mangler( const Mangler &rhs ) : mangleName() { … … 48 54 } 49 55 50 void Mangler::mangleDecl( DeclarationWithType * declaration ) {56 void Mangler::mangleDecl( DeclarationWithType * declaration ) { 51 57 bool wasTopLevel = isTopLevel; 52 58 if ( isTopLevel ) { … … 79 85 } 80 86 81 void Mangler::visit( ObjectDecl * declaration ) {87 void Mangler::visit( ObjectDecl * declaration ) { 82 88 mangleDecl( declaration ); 83 89 } 84 90 85 void Mangler::visit( FunctionDecl * declaration ) {91 void Mangler::visit( FunctionDecl * declaration ) { 86 92 mangleDecl( declaration ); 87 93 } 88 94 89 void Mangler::visit( VoidType * voidType ) {95 void Mangler::visit( VoidType * voidType ) { 90 96 printQualifiers( voidType ); 91 97 mangleName << "v"; 92 98 } 93 99 94 void Mangler::visit( BasicType * basicType ) {100 void Mangler::visit( BasicType * basicType ) { 95 101 static const char *btLetter[] = { 96 102 "b", // Bool … … 115 121 "Id", // DoubleImaginary 116 122 "Ir", // LongDoubleImaginary 123 "w", // SignedInt128 124 "Uw", // UnsignedInt128 117 125 }; 118 126 … … 121 129 } 122 130 123 void Mangler::visit( PointerType * pointerType ) {131 void Mangler::visit( PointerType * pointerType ) { 124 132 printQualifiers( pointerType ); 125 133 mangleName << "P"; … … 127 135 } 128 136 129 void Mangler::visit( ArrayType * arrayType ) {137 void Mangler::visit( ArrayType * arrayType ) { 130 138 // TODO: encode dimension 131 139 printQualifiers( arrayType ); … … 134 142 } 135 143 136 void Mangler::visit( ReferenceType * refType ) {144 void Mangler::visit( ReferenceType * refType ) { 137 145 printQualifiers( refType ); 138 146 mangleName << "R"; … … 149 157 } 150 158 151 void Mangler::visit( FunctionType * functionType ) {159 void Mangler::visit( FunctionType * functionType ) { 152 160 printQualifiers( functionType ); 153 161 mangleName << "F"; … … 160 168 } 161 169 162 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {170 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) { 163 171 printQualifiers( refType ); 164 172 165 173 mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name(); 166 } 167 168 void Mangler::mangleGenericRef( ReferenceToType *refType, std::string prefix ) { 169 printQualifiers( refType ); 170 171 std::ostringstream oldName( mangleName.str() ); 172 mangleName.clear(); 173 174 mangleName << prefix << refType->get_name(); 175 176 std::list< Expression* >& params = refType->get_parameters(); 177 if ( ! params.empty() ) { 178 mangleName << "_"; 179 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) { 180 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 181 assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str()); 182 maybeAccept( paramType->get_type(), *this ); 174 175 if ( mangleGenericParams ) { 176 std::list< Expression* >& params = refType->get_parameters(); 177 if ( ! params.empty() ) { 178 mangleName << "_"; 179 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) { 180 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 181 assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str()); 182 maybeAccept( paramType->get_type(), *this ); 183 } 184 mangleName << "_"; 183 185 } 184 mangleName << "_";185 186 } 186 187 oldName << mangleName.str().length() << mangleName.str(); 188 mangleName.str( oldName.str() ); 189 } 190 191 void Mangler::visit( StructInstType *aggregateUseType ) { 192 if ( typeMode ) mangleGenericRef( aggregateUseType, "s" ); 193 else mangleRef( aggregateUseType, "s" ); 194 } 195 196 void Mangler::visit( UnionInstType *aggregateUseType ) { 197 if ( typeMode ) mangleGenericRef( aggregateUseType, "u" ); 198 else mangleRef( aggregateUseType, "u" ); 199 } 200 201 void Mangler::visit( EnumInstType *aggregateUseType ) { 187 } 188 189 void Mangler::visit( StructInstType * aggregateUseType ) { 190 mangleRef( aggregateUseType, "s" ); 191 } 192 193 void Mangler::visit( UnionInstType * aggregateUseType ) { 194 mangleRef( aggregateUseType, "u" ); 195 } 196 197 void Mangler::visit( EnumInstType * aggregateUseType ) { 202 198 mangleRef( aggregateUseType, "e" ); 203 199 } 204 200 205 void Mangler::visit( TypeInstType * typeInst ) {201 void Mangler::visit( TypeInstType * typeInst ) { 206 202 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 207 203 if ( varNum == varNums.end() ) { … … 212 208 numStream << varNum->second.first; 213 209 switch ( (TypeDecl::Kind )varNum->second.second ) { 214 case TypeDecl::Any:215 mangleName << "t";216 break;217 210 case TypeDecl::Dtype: 218 211 mangleName << "d"; … … 231 224 } 232 225 233 void Mangler::visit( TupleType * tupleType ) {226 void Mangler::visit( TupleType * tupleType ) { 234 227 printQualifiers( tupleType ); 235 228 mangleName << "T"; 236 acceptAll( tupleType-> get_types(), *this );229 acceptAll( tupleType->types, *this ); 237 230 mangleName << "_"; 238 231 } 239 232 240 void Mangler::visit( VarArgsType * varArgsType ) {233 void Mangler::visit( VarArgsType * varArgsType ) { 241 234 printQualifiers( varArgsType ); 242 235 mangleName << "VARGS"; 243 236 } 244 237 245 void Mangler::visit( __attribute__((unused)) ZeroType *zeroType) {238 void Mangler::visit( ZeroType * ) { 246 239 mangleName << "Z"; 247 240 } 248 241 249 void Mangler::visit( __attribute__((unused)) OneType *oneType) {242 void Mangler::visit( OneType * ) { 250 243 mangleName << "O"; 251 244 } 252 245 253 void Mangler::visit( TypeDecl * decl ) {246 void Mangler::visit( TypeDecl * decl ) { 254 247 static const char *typePrefix[] = { "BT", "BD", "BF" }; 255 mangleName << typePrefix[ decl->get_kind() ] << ( decl-> get_name().length() + 1 ) << decl->get_name();248 mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name; 256 249 } 257 250 … … 262 255 } 263 256 264 void Mangler::printQualifiers( Type * type ) {257 void Mangler::printQualifiers( Type * type ) { 265 258 // skip if not including qualifiers 266 259 if ( typeMode ) return; … … 270 263 int tcount = 0, dcount = 0, fcount = 0, vcount = 0; 271 264 mangleName << "A"; 272 for ( Type::ForallList::iterator i = type-> get_forall().begin(); i != type->get_forall().end(); ++i ) {265 for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) { 273 266 switch ( (*i)->get_kind() ) { 274 case TypeDecl::Any:275 tcount++;276 break;277 267 case TypeDecl::Dtype: 278 268 dcount++; … … 287 277 assert( false ); 288 278 } // switch 289 varNums[ (*i )->get_name() ] = std::pair< int, int >( nextVarNum++, (int )(*i)->get_kind() );290 for ( std::list< DeclarationWithType* >::iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {291 Mangler sub_mangler( mangleOverridable, typeMode );279 varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() ); 280 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 281 Mangler sub_mangler( mangleOverridable, typeMode, mangleGenericParams ); 292 282 sub_mangler.nextVarNum = nextVarNum; 293 283 sub_mangler.isTopLevel = false; … … 307 297 mangleName << "V"; 308 298 } // if 299 if ( type->get_mutex() ) { 300 mangleName << "M"; 301 } // if 309 302 // Removed due to restrict not affecting function compatibility in GCC 310 303 // if ( type->get_isRestrict() ) { … … 312 305 // } // if 313 306 if ( type->get_lvalue() ) { 307 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues 314 308 mangleName << "L"; 315 } // if309 } 316 310 if ( type->get_atomic() ) { 317 311 mangleName << "A"; -
src/SymTab/Mangler.h
r78315272 r3f7e12cb 30 30 /// Mangle syntax tree object; primary interface to clients 31 31 template< typename SynTreeClass > 32 static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true, bool typeMode = false );32 static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true ); 33 33 /// Mangle a type name; secondary interface 34 34 static std::string mangleType( Type* ty ); 35 /// Mangle ignoring generic type parameters 36 static std::string mangleConcrete( Type* ty ); 37 35 38 36 39 virtual void visit( ObjectDecl *declaration ); … … 62 65 bool mangleOverridable; ///< Specially mangle overridable built-in methods 63 66 bool typeMode; ///< Produce a unique mangled name for a type 67 bool mangleGenericParams; ///< Include generic parameters in name mangling if true 64 68 65 Mangler( bool mangleOverridable, bool typeMode );69 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); 66 70 Mangler( const Mangler & ); 67 71 68 72 void mangleDecl( DeclarationWithType *declaration ); 69 73 void mangleRef( ReferenceToType *refType, std::string prefix ); 70 void mangleGenericRef( ReferenceToType *refType, std::string prefix );71 74 72 75 void printQualifiers( Type *type ); … … 74 77 75 78 template< typename SynTreeClass > 76 std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable, bool typeMode ) {77 Mangler mangler( mangleOverridable, typeMode );79 std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { 80 Mangler mangler( mangleOverridable, typeMode, mangleGenericParams ); 78 81 maybeAccept( decl, mangler ); 79 82 return mangler.get_mangleName(); -
src/SymTab/Validate.cc
r78315272 r3f7e12cb 56 56 #include "FixFunction.h" // for FixFunction 57 57 #include "Indexer.h" // for Indexer 58 #include "InitTweak/GenInit.h" // for fixReturnStatements 58 59 #include "InitTweak/InitTweak.h" // for isCtorDtorAssign 59 60 #include "Parser/LinkageSpec.h" // for C … … 150 151 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 151 152 struct ForallPointerDecay final { 152 void previsit( ObjectDecl *object ); 153 void previsit( FunctionDecl *func ); 153 void previsit( ObjectDecl * object ); 154 void previsit( FunctionDecl * func ); 155 void previsit( StructDecl * aggrDecl ); 156 void previsit( UnionDecl * aggrDecl ); 154 157 }; 155 158 … … 265 268 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order 266 269 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 270 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling 267 271 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 268 272 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes 269 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist270 273 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 274 ReturnChecker::checkFunctionReturns( translationUnit ); 275 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen 271 276 Concurrency::applyKeywords( translationUnit ); 277 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution 272 278 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay 273 279 Concurrency::implementMutexFuncs( translationUnit ); 274 280 Concurrency::implementThreadStarter( translationUnit ); 275 ReturnChecker::checkFunctionReturns( translationUnit );276 281 mutateAll( translationUnit, compoundliteral ); 277 acceptAll( translationUnit, fpd );278 282 ArrayLength::computeLength( translationUnit ); 279 acceptAll( translationUnit, finder ); 283 acceptAll( translationUnit, finder ); // xxx - remove this pass soon 280 284 mutateAll( translationUnit, labelAddrFixer ); 281 285 } … … 368 372 DWTIterator begin( dwts.begin() ), end( dwts.end() ); 369 373 if ( begin == end ) return; 370 FixFunctionfixer;374 PassVisitor<FixFunction> fixer; 371 375 DWTIterator i = begin; 372 376 *i = (*i)->acceptMutator( fixer ); 373 if ( fixer. get_isVoid()) {377 if ( fixer.pass.isVoid ) { 374 378 DWTIterator j = i; 375 379 ++i; … … 382 386 ++i; 383 387 for ( ; i != end; ++i ) { 384 FixFunctionfixer;388 PassVisitor<FixFunction> fixer; 385 389 *i = (*i)->acceptMutator( fixer ); 386 if ( fixer. get_isVoid()) {390 if ( fixer.pass.isVoid ) { 387 391 throw SemanticError( "invalid type void in function type ", func ); 388 392 } // if … … 579 583 580 584 /// Fix up assertions - flattens assertion lists, removing all trait instances 581 void forallFixer( Type * func) {582 for ( TypeDecl * type : f unc->get_forall()) {585 void forallFixer( std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) { 586 for ( TypeDecl * type : forall ) { 583 587 std::list< DeclarationWithType * > asserts; 584 588 asserts.splice( asserts.end(), type->assertions ); … … 596 600 // apply FixFunction to every assertion to check for invalid void type 597 601 for ( DeclarationWithType *& assertion : type->assertions ) { 598 FixFunctionfixer;602 PassVisitor<FixFunction> fixer; 599 603 assertion = assertion->acceptMutator( fixer ); 600 if ( fixer. get_isVoid()) {601 throw SemanticError( "invalid type void in assertion of function ", func);604 if ( fixer.pass.isVoid ) { 605 throw SemanticError( "invalid type void in assertion of function ", node ); 602 606 } // if 603 607 } // for … … 607 611 608 612 void ForallPointerDecay::previsit( ObjectDecl *object ) { 609 forallFixer( object-> get_type());610 if ( PointerType *pointer = dynamic_cast< PointerType * >( object-> get_type()) ) {611 forallFixer( pointer-> get_base());613 forallFixer( object->type->forall, object ); 614 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->type ) ) { 615 forallFixer( pointer->base->forall, object ); 612 616 } // if 613 617 object->fixUniqueId(); … … 615 619 616 620 void ForallPointerDecay::previsit( FunctionDecl *func ) { 617 forallFixer( func-> get_type());621 forallFixer( func->type->forall, func ); 618 622 func->fixUniqueId(); 623 } 624 625 void ForallPointerDecay::previsit( StructDecl * aggrDecl ) { 626 forallFixer( aggrDecl->parameters, aggrDecl ); 627 } 628 629 void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) { 630 forallFixer( aggrDecl->parameters, aggrDecl ); 619 631 } 620 632 … … 656 668 } 657 669 filter( translationUnit, isTypedef, true ); 658 659 670 } 660 671 … … 664 675 TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() ); 665 676 if ( def != typedefNames.end() ) { 666 Type *ret = def->second.first-> get_base()->clone();677 Type *ret = def->second.first->base->clone(); 667 678 ret->get_qualifiers() |= typeInst->get_qualifiers(); 668 679 // place instance parameters on the typedef'd type 669 if ( ! typeInst-> get_parameters().empty() ) {680 if ( ! typeInst->parameters.empty() ) { 670 681 ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret); 671 682 if ( ! rtt ) { 672 throw SemanticError(" cannot apply type parameters to base type of " + typeInst->get_name());683 throw SemanticError("Cannot apply type parameters to base type of " + typeInst->name); 673 684 } 674 685 rtt->get_parameters().clear(); 675 cloneAll( typeInst-> get_parameters(), rtt->get_parameters());676 mutateAll( rtt-> get_parameters(), *visitor ); // recursively fix typedefs on parameters686 cloneAll( typeInst->parameters, rtt->parameters ); 687 mutateAll( rtt->parameters, *visitor ); // recursively fix typedefs on parameters 677 688 } // if 678 689 delete typeInst; … … 680 691 } else { 681 692 TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() ); 682 assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst-> get_name().c_str() );693 assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() ); 683 694 typeInst->set_baseType( base->second ); 684 695 } // if 685 696 return typeInst; 697 } 698 699 struct VarLenChecker : WithShortCircuiting { 700 void previsit( FunctionType * ) { visit_children = false; } 701 void previsit( ArrayType * at ) { 702 isVarLen |= at->isVarLen; 703 } 704 bool isVarLen = false; 705 }; 706 707 bool isVariableLength( Type * t ) { 708 PassVisitor<VarLenChecker> varLenChecker; 709 maybeAccept( t, varLenChecker ); 710 return varLenChecker.pass.isVarLen; 686 711 } 687 712 … … 694 719 Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base(); 695 720 if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) { 696 throw SemanticError( "cannot redefine typedef: " + tyDecl->get_name() ); 721 throw SemanticError( "Cannot redefine typedef: " + tyDecl->name ); 722 } 723 // cannot redefine VLA typedefs 724 if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) { 725 throw SemanticError( "Cannot redefine typedef: " + tyDecl->name ); 697 726 } 698 727 } else {
Note:
See TracChangeset
for help on using the changeset viewer.