Changes in src/GenPoly/Box.cc [9d7b3ea:4067aa8]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r9d7b3ea r4067aa8 22 22 23 23 #include "Box.h" 24 #include "DeclMutator.h"25 24 #include "InstantiateGeneric.h" 26 25 #include "PolyMutator.h" … … 55 54 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 56 55 57 /// Adds layout-generation functions to polymorphic types58 class LayoutFunctionBuilder : public DeclMutator {59 unsigned int functionNesting; // current level of nested functions60 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 68 56 /// 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 69 57 class Pass1 : public PolyMutator { … … 171 159 } // anonymous namespace 172 160 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 } // if 167 } // for 168 } 169 173 170 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging 174 171 template< typename MutatorType > … … 198 195 199 196 void box( std::list< Declaration *>& translationUnit ) { 200 LayoutFunctionBuilder layoutBuilder;201 197 Pass1 pass1; 202 198 Pass2 pass2; 203 199 MemberExprFixer memberFixer; 204 200 Pass3 pass3; 205 layoutBuilder.mutateDeclarationList( translationUnit );206 201 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 207 202 mutateTranslationUnit/*All*/( translationUnit, pass2 ); … … 211 206 } 212 207 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 function225 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 type238 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 declaration247 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 units249 // 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 operation257 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 operation264 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 variable272 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 block277 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 < rhs282 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 rhs289 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );290 // if not aligned, increment to alignment291 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );292 return makeCond( ifCond, ifExpr );293 }294 295 /// adds an expression to a compound statement296 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 statement301 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 structs307 if ( structDecl->get_members().empty() ) return structDecl;308 309 // get parameters that can change layout, exiting early if none310 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );311 if ( otypeParams.empty() ) return structDecl;312 313 // build layout function signature314 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 decl327 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );328 329 // calculate struct layout in function body330 331 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size332 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 alignment344 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( dwt->get_type() ) ) );345 }346 347 // place current size in the current offset index348 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 size353 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) );354 355 // take max of member alignment and global alignment356 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 alignment359 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 unions367 if ( unionDecl->get_members().empty() ) return unionDecl;368 369 // get parameters that can change layout, exiting early if none370 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );371 if ( otypeParams.empty() ) return unionDecl;372 373 // build layout function signature374 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 decl385 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );386 387 // calculate union layout in function body388 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 size395 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) );396 397 // take max of member alignment and global alignment398 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 alignment401 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );402 403 addDeclarationAfter( layoutDecl );404 return unionDecl;405 }406 407 208 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 408 209
Note:
See TracChangeset
for help on using the changeset viewer.