Changes in src/SymTab/Autogen.cc [1486116:906e24d]
- File:
-
- 1 edited
-
src/SymTab/Autogen.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
r1486116 r906e24d 24 24 #include "MakeLibCfa.h" 25 25 #include "Autogen.h" 26 #include "GenPoly/ScopedSet.h"27 #include "SymTab/Mangler.h"28 #include "GenPoly/DeclMutator.h"29 26 30 27 namespace SymTab { … … 32 29 33 30 class AutogenerateRoutines : public Visitor { 34 public:31 public: 35 32 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; } 36 37 typedef Visitor Parent;38 using Parent::visit;39 33 40 34 virtual void visit( EnumDecl *enumDecl ); … … 51 45 virtual void visit( SwitchStmt *switchStmt ); 52 46 53 private: 47 AutogenerateRoutines() : functionNesting( 0 ) {} 48 private: 54 49 template< typename StmtClass > void visitStatement( StmtClass *stmt ); 55 50 56 51 std::list< Declaration * > declsToAdd; 57 52 std::set< std::string > structsDone; 58 unsigned int functionNesting = 0; // current level of nested functions53 unsigned int functionNesting; // current level of nested functions 59 54 }; 60 55 61 /// generates routines for tuple types.62 /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit63 /// or anything we currently have that supports adding new declarations for visitors64 class AutogenTupleRoutines : public GenPoly::DeclMutator {65 public:66 typedef GenPoly::DeclMutator Parent;67 using Parent::mutate;68 69 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );70 71 virtual Type * mutate( TupleType *tupleType );72 73 virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );74 75 private:76 unsigned int functionNesting = 0; // current level of nested functions77 GenPoly::ScopedSet< std::string > seenTuples;78 };79 80 56 void autogenerateRoutines( std::list< Declaration * > &translationUnit ) { 81 AutogenerateRoutines generator; 82 acceptAndAdd( translationUnit, generator, false ); 83 84 // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc. 85 // AutogenTupleRoutines tupleGenerator; 86 // tupleGenerator.mutateDeclarationList( translationUnit ); 57 AutogenerateRoutines visitor; 58 acceptAndAdd( translationUnit, visitor, false ); 87 59 } 88 60 … … 91 63 } 92 64 93 /// inserts a forward declaration for functionDecl into declsToAdd 94 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { 95 FunctionDecl * decl = functionDecl->clone(); 96 delete decl->get_statements(); 97 decl->set_statements( NULL ); 98 declsToAdd.push_back( decl ); 99 decl->fixUniqueId(); 100 } 101 102 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 103 FunctionType * genDefaultType( Type * paramType ) { 104 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 105 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr ); 106 ftype->get_parameters().push_back( dstParam ); 107 108 return ftype; 109 } 110 111 /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T) 112 FunctionType * genCopyType( Type * paramType ) { 113 FunctionType *ftype = genDefaultType( paramType ); 114 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 115 ftype->get_parameters().push_back( srcParam ); 116 return ftype; 117 } 118 119 /// given type T, generate type of assignment, i.e. function type T (*) (T *, T) 120 FunctionType * genAssignType( Type * paramType ) { 121 FunctionType *ftype = genCopyType( paramType ); 122 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 123 ftype->get_returnVals().push_back( returnVal ); 124 return ftype; 125 } 126 127 /// true if the aggregate's layout is dynamic 128 template< typename AggrDecl > 129 bool hasDynamicLayout( AggrDecl * aggregateDecl ) { 130 for ( TypeDecl * param : aggregateDecl->get_parameters() ) { 131 if ( param->get_kind() == TypeDecl::Any ) return true; 132 } 133 return false; 134 } 135 136 /// generate a function decl from a name and type. Nesting depth determines whether 137 /// the declaration is static or not; optional paramter determines if declaration is intrinsic 138 FunctionDecl * genFunc( const std::string & fname, FunctionType * ftype, unsigned int functionNesting, bool isIntrinsic = false ) { 139 // Routines at global scope marked "static" to prevent multiple definitions in separate translation units 65 template< typename OutputIterator > 66 void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, OutputIterator out ) { 67 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 68 copy->get_args().push_back( new VariableExpr( dstParam ) ); 69 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 70 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); 71 72 *out++ = new ExprStmt( noLabels, copy ); 73 } 74 75 //E ?=?(E volatile*, int), 76 // ?=?(E _Atomic volatile*, int); 77 void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) { 78 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 79 80 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 ); 81 assignType->get_parameters().push_back( dstParam ); 82 83 // void ?{}(E *); void ^?{}(E *); 84 FunctionType * ctorType = assignType->clone(); 85 FunctionType * dtorType = assignType->clone(); 86 87 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 ); 88 assignType->get_parameters().push_back( srcParam ); 89 // void ?{}(E *, E); 90 FunctionType *copyCtorType = assignType->clone(); 91 92 // T ?=?(E *, E); 93 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 ); 94 assignType->get_returnVals().push_back( returnVal ); 95 96 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 97 // right now these cases work, but that might change. 98 99 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 140 100 // because each unit generates copies of the default routines for each aggregate. 141 DeclarationNode::StorageClass sc = functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static; 142 LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen; 143 FunctionDecl * decl = new FunctionDecl( fname, sc, spec, ftype, new CompoundStmt( noLabels ), true, false ); 144 decl->fixUniqueId(); 145 return decl; 146 } 147 148 /// generates a single enumeration assignment expression 149 ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) { 101 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment. 102 // Really they're something of a cross between instrinsic and autogen, so should 103 // probably make a new linkage type 104 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false ); 105 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false ); 106 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false ); 107 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false ); 108 assignDecl->fixUniqueId(); 109 ctorDecl->fixUniqueId(); 110 copyCtorDecl->fixUniqueId(); 111 dtorDecl->fixUniqueId(); 112 150 113 // enum copy construct and assignment is just C-style assignment. 151 114 // this looks like a bad recursive call, but code gen will turn it into 152 115 // a C-style assignment. 153 116 // This happens before function pointer type conversion, so need to do it manually here 154 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the155 // type of the function that this expression is being generated for (so that the correct156 // parameters) are using in the variable exprs157 assert( ftype->get_parameters().size() == 2 );158 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );159 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );160 161 117 VariableExpr * assignVarExpr = new VariableExpr( assignDecl ); 162 118 Type * assignVarExprType = assignVarExpr->get_result(); … … 166 122 assignExpr->get_args().push_back( new VariableExpr( dstParam ) ); 167 123 assignExpr->get_args().push_back( new VariableExpr( srcParam ) ); 168 return assignExpr;169 }170 171 // E ?=?(E volatile*, int),172 // ?=?(E _Atomic volatile*, int);173 void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {174 175 // T ?=?(E *, E);176 FunctionType *assignType = genAssignType( refType );177 178 // void ?{}(E *); void ^?{}(E *);179 FunctionType * ctorType = genDefaultType( refType->clone() );180 FunctionType * dtorType = genDefaultType( refType->clone() );181 182 // void ?{}(E *, E);183 FunctionType *copyCtorType = genCopyType( refType->clone() );184 185 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?186 // right now these cases work, but that might change.187 188 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.189 // Really they're something of a cross between instrinsic and autogen, so should190 // probably make a new linkage type191 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true );192 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true );193 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true );194 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true );195 124 196 125 // body is either return stmt or expr stmt 197 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) ); 198 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) ); 199 126 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) ); 127 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) ); 128 129 declsToAdd.push_back( assignDecl ); 200 130 declsToAdd.push_back( ctorDecl ); 201 131 declsToAdd.push_back( copyCtorDecl ); 202 132 declsToAdd.push_back( dtorDecl ); 203 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return 204 } 205 206 /// generates a single struct member operation (constructor call, destructor call, assignment call) 207 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) { 133 } 134 135 /// Clones a reference type, replacing any parameters it may have with a clone of the provided list 136 template< typename GenericInstType > 137 GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) { 138 GenericInstType *clone = refType->clone(); 139 clone->get_parameters().clear(); 140 cloneAll( params, clone->get_parameters() ); 141 return clone; 142 } 143 144 /// Creates a new type decl that's the same as src, but renamed and with only the ?=?, ?{} (default and copy), and ^?{} assertions (for complete types only) 145 TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) { 146 // TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() ); 147 148 // if ( src->get_kind() == TypeDecl::Any ) { 149 // TypeInstType *opParamType = new TypeInstType( Type::Qualifiers(), name, dst ); 150 // FunctionType *opFunctionType = new FunctionType( Type::Qualifiers(), false ); 151 // opFunctionType->get_parameters().push_back( 152 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), opParamType->clone() ), 0 ) ); 153 // FunctionDecl *ctorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false ); 154 // FunctionDecl *dtorAssert = new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false ); 155 156 // opFunctionType->get_parameters().push_back( 157 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType, 0 ) ); 158 // FunctionDecl *copyCtorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false ); 159 160 // opFunctionType->get_returnVals().push_back( 161 // new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType->clone(), 0 ) ); 162 // FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType, 0, false, false ); 163 164 165 // dst->get_assertions().push_back( assignAssert ); 166 // dst->get_assertions().push_back( ctorAssert ); 167 // dst->get_assertions().push_back( dtorAssert ); 168 // dst->get_assertions().push_back( copyCtorAssert ); 169 // } 170 171 TypeDecl *dst = new TypeDecl( src->get_name(), src->get_storageClass(), 0, src->get_kind() ); 172 cloneAll(src->get_assertions(), dst->get_assertions()); 173 return dst; 174 } 175 176 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) { 177 // if ( isDynamicLayout && src ) { 178 // genericSubs.apply( src ); 179 // } 180 208 181 ObjectDecl * returnVal = NULL; 209 182 if ( ! func->get_functionType()->get_returnVals().empty() ) { … … 214 187 215 188 // assign to destination (and return value if generic) 216 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) ); 189 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 190 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 217 191 Expression *dstselect = new MemberExpr( field, derefExpr ); 218 192 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 219 193 220 194 if ( isDynamicLayout && returnVal ) { 221 // xxx - there used to be a dereference on returnVal, but this seems to have been wrong? 222 Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) ); 195 UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) ); 196 derefRet->get_args().push_back( new VariableExpr( returnVal ) ); 197 Expression *retselect = new MemberExpr( field, derefRet ); 223 198 genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 224 199 } // if 225 200 } 226 201 227 /// 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 bodies228 202 template<typename Iterator> 229 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {203 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) { 230 204 for ( ; member != end; ++member ) { 231 205 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate … … 263 237 264 238 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL; 265 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );239 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout, forward ); 266 240 } // if 267 241 } // for … … 271 245 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 272 246 template<typename Iterator> 273 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {247 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout ) { 274 248 FunctionType * ftype = func->get_functionType(); 275 249 std::list<DeclarationWithType*> & params = ftype->get_parameters(); … … 297 271 // matching parameter, initialize field with copy ctor 298 272 Expression *srcselect = new VariableExpr(*parameter); 299 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );273 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout ); 300 274 ++parameter; 301 275 } else { 302 276 // no matching parameter, initialize field with default ctor 303 makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );277 makeStructMemberOp( dstParam, NULL, field, func, genericSubs, isDynamicLayout ); 304 278 } 305 279 } … … 307 281 } 308 282 309 /// generates struct constructors, destructor, and assignment functions 283 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { 284 FunctionDecl * decl = functionDecl->clone(); 285 delete decl->get_statements(); 286 decl->set_statements( NULL ); 287 declsToAdd.push_back( decl ); 288 decl->fixUniqueId(); 289 } 290 310 291 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 292 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 311 293 312 294 // Make function polymorphic in same parameters as generic struct, if applicable 313 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 314 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 295 bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 296 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 297 std::list< Expression* > structParams; // List of matching parameters to put on types 298 TypeSubstitution genericSubs; // Substitutions to make to member types of struct 299 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 300 if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true; 301 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 302 assignType->get_forall().push_back( typeParam ); 303 TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ); 304 genericSubs.add( (*param)->get_name(), newParamType ); 305 structParams.push_back( new TypeExpr( newParamType ) ); 306 } 307 308 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 ); 309 assignType->get_parameters().push_back( dstParam ); 310 311 // void ?{}(T *); void ^?{}(T *); 312 FunctionType *ctorType = assignType->clone(); 313 FunctionType *dtorType = assignType->clone(); 314 315 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 316 assignType->get_parameters().push_back( srcParam ); 317 318 // void ?{}(T *, T); 319 FunctionType *copyCtorType = assignType->clone(); 315 320 316 321 // T ?=?(T *, T); 317 FunctionType *assignType = genAssignType( refType ); 318 cloneAll( typeParams, assignType->get_forall() ); 319 320 // void ?{}(T *); void ^?{}(T *); 321 FunctionType *ctorType = genDefaultType( refType ); 322 cloneAll( typeParams, ctorType->get_forall() ); 323 FunctionType *dtorType = genDefaultType( refType ); 324 cloneAll( typeParams, dtorType->get_forall() ); 325 326 // void ?{}(T *, T); 327 FunctionType *copyCtorType = genCopyType( refType ); 328 cloneAll( typeParams, copyCtorType->get_forall() ); 329 330 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 331 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 332 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 333 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 322 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 323 assignType->get_returnVals().push_back( returnVal ); 324 325 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 326 // because each unit generates copies of the default routines for each aggregate. 327 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 328 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false ); 329 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false ); 330 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false ); 331 assignDecl->fixUniqueId(); 332 ctorDecl->fixUniqueId(); 333 copyCtorDecl->fixUniqueId(); 334 dtorDecl->fixUniqueId(); 334 335 335 336 if ( functionNesting == 0 ) { 336 337 // forward declare if top-level struct, so that 337 338 // type is complete as soon as its body ends 338 // Note: this is necessary if we want structs which contain339 // generic (otype) structs as members.340 339 addForwardDecl( assignDecl, declsToAdd ); 341 340 addForwardDecl( ctorDecl, declsToAdd ); … … 366 365 } 367 366 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 368 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 369 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout ); 367 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false ); 368 ctor->fixUniqueId(); 369 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isDynamicLayout ); 370 370 memCtors.push_back( ctor ); 371 371 } … … 373 373 374 374 // generate appropriate calls to member ctor, assignment 375 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout );376 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout );377 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout );375 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isDynamicLayout ); 376 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isDynamicLayout ); 377 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isDynamicLayout ); 378 378 // needs to do everything in reverse, so pass "forward" as false 379 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false ); 380 381 assert( assignType->get_parameters().size() == 2 ); 382 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 383 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 384 379 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isDynamicLayout, false ); 380 381 if ( ! isDynamicLayout ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 382 383 declsToAdd.push_back( assignDecl ); 385 384 declsToAdd.push_back( ctorDecl ); 386 385 declsToAdd.push_back( copyCtorDecl ); 387 386 declsToAdd.push_back( dtorDecl ); 388 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return389 387 declsToAdd.splice( declsToAdd.end(), memCtors ); 390 388 } 391 389 392 /// generate a single union assignment expression (using memcpy)393 template< typename OutputIterator >394 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {395 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );396 copy->get_args().push_back( new VariableExpr( dstParam ) );397 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );398 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );399 *out++ = new ExprStmt( noLabels, copy );400 }401 402 /// generates the body of a union assignment/copy constructor/field constructor403 void makeUnionAssignBody( FunctionDecl * funcDecl, bool isDynamicLayout ) {404 FunctionType * ftype = funcDecl->get_functionType();405 assert( ftype->get_parameters().size() == 2 );406 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );407 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );408 ObjectDecl * returnVal = nullptr;409 if ( ! ftype->get_returnVals().empty() ) {410 returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );411 }412 413 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );414 if ( returnVal ) {415 if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( funcDecl->get_statements()->get_kids() ) );416 else funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );417 }418 }419 420 /// generates union constructors, destructors, and assignment operator421 390 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 391 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 392 422 393 // Make function polymorphic in same parameters as generic union, if applicable 423 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 424 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 394 bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 395 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 396 std::list< Expression* > unionParams; // List of matching parameters to put on types 397 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 398 if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true; 399 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 400 assignType->get_forall().push_back( typeParam ); 401 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); 402 } 403 404 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 ); 405 assignType->get_parameters().push_back( dstParam ); 425 406 426 407 // default ctor/dtor need only first parameter 427 // void ?{}(T *); void ^?{}(T *); 428 FunctionType *ctorType = genDefaultType( refType ); 429 FunctionType *dtorType = genDefaultType( refType ); 408 FunctionType * ctorType = assignType->clone(); 409 FunctionType * dtorType = assignType->clone(); 410 411 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 412 assignType->get_parameters().push_back( srcParam ); 430 413 431 414 // copy ctor needs both parameters 432 // void ?{}(T *, T); 433 FunctionType *copyCtorType = genCopyType( refType ); 415 FunctionType * copyCtorType = assignType->clone(); 434 416 435 417 // assignment needs both and return value 436 // T ?=?(T *, T); 437 FunctionType *assignType = genAssignType( refType ); 438 439 cloneAll( typeParams, ctorType->get_forall() ); 440 cloneAll( typeParams, dtorType->get_forall() ); 441 cloneAll( typeParams, copyCtorType->get_forall() ); 442 cloneAll( typeParams, assignType->get_forall() ); 418 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 419 assignType->get_returnVals().push_back( returnVal ); 443 420 444 421 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 445 422 // because each unit generates copies of the default routines for each aggregate. 446 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 447 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 448 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 449 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 450 451 makeUnionAssignBody( assignDecl, isDynamicLayout ); 423 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 424 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false ); 425 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false ); 426 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false ); 427 428 assignDecl->fixUniqueId(); 429 ctorDecl->fixUniqueId(); 430 copyCtorDecl->fixUniqueId(); 431 dtorDecl->fixUniqueId(); 432 433 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( assignDecl->get_statements()->get_kids() ) ); 434 if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( assignDecl->get_statements()->get_kids() ) ); 435 else assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 452 436 453 437 // body of assignment and copy ctor is the same 454 makeUnionAssignBody( copyCtorDecl, isDynamicLayout);438 copyCtorDecl->set_statements( assignDecl->get_statements()->clone() ); 455 439 456 440 // create a constructor which takes the first member type as a parameter. … … 465 449 FunctionType * memCtorType = ctorType->clone(); 466 450 memCtorType->get_parameters().push_back( srcParam ); 467 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting ); 468 469 makeUnionAssignBody( ctor, isDynamicLayout ); 451 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType, new CompoundStmt( noLabels ), true, false ); 452 ctor->fixUniqueId(); 453 454 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( ctor->get_statements()->get_kids() ) ); 470 455 memCtors.push_back( ctor ); 471 456 // only generate a ctor for the first field … … 474 459 } 475 460 461 declsToAdd.push_back( assignDecl ); 476 462 declsToAdd.push_back( ctorDecl ); 477 463 declsToAdd.push_back( copyCtorDecl ); 478 464 declsToAdd.push_back( dtorDecl ); 479 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return480 465 declsToAdd.splice( declsToAdd.end(), memCtors ); 481 466 } … … 493 478 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) { 494 479 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 495 for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {496 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );497 }498 480 structInst.set_baseStruct( structDecl ); 499 481 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd ); … … 506 488 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 507 489 unionInst.set_baseUnion( unionDecl ); 508 for ( TypeDecl * typeDecl : unionDecl->get_parameters() ) {509 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );510 }511 490 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd ); 512 491 } // if … … 514 493 515 494 void AutogenerateRoutines::visit( TypeDecl *typeDecl ) { 495 CompoundStmt *stmts = 0; 516 496 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false ); 517 497 typeInst->set_baseType( typeDecl ); 518 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, typeInst->clone(), nullptr ); 519 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), typeInst->clone() ), nullptr ); 520 521 std::list< Statement * > stmts; 498 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 ); 499 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 ); 522 500 if ( typeDecl->get_base() ) { 523 501 // xxx - generate ctor/dtors for typedecls, e.g. 524 502 // otype T = int *; 503 stmts = new CompoundStmt( std::list< Label >() ); 525 504 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 526 505 assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) ); 527 506 assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) ); 528 stmts .push_back( new ReturnStmt( std::list< Label >(), assign ) );507 stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) ); 529 508 } // if 530 509 FunctionType *type = new FunctionType( Type::Qualifiers(), false ); … … 532 511 type->get_parameters().push_back( dst ); 533 512 type->get_parameters().push_back( src ); 534 FunctionDecl *func = genFunc( "?=?", type, functionNesting ); 535 func->get_statements()->get_kids() = stmts; 513 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false ); 536 514 declsToAdd.push_back( func ); 537 515 } … … 578 556 visitStatement( switchStmt ); 579 557 } 580 581 void makeTupleFunctionBody( FunctionDecl * function ) {582 FunctionType * ftype = function->get_functionType();583 assertf( ftype->get_parameters().size() == 1 || ftype->get_parameters().size() == 2, "too many parameters in generated tuple function" );584 585 UntypedExpr * untyped = new UntypedExpr( new NameExpr( function->get_name() ) );586 587 /// xxx - &* is used to make this easier for later passes to handle588 untyped->get_args().push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );589 if ( ftype->get_parameters().size() == 2 ) {590 untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );591 }592 function->get_statements()->get_kids().push_back( new ExprStmt( noLabels, untyped ) );593 function->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );594 }595 596 Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {597 tupleType = safe_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );598 std::string mangleName = SymTab::Mangler::mangleType( tupleType );599 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;600 seenTuples.insert( mangleName );601 602 // T ?=?(T *, T);603 FunctionType *assignType = genAssignType( tupleType );604 605 // void ?{}(T *); void ^?{}(T *);606 FunctionType *ctorType = genDefaultType( tupleType );607 FunctionType *dtorType = genDefaultType( tupleType );608 609 // void ?{}(T *, T);610 FunctionType *copyCtorType = genCopyType( tupleType );611 612 std::set< TypeDecl* > done;613 std::list< TypeDecl * > typeParams;614 for ( Type * t : *tupleType ) {615 if ( TypeInstType * ty = dynamic_cast< TypeInstType * >( t ) ) {616 if ( ! done.count( ty->get_baseType() ) ) {617 TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), DeclarationNode::NoStorageClass, nullptr, TypeDecl::Any );618 TypeInstType * inst = new TypeInstType( Type::Qualifiers(), newDecl->get_name(), newDecl );619 newDecl->get_assertions().push_back( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genAssignType( inst ), nullptr, true, false ) );620 newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );621 newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genCopyType( inst ), nullptr, true, false ) );622 newDecl->get_assertions().push_back( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );623 typeParams.push_back( newDecl );624 done.insert( ty->get_baseType() );625 }626 }627 }628 cloneAll( typeParams, ctorType->get_forall() );629 cloneAll( typeParams, dtorType->get_forall() );630 cloneAll( typeParams, copyCtorType->get_forall() );631 cloneAll( typeParams, assignType->get_forall() );632 633 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );634 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );635 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );636 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );637 638 makeTupleFunctionBody( assignDecl );639 makeTupleFunctionBody( ctorDecl );640 makeTupleFunctionBody( copyCtorDecl );641 makeTupleFunctionBody( dtorDecl );642 643 addDeclaration( ctorDecl );644 addDeclaration( copyCtorDecl );645 addDeclaration( dtorDecl );646 addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return647 648 return tupleType;649 }650 651 DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {652 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );653 mutateAll( functionDecl->get_oldDecls(), *this );654 functionNesting += 1;655 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );656 functionNesting -= 1;657 return functionDecl;658 }659 660 CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {661 seenTuples.beginScope();662 compoundStmt = safe_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );663 seenTuples.endScope();664 return compoundStmt;665 }666 558 } // SymTab
Note:
See TracChangeset
for help on using the changeset viewer.