// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // Tables.cc -- // // Author : Andrew Beach // Created On : Mon Aug 31 11:11:00 2020 // Last Modified By : Andrew Beach // Last Modified On : Tue Sep 3 14:56:00 2020 // Update Count : 0 // #include #include #include namespace Virtual { std::string vtableTypeName( std::string const & name ) { return name + "_vtable"; } std::string instanceName( std::string const & name ) { return std::string("_") + name + "_instance"; } std::string vtableInstanceName( std::string const & name ) { return instanceName( vtableTypeName( name ) ); } bool isVTableInstanceName( std::string const & name ) { // There are some delicate length calculations here. return 17 < name.size() && '_' == name[0] && std::string("_vtable_instance") == name.substr(1, name.size() - 17); } // Fuse base polymorphic declaration and forall arguments into a new type. static StructInstType * vtableInstType( StructDecl * polyDecl, std::list< Expression * > && parameters ) { assert( parameters.size() == polyDecl->parameters.size() ); StructInstType * type = new StructInstType( Type::Qualifiers( /* Type::Const */ ), polyDecl ); type->parameters = std::move( parameters ); return type; } static ObjectDecl * makeVtableDeclaration( StructInstType * type, Initializer * init ) { std::string const & name = instanceName( type->name ); Type::StorageClasses storage = noStorageClasses; if ( nullptr == init ) { storage.is_extern = true; } return new ObjectDecl( name, storage, LinkageSpec::Cforall, nullptr, type, init ); } ObjectDecl * makeVtableForward( StructInstType * type ) { return makeVtableDeclaration( type, nullptr ); } ObjectDecl * makeVtableForward( StructDecl * polyDecl, std::list< Expression * > && parameters ) { return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) ); } ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * vobject_type, Initializer * init ) { StructDecl * vtableStruct = vtableType->baseStruct; // Build the initialization if ( nullptr == init ) { std::list< Initializer * > inits; // This is going to have to be run before the resolver to connect expressions. for ( auto field : vtableStruct->members ) { if ( std::string( "parent" ) == field->name ) { // This will not work with polymorphic state. auto oField = strict_dynamic_cast< ObjectDecl * >( field ); auto fieldType = strict_dynamic_cast< PointerType * >( oField->type ); auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base ); std::string const & parentInstance = instanceName( parentType->name ); inits.push_back( new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) ); } else if ( std::string( "size" ) == field->name ) { inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) ); } else if ( std::string( "align" ) == field->name ) { inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) ); } else { inits.push_back( new SingleInit( new NameExpr( field->name ) ) ); } } init = new ListInit( inits ); // This should initialize everything except the parent pointer, the // size-of and align-of fields. These should be inserted. } else { assert(false); } return makeVtableDeclaration( vtableType, init ); } ObjectDecl * makeVtableInstance( StructDecl * polyDecl, std::list< Expression * > && parameters, Type * vobject, Initializer * init ) { return makeVtableInstance( vtableInstType( polyDecl, std::move( parameters ) ), vobject, init ); } }