Changeset 9d7b3ea for src/GenPoly
- Timestamp:
- Mar 3, 2016, 1:28:51 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
- Children:
- 36ebd03
- Parents:
- dbd8652
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rdbd8652 r9d7b3ea 22 22 23 23 #include "Box.h" 24 #include "DeclMutator.h" 24 25 #include "InstantiateGeneric.h" 25 26 #include "PolyMutator.h" … … 54 55 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 55 56 57 /// Adds layout-generation functions to polymorphic types 58 class LayoutFunctionBuilder : public DeclMutator { 59 unsigned int functionNesting; // current level of nested functions 60 public: 61 LayoutFunctionBuilder() : functionNesting( 0 ) {} 62 63 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 64 virtual Declaration *mutate( StructDecl *structDecl ); 65 virtual Declaration *mutate( UnionDecl *unionDecl ); 66 }; 67 56 68 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call 57 69 class Pass1 : public PolyMutator { … … 159 171 } // anonymous namespace 160 172 161 void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {162 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {163 if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {164 (*i)->print( os );165 os << std::endl;166 } // if167 } // for168 }169 170 173 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 171 174 template< typename MutatorType > … … 195 198 196 199 void box( std::list< Declaration *>& translationUnit ) { 200 LayoutFunctionBuilder layoutBuilder; 197 201 Pass1 pass1; 198 202 Pass2 pass2; 199 203 MemberExprFixer memberFixer; 200 204 Pass3 pass3; 205 layoutBuilder.mutateDeclarationList( translationUnit ); 201 206 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 202 207 mutateTranslationUnit/*All*/( translationUnit, pass2 ); … … 206 211 } 207 212 213 ////////////////////////////////// LayoutFunctionBuilder //////////////////////////////////////////// 214 215 DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) { 216 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) ); 217 mutateAll( functionDecl->get_oldDecls(), *this ); 218 ++functionNesting; 219 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 220 --functionNesting; 221 return functionDecl; 222 } 223 224 /// Get a list of type declarations that will affect a layout function 225 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) { 226 std::list< TypeDecl * > otypeDecls; 227 228 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) { 229 if ( decl->get_kind() == TypeDecl::Any ) { 230 otypeDecls.push_back( *decl ); 231 } 232 } 233 234 return otypeDecls; 235 } 236 237 /// Adds parameters for otype layout to a function type 238 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) { 239 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 240 241 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 242 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( (*param)->get_base() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) ); 243 } 244 } 245 246 /// Builds a layout function declaration 247 FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) { 248 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 249 // because each unit generates copies of the default routines for each aggregate. 250 FunctionDecl *layoutDecl = new FunctionDecl( 251 "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false ); 252 layoutDecl->fixUniqueId(); 253 return layoutDecl; 254 } 255 256 /// Makes a unary operation 257 Expression *makeOp( const std::string &name, Expression *arg ) { 258 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 259 expr->get_args().push_back( arg ); 260 return expr; 261 } 262 263 /// Makes a binary operation 264 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) { 265 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 266 expr->get_args().push_back( lhs ); 267 expr->get_args().push_back( rhs ); 268 return expr; 269 } 270 271 /// Returns the dereference of a local pointer variable 272 Expression *derefVar( ObjectDecl *var ) { 273 return makeOp( "*?", new VariableExpr( var ) ); 274 } 275 276 /// makes an if-statement with a single-expression if-block and no then block 277 Statement *makeCond( Expression *cond, Expression *ifPart ) { 278 return new IfStmt( noLabels, cond, new ExprStmt( ifPart ), 0 ); 279 } 280 281 /// makes a statement that assigns rhs to lhs if lhs < rhs 282 Statement *makeAssignMax( Expression *lhs, Expression *rhs ) { 283 return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) ); 284 } 285 286 /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two) 287 Statement *makeAlignTo( Expression *lhs, Expression *rhs ) { 288 // check that the lhs is zeroed out to the level of rhs 289 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) ); 290 // if not aligned, increment to alignment 291 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) ); 292 return makeCond( ifCond, ifExpr ); 293 } 294 295 /// adds an expression to a compound statement 296 void addExpr( CompoundStmt *stmts, Expression *expr ) { 297 stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) ); 298 } 299 300 /// adds a statement to a compound statement 301 void addStmt( CompoundStmt *stmts, Statement *stmt ) { 302 stmts->get_kids().push_back( stmt ); 303 } 304 305 virtual Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) { 306 // do not generate layout function for "empty" tag structs 307 if ( structDecl->get_members().empty() ) return structDecl; 308 309 // get parameters that can change layout, exiting early if none 310 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() ); 311 if ( otypeParams.empty() ) return structDecl; 312 313 // build layout function signature 314 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false ); 315 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 316 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 317 318 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 319 layoutFnType->get_parameters().push_back( sizeParam ); 320 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 321 layoutFnType->get_parameters().push_back( alignParam ); 322 ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 323 layoutFnType->get_parameters().push_back( offsetParam ); 324 addOtypeParams( layoutFnType, otypeParams ); 325 326 // build function decl 327 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType ); 328 329 // calculate struct layout in function body 330 331 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size 332 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) ); 333 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 334 unsigned long n_members = 0; 335 bool firstMember = true; 336 for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) { 337 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ); 338 assert( dwt ); 339 340 if ( firstMember ) { 341 firstMember = false; 342 } else { 343 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment 344 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( dwt->get_type() ) ) ); 345 } 346 347 // place current size in the current offset index 348 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ), 349 derefVar( sizeParam ) ) ); 350 ++n_members; 351 352 // add member size to current size 353 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) ); 354 355 // take max of member alignment and global alignment 356 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( dwt->get_type() ) ) ); 357 } 358 // make sure the type is end-padded to a multiple of its alignment 359 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 360 361 addDeclarationAfter( layoutDecl ); 362 return structDecl; 363 } 364 365 virtual Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) { 366 // do not generate layout function for "empty" tag unions 367 if ( unionDecl->get_members().empty() ) return unionDecl; 368 369 // get parameters that can change layout, exiting early if none 370 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() ); 371 if ( otypeParams.empty() ) return unionDecl; 372 373 // build layout function signature 374 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false ); 375 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 376 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 377 378 ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 379 layoutFnType->get_parameters().push_back( sizeParam ); 380 ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 ); 381 layoutFnType->get_parameters().push_back( alignParam ); 382 addOtypeParams( layoutFnType, otypeParams ); 383 384 // build function decl 385 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType ); 386 387 // calculate union layout in function body 388 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 389 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) ); 390 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) { 391 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ); 392 assert( dwt ); 393 394 // take max member size and global size 395 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) ); 396 397 // take max of member alignment and global alignment 398 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( dwt->get_type() ) ) ); 399 } 400 // make sure the type is end-padded to a multiple of its alignment 401 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 402 403 addDeclarationAfter( layoutDecl ); 404 return unionDecl; 405 } 406 208 407 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 209 408
Note: See TracChangeset
for help on using the changeset viewer.