// // 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 #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); } 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 ) { assert( type ); return makeVtableDeclaration( type, nullptr ); } ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * objectType, Initializer * init ) { assert( vtableType ); assert( objectType ); 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( objectType->clone() ) ) ); } else if ( std::string( "align" ) == field->name ) { inits.push_back( new SingleInit( new AlignofExpr( objectType->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 ); } namespace { std::string const functionName = "get_exception_vtable"; } FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType ) { assert( vtableType ); assert( exceptType ); FunctionType * type = new FunctionType( noQualifiers, false ); vtableType->tq.is_const = true; type->returnVals.push_back( new ObjectDecl( "_retvalue", noStorageClasses, LinkageSpec::Cforall, nullptr, new ReferenceType( noQualifiers, vtableType ), nullptr, { new Attribute("unused") } ) ); type->parameters.push_back( new ObjectDecl( "__unused", noStorageClasses, LinkageSpec::Cforall, nullptr, new PointerType( noQualifiers, exceptType ), nullptr, { new Attribute("unused") } ) ); return new FunctionDecl( functionName, noStorageClasses, LinkageSpec::Cforall, type, nullptr ); } FunctionDecl * makeGetExceptionFunction( ObjectDecl * vtableInstance, Type * exceptType ) { assert( vtableInstance ); assert( exceptType ); FunctionDecl * func = makeGetExceptionForward( vtableInstance->type->clone(), exceptType ); func->statements = new CompoundStmt( { new ReturnStmt( new VariableExpr( vtableInstance ) ), } ); return func; } }