// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // TreeStruct.cc -- // // Author : Andrew Beach // Created On : Wed Jul 12 14:48:00 2017 // Last Modified By : Andrew Beach // Last Modified On : Fri Jul 14 15:49:00 2017 // Update Count : 0 // #include "Common/PassVisitor.h" #include "InitTweak/InitTweak.h" #include "SynTree/Attribute.h" #include "SynTree/Declaration.h" #include "SynTree/Expression.h" #include "SynTree/Statement.h" #include "SynTree/Type.h" #include "SynTree/Mutator.h" __attribute__((noinline)) Declaration* searchDeclList( const std::list< Declaration* > & lst, const Declaration * val ) { auto tmp = std::find( lst.begin(), lst.end(), val ); return (tmp == lst.end()) ? nullptr : *tmp; } class TreeStructExpanderCore : public WithDeclsToAdd { typedef std::pair map_pair; typedef std::map map; typedef std::pair insert_result; // std::pair >, // bool> // key_name first first std::string key_name( std::pair & result ) { return result.first->first; } // struct_decl first second first StructDecl *& struct_decl( std::pair & result ) { return result.first->second.first; } // type_object first second second ObjectDecl *& type_object( std::pair & result ) { return result.first->second.second; } // key_name first std::string key_name( map::iterator & it ) { return it->first; } // struct_decl second first StructDecl *& struct_decl( map::iterator & it ) { return it->second.first; } // type_object second second ObjectDecl *& type_object( map::iterator & it ) { return it->second.second; } StructDecl * type_object_type; map known_structs; public: TreeStructExpanderCore() : type_object_type( nullptr ) {} std::string base_type_object_name( std::string struct_name ) { return std::string("type_object_for_") + struct_name; } // Throws SemanticError if error is found. Declaration * postmutate( StructDecl * node ) { // Skip all untagged nodes. if ( ! node->get_tagged() ) { // Although we do grap the type object first. if ( "__cfa__type_object" == node->get_name() ) { assert( !type_object_type && "repeated type_object definition" ); type_object_type = node; } return node; } else { assert( type_object_type && "missing type_object definition" ); } // Track all of the tagged nodes. std::pair target = known_structs.insert( std::make_pair( node->get_name(), map_pair( node, nullptr) ) ); // Validate no conflict (is that does elsewhere?) // New declaration, no conflicting definition possible. if ( target.second ) { ; // Conflict if they have different parents. } else if ( node->get_parentName() != struct_decl( target )->get_parentName() ) { throw SemanticError("TreeStructs do not share parents."); // Conflict if they both have a body. } else if ( node->has_body() && struct_decl( target )->has_body() ) { throw SemanticError("TreeStructs with repeated bodies."); // Update to the one with a body. } else if ( node->has_body() ) { struct_decl( target ) = node; } // if ( node->get_name() == node->get_parent_name() ) // We might actually use this for a while to say no parent. // Validate Parent exists: map::iterator target_parent = known_structs.find( node->get_parentName() ); if ( known_structs.end() == target_parent && node->has_parent() ) { throw SemanticError( std::string( "No named " ) + node->get_parentName() + " defined." ); } static Attribute linkonce( "section", std::list{ new NameExpr( "\".gnu.linkonce.exception\"" ) } ); Expression * parent_address = node->has_parent() ? (Expression *)new AddressExpr( new VariableExpr( target_parent->second.second ) ) : (Expression *)new ConstantExpr( Constant::null( new PointerType( Type::Qualifiers(), new StructInstType( Type::Qualifiers(), type_object_type ) ) ) ); // Insert the declaration of the type object. ObjectDecl * type_object_inst = new ObjectDecl( base_type_object_name( node->get_name() ), Type::StorageClasses() /* I think this is none. */, node->get_linkage(), nullptr, new StructInstType( Type::Qualifiers(), type_object_type ), new ListInit({ new SingleInit( parent_address ) }), std::list{ linkonce.clone() } ); declsToAddAfter.push_back( type_object_inst ); type_object( target ) = type_object_inst; // Insert a field into the structure. node->get_members().push_front( new ObjectDecl( "tag", Type::StorageClasses(), node->get_linkage(), nullptr, new PointerType( Type::Qualifiers( Type::Const ), new StructInstType( Type::Qualifiers( Type::Const ), type_object_type ) ), nullptr /*new SingleInit( new AddressExpr( new VariableExpr( type_object_inst ) ) )*/ ) ); return node; } DeclarationWithType * postmutate( FunctionDecl * funcDecl ) { if ( ! InitTweak::isConstructor( funcDecl->get_name() ) ) { return funcDecl; } if ( nullptr == funcDecl->get_statements() ) { return funcDecl; } DeclarationWithType * param_one = funcDecl->get_functionType()->get_parameters().front(); Type * param_one_t = InitTweak::getPointerBase( param_one->get_type() ); StructInstType * struct_one_t = dynamic_cast( param_one_t ); if ( struct_one_t && struct_one_t->get_baseStruct()->get_tagged() ) { map::iterator target = known_structs.find( struct_one_t->get_name() ); assertf( known_structs.end() != target, "Missing definition of structure." ); DeclarationWithType * ptto_field = dynamic_cast( struct_decl( target )->get_members().front() ); assertf( ptto_field, "Pointer to type object not found." ); Type * mutptr = ptto_field->get_type()->clone(); mutptr->set_const( false ); mutptr = new PointerType(Type::Qualifiers(), mutptr); funcDecl->get_statements()->push_front( new ExprStmt( noLabels, new UntypedExpr( new NameExpr( "?{}" ), std::list{ new CastExpr( new AddressExpr( new MemberExpr( ptto_field, UntypedExpr::createDeref( new VariableExpr( param_one ) ) ) ), mutptr ), new AddressExpr( new VariableExpr( type_object( target ) ) ) } ) ) ); } return funcDecl; } }; // ?{}((type_object const**)&this->tag, & ) void expand_tree_structs( std::list & translationUnit ) { PassVisitor translator; mutateAll( translationUnit, translator ); }