Changeset 186fd86
- Timestamp:
- Nov 17, 2016, 4:22:24 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, with_gc
- Children:
- 2c57025
- Parents:
- d9fa60a
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
rd9fa60a r186fd86 32 32 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; } 33 33 34 typedef Visitor Parent; 35 using Parent::visit; 36 34 37 virtual void visit( EnumDecl *enumDecl ); 35 38 virtual void visit( StructDecl *structDecl ); … … 63 66 } 64 67 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 68 /// inserts a forward declaration for functionDecl into declsToAdd 69 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { 70 FunctionDecl * decl = functionDecl->clone(); 71 delete decl->get_statements(); 72 decl->set_statements( NULL ); 73 declsToAdd.push_back( decl ); 74 decl->fixUniqueId(); 75 } 76 77 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 78 FunctionType * genDefaultType( Type * paramType ) { 79 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 80 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr ); 81 ftype->get_parameters().push_back( dstParam ); 82 83 return ftype; 84 } 85 86 /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T) 87 FunctionType * genCopyType( Type * paramType ) { 88 FunctionType *ftype = genDefaultType( paramType ); 89 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 90 ftype->get_parameters().push_back( srcParam ); 91 return ftype; 92 } 93 94 /// given type T, generate type of assignment, i.e. function type T (*) (T *, T) 95 FunctionType * genAssignType( Type * paramType, const std::list< Expression* > & params = std::list< Expression* >() ) { 96 FunctionType *ftype = genCopyType( paramType ); 97 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr ); 98 ftype->get_returnVals().push_back( returnVal ); 99 return ftype; 100 } 101 102 /// true if the aggregate's layout is dynamic 103 template< typename AggrDecl > 104 bool hasDynamicLayout( AggrDecl * aggregateDecl ) { 105 for ( TypeDecl * param : aggregateDecl->get_parameters() ) { 106 if ( param->get_kind() == TypeDecl::Any ) return true; 107 } 108 return false; 109 } 110 111 /// generate a function decl from a name and type. Nesting depth determines whether 112 /// the declaration is static or not; optional paramter determines if declaration is intrinsic 113 FunctionDecl * genFunc( const std::string & fname, FunctionType * ftype, unsigned int functionNesting, bool isIntrinsic = false ) { 114 // Routines at global scope marked "static" to prevent multiple definitions in separate translation units 100 115 // because each unit generates copies of the default routines for each aggregate. 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 116 DeclarationNode::StorageClass sc = functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static; 117 LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen; 118 FunctionDecl * decl = new FunctionDecl( fname, sc, spec, ftype, new CompoundStmt( noLabels ), true, false ); 119 decl->fixUniqueId(); 120 return decl; 121 } 122 123 /// generates a single enumeration assignment expression 124 ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) { 113 125 // enum copy construct and assignment is just C-style assignment. 114 126 // this looks like a bad recursive call, but code gen will turn it into 115 127 // a C-style assignment. 116 128 // This happens before function pointer type conversion, so need to do it manually here 129 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the 130 // type of the function that this expression is being generated for (so that the correct 131 // parameters) are using in the variable exprs 132 assert( ftype->get_parameters().size() == 2 ); 133 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 134 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 135 117 136 VariableExpr * assignVarExpr = new VariableExpr( assignDecl ); 118 137 Type * assignVarExprType = assignVarExpr->get_result(); … … 122 141 assignExpr->get_args().push_back( new VariableExpr( dstParam ) ); 123 142 assignExpr->get_args().push_back( new VariableExpr( srcParam ) ); 143 return assignExpr; 144 } 145 146 // E ?=?(E volatile*, int), 147 // ?=?(E _Atomic volatile*, int); 148 void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) { 149 150 // T ?=?(E *, E); 151 FunctionType *assignType = genAssignType( refType ); 152 153 // void ?{}(E *); void ^?{}(E *); 154 FunctionType * ctorType = genDefaultType( refType->clone() ); 155 FunctionType * dtorType = genDefaultType( refType->clone() ); 156 157 // void ?{}(E *, E); 158 FunctionType *copyCtorType = genCopyType( refType->clone() ); 159 160 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 161 // right now these cases work, but that might change. 162 163 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment. 164 // Really they're something of a cross between instrinsic and autogen, so should 165 // probably make a new linkage type 166 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true ); 167 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true ); 168 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true ); 169 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true ); 124 170 125 171 // body is either return stmt or expr stmt 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() ) );172 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) ); 173 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) ); 128 174 129 175 declsToAdd.push_back( assignDecl ); … … 133 179 } 134 180 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 ) { 181 /// generates a single struct member operation (constructor call, destructor call, assignment call) 182 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) { 177 183 ObjectDecl * returnVal = NULL; 178 184 if ( ! func->get_functionType()->get_returnVals().empty() ) { … … 194 200 } 195 201 202 /// 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 196 203 template<typename Iterator> 197 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs,bool isDynamicLayout, bool forward = true ) {204 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) { 198 205 for ( ; member != end; ++member ) { 199 206 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate … … 231 238 232 239 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL; 233 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs,isDynamicLayout, forward );240 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward ); 234 241 } // if 235 242 } // for … … 239 246 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 240 247 template<typename Iterator> 241 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs,bool isDynamicLayout ) {248 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) { 242 249 FunctionType * ftype = func->get_functionType(); 243 250 std::list<DeclarationWithType*> & params = ftype->get_parameters(); … … 265 272 // matching parameter, initialize field with copy ctor 266 273 Expression *srcselect = new VariableExpr(*parameter); 267 makeStructMemberOp( dstParam, srcselect, field, func, genericSubs,isDynamicLayout );274 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout ); 268 275 ++parameter; 269 276 } else { 270 277 // no matching parameter, initialize field with default ctor 271 makeStructMemberOp( dstParam, NULL, field, func, genericSubs,isDynamicLayout );278 makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout ); 272 279 } 273 280 } … … 275 282 } 276 283 277 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { 278 FunctionDecl * decl = functionDecl->clone(); 279 delete decl->get_statements(); 280 decl->set_statements( NULL ); 281 declsToAdd.push_back( decl ); 282 decl->fixUniqueId(); 283 } 284 284 /// generates struct constructors, destructor, and assignment functions 285 285 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 286 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );287 286 288 287 // Make function polymorphic in same parameters as generic struct, if applicable 289 bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 290 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 291 std::list< Expression* > structParams; // List of matching parameters to put on types 292 TypeSubstitution genericSubs; // Substitutions to make to member types of struct 293 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 294 if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true; 295 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 296 assignType->get_forall().push_back( typeParam ); 297 TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ); 298 genericSubs.add( (*param)->get_name(), newParamType ); 299 structParams.push_back( new TypeExpr( newParamType ) ); 300 } 301 302 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 ); 303 assignType->get_parameters().push_back( dstParam ); 288 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 289 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 290 291 // T ?=?(T *, T); 292 FunctionType *assignType = genAssignType( refType ); 293 cloneAll( typeParams, assignType->get_forall() ); 304 294 305 295 // void ?{}(T *); void ^?{}(T *); 306 FunctionType *ctorType = assignType->clone(); 307 FunctionType *dtorType = assignType->clone(); 308 309 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 310 assignType->get_parameters().push_back( srcParam ); 296 FunctionType *ctorType = genDefaultType( refType ); 297 cloneAll( typeParams, ctorType->get_forall() ); 298 FunctionType *dtorType = genDefaultType( refType ); 299 cloneAll( typeParams, dtorType->get_forall() ); 311 300 312 301 // void ?{}(T *, T); 313 FunctionType *copyCtorType = assignType->clone(); 314 315 // T ?=?(T *, T); 316 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 317 assignType->get_returnVals().push_back( returnVal ); 318 319 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 320 // because each unit generates copies of the default routines for each aggregate. 321 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 322 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false ); 323 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false ); 324 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false ); 325 assignDecl->fixUniqueId(); 326 ctorDecl->fixUniqueId(); 327 copyCtorDecl->fixUniqueId(); 328 dtorDecl->fixUniqueId(); 302 FunctionType *copyCtorType = genCopyType( refType ); 303 cloneAll( typeParams, copyCtorType->get_forall() ); 304 305 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 306 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 307 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 308 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 329 309 330 310 if ( functionNesting == 0 ) { … … 359 339 } 360 340 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 361 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false ); 362 ctor->fixUniqueId(); 363 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isDynamicLayout ); 341 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 342 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout ); 364 343 memCtors.push_back( ctor ); 365 344 } … … 367 346 368 347 // generate appropriate calls to member ctor, assignment 369 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs,isDynamicLayout );370 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs,isDynamicLayout );371 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs,isDynamicLayout );348 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout ); 349 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout ); 350 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout ); 372 351 // needs to do everything in reverse, so pass "forward" as false 373 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isDynamicLayout, false ); 374 375 if ( ! isDynamicLayout ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 352 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false ); 353 354 if ( ! isDynamicLayout ) { 355 assert( assignType->get_parameters().size() == 2 ); 356 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() ); 357 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 358 } 376 359 377 360 declsToAdd.push_back( assignDecl ); … … 382 365 } 383 366 367 /// generate a single union assignment expression (using memcpy) 368 template< typename OutputIterator > 369 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 370 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 371 copy->get_args().push_back( new VariableExpr( dstParam ) ); 372 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 373 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); 374 *out++ = new ExprStmt( noLabels, copy ); 375 } 376 377 /// generates the body of a union assignment/copy constructor/field constructor 378 void makeUnionAssignBody( FunctionDecl * funcDecl, bool isDynamicLayout ) { 379 FunctionType * ftype = funcDecl->get_functionType(); 380 assert( ftype->get_parameters().size() == 2 ); 381 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 382 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 383 ObjectDecl * returnVal = nullptr; 384 if ( ! ftype->get_returnVals().empty() ) { 385 returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() ); 386 } 387 388 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) ); 389 if ( returnVal ) { 390 if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( funcDecl->get_statements()->get_kids() ) ); 391 else funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 392 } 393 } 394 395 /// generates union constructors, destructors, and assignment operator 384 396 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 385 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );386 387 397 // Make function polymorphic in same parameters as generic union, if applicable 388 bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 389 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 390 std::list< Expression* > unionParams; // List of matching parameters to put on types 391 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 392 if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true; 393 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 394 assignType->get_forall().push_back( typeParam ); 395 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); 396 } 397 398 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 ); 399 assignType->get_parameters().push_back( dstParam ); 398 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 399 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 400 400 401 401 // default ctor/dtor need only first parameter 402 FunctionType * ctorType = assignType->clone();403 FunctionType * dtorType = assignType->clone();404 405 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0);406 assignType->get_parameters().push_back( srcParam);402 // void ?{}(T *); void ^?{}(T *); 403 FunctionType *ctorType = genDefaultType( refType ); 404 cloneAll( typeParams, ctorType->get_forall() ); 405 FunctionType *dtorType = genDefaultType( refType ); 406 cloneAll( typeParams, dtorType->get_forall() ); 407 407 408 408 // copy ctor needs both parameters 409 FunctionType * copyCtorType = assignType->clone(); 409 // void ?{}(T *, T); 410 FunctionType *copyCtorType = genCopyType( refType ); 411 cloneAll( typeParams, copyCtorType->get_forall() ); 410 412 411 413 // assignment needs both and return value 412 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 413 assignType->get_returnVals().push_back( returnVal ); 414 // T ?=?(T *, T); 415 FunctionType *assignType = genAssignType( refType ); 416 cloneAll( typeParams, assignType->get_forall() ); 414 417 415 418 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 416 419 // because each unit generates copies of the default routines for each aggregate. 417 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 418 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false ); 419 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false ); 420 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false ); 421 422 assignDecl->fixUniqueId(); 423 ctorDecl->fixUniqueId(); 424 copyCtorDecl->fixUniqueId(); 425 dtorDecl->fixUniqueId(); 426 427 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( assignDecl->get_statements()->get_kids() ) ); 428 if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( assignDecl->get_statements()->get_kids() ) ); 429 else assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 420 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting ); 421 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting ); 422 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting ); 423 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 424 425 makeUnionAssignBody( assignDecl, isDynamicLayout ); 430 426 431 427 // body of assignment and copy ctor is the same 432 copyCtorDecl->set_statements( assignDecl->get_statements()->clone());428 makeUnionAssignBody( copyCtorDecl, isDynamicLayout ); 433 429 434 430 // create a constructor which takes the first member type as a parameter. … … 443 439 FunctionType * memCtorType = ctorType->clone(); 444 440 memCtorType->get_parameters().push_back( srcParam ); 445 FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType, new CompoundStmt( noLabels ), true, false ); 446 ctor->fixUniqueId(); 447 448 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( ctor->get_statements()->get_kids() ) ); 441 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting ); 442 443 makeUnionAssignBody( ctor, isDynamicLayout ); 449 444 memCtors.push_back( ctor ); 450 445 // only generate a ctor for the first field … … 472 467 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) { 473 468 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 469 for ( TypeDecl * typeDecl : structDecl->get_parameters() ) { 470 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 471 } 474 472 structInst.set_baseStruct( structDecl ); 475 473 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd ); … … 482 480 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 483 481 unionInst.set_baseUnion( unionDecl ); 482 for ( TypeDecl * typeDecl : unionDecl->get_parameters() ) { 483 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) ); 484 } 484 485 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd ); 485 486 } // if … … 487 488 488 489 void AutogenerateRoutines::visit( TypeDecl *typeDecl ) { 489 CompoundStmt *stmts = 0;490 490 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false ); 491 491 typeInst->set_baseType( typeDecl ); 492 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 ); 493 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 ); 492 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, typeInst->clone(), nullptr ); 493 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), typeInst->clone() ), nullptr ); 494 495 std::list< Statement * > stmts; 494 496 if ( typeDecl->get_base() ) { 495 497 // xxx - generate ctor/dtors for typedecls, e.g. 496 498 // otype T = int *; 497 stmts = new CompoundStmt( std::list< Label >() );498 499 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 499 500 assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) ); 500 501 assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) ); 501 stmts ->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );502 stmts.push_back( new ReturnStmt( std::list< Label >(), assign ) ); 502 503 } // if 503 504 FunctionType *type = new FunctionType( Type::Qualifiers(), false ); … … 505 506 type->get_parameters().push_back( dst ); 506 507 type->get_parameters().push_back( src ); 507 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false ); 508 FunctionDecl *func = genFunc( "?=?", type, functionNesting ); 509 func->get_statements()->get_kids() = stmts; 508 510 declsToAdd.push_back( func ); 509 511 } -
src/tests/.expect/32/extension.txt
rd9fa60a r186fd86 70 70 ((void)((_tmp_cp_ret1=__builtin_memcpy(((void *)___dst__P2uU_1), ((const void *)(&___src__2uU_1)), sizeof(union U ))) , _tmp_cp_ret1)); 71 71 ((void)(_tmp_cp_ret1) /* ^?{} */); 72 return ((void)___src__2uU_1);73 72 } 74 73 static inline void ___destructor__F_P2uU_autogen___1(union U *___dst__P2uU_1){ -
src/tests/.expect/64/extension.txt
rd9fa60a r186fd86 70 70 ((void)((_tmp_cp_ret1=__builtin_memcpy(((void *)___dst__P2uU_1), ((const void *)(&___src__2uU_1)), sizeof(union U ))) , _tmp_cp_ret1)); 71 71 ((void)(_tmp_cp_ret1) /* ^?{} */); 72 return ((void)___src__2uU_1);73 72 } 74 73 static inline void ___destructor__F_P2uU_autogen___1(union U *___dst__P2uU_1){
Note: See TracChangeset
for help on using the changeset viewer.