Changeset ecfd758 for src/Virtual


Ignore:
Timestamp:
Apr 9, 2021, 2:11:43 PM (8 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
b91bfde
Parents:
e07b589
Message:

Major exception update, seperating type-ids from virtual tables. The major interface changes are done. There is a regression of ?Cancelled(T) to Some?Cancelled. There is some bits of code for the new verion of the ?Cancelled(T) interface already there. Not connected yet but I just reached the limit of what I wanted to do in one commit and then spent over a day cleaning up, so it will replace Some?Cancelled in a future commit.

Location:
src/Virtual
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    re07b589 recfd758  
    3232namespace Virtual {
    3333
     34static bool is_prefix( const std::string & prefix, const std::string& entire ) {
     35        size_t const p_size = prefix.size();
     36        return (p_size < entire.size() && prefix == entire.substr(0, p_size));
     37}
     38
     39static bool is_type_id_object( const ObjectDecl * objectDecl ) {
     40        const std::string & objectName = objectDecl->name;
     41        return is_prefix( "__cfatid_", objectName );
     42}
     43
    3444        // Indented until the new ast code gets added.
    3545
     
    6676        };
    6777
    68         /* Currently virtual depends on the rather brittle name matching between
    69          * a (strict/explicate) virtual type, its vtable type and the vtable
    70          * instance.
    71          * A stronger implementation, would probably keep track of those triads
    72          * and use that information to create better error messages.
    73          */
    74 
    75         namespace {
    76 
    77         std::string get_vtable_name( std::string const & name ) {
    78                 return name + "_vtable";
    79         }
    80 
    81         std::string get_vtable_inst_name( std::string const & name ) {
    82                 return std::string("_") + get_vtable_name( name ) + "_instance";
    83         }
    84 
    85         std::string get_vtable_name_root( std::string const & name ) {
    86                 return name.substr(0, name.size() - 7 );
    87         }
    88 
    89         std::string get_vtable_inst_name_root( std::string const & name ) {
    90                 return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
    91         }
    92 
    93         bool is_vtable_inst_name( std::string const & name ) {
    94                 return 17 < name.size() &&
    95                         name == get_vtable_inst_name( get_vtable_inst_name_root( name ) );
    96         }
    97 
    98         } // namespace
    99 
    10078        class VirtualCastCore {
    10179                Type * pointer_to_pvt(int level_of_indirection) {
     
    141119
    142120        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    143                 if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    144                         if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) {
    145                                 std::string msg = "Repeated instance of virtual table, original found at: ";
    146                                 msg += existing->location.filename;
    147                                 msg += ":" + toString( existing->location.first_line );
    148                                 SemanticError( objectDecl->location, msg );
    149                         }
     121                if ( is_type_id_object( objectDecl ) ) {
     122                        // Multiple definitions should be fine because of linkonce.
     123                        indexer.insert( objectDecl );
    150124                }
    151125        }
     
    170144        }
    171145
    172         /// Get the virtual table type used in a virtual cast.
    173         Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
    174                 const Type * objectType;
    175                 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
    176                         objectType = target->base;
    177                 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
    178                         objectType = target->base;
     146        /// Get the base type from a pointer or reference.
     147        const Type * getBaseType( const Type * type ) {
     148                if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
     149                        return target->base;
     150                } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
     151                        return target->base;
    179152                } else {
    180                         castError( castExpr, "Virtual cast type must be a pointer or reference type." );
    181                 }
    182                 assert( objectType );
    183 
    184                 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
    185                 if ( nullptr == structType ) {
    186                         castError( castExpr, "Virtual cast type must refer to a structure type." );
    187                 }
    188                 const StructDecl * structDecl = structType->baseStruct;
    189                 assert( structDecl );
    190 
    191                 const ObjectDecl * fieldDecl = nullptr;
    192                 if ( 0 < structDecl->members.size() ) {
    193                         const Declaration * memberDecl = structDecl->members.front();
     153                        return nullptr;
     154                }
     155        }
     156
     157        /* Attempt to follow the "head" field of the structure to get the...
     158         * Returns nullptr on error, otherwise owner must free returned node.
     159         */
     160        StructInstType * followHeadPointerType(
     161                        const StructInstType * oldType,
     162                        const std::string& fieldName,
     163                        const CodeLocation& errorLocation ) {
     164
     165                // First section of the function is all about trying to fill this variable in.
     166                StructInstType * newType = nullptr;
     167                {
     168                        const StructDecl * oldDecl = oldType->baseStruct;
     169                        assert( oldDecl );
     170
     171                        // Helper function for throwing semantic errors.
     172                        auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
     173                                const std::string& context = "While following head pointer of " +
     174                                        oldDecl->name + " named '" + fieldName + "': ";
     175                                SemanticError( errorLocation, context + message );
     176                        };
     177
     178                        if ( oldDecl->members.empty() ) {
     179                                throwError( "Type has no fields." );
     180                        }
     181                        const Declaration * memberDecl = oldDecl->members.front();
    194182                        assert( memberDecl );
    195                         fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    196                         if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
    197                                 fieldDecl = nullptr;
    198                         }
    199                 }
    200                 if ( nullptr == fieldDecl ) {
    201                         castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
    202                 }
    203                 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
    204                 if ( nullptr == fieldType ) {
    205                         castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
    206                 }
    207                 assert( fieldType->base );
    208                 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
    209                 assert( virtualStructType );
    210 
    211                 // Here is the type, but if it is polymorphic it will have lost information.
    212                 // (Always a clone so that it may always be deleted.)
    213                 StructInstType * virtualType = virtualStructType->clone();
    214                 if ( ! structType->parameters.empty() ) {
    215                         deleteAll( virtualType->parameters );
    216                         virtualType->parameters.clear();
    217                         cloneAll( structType->parameters, virtualType->parameters );
    218                 }
    219                 return virtualType;
     183                        const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     184                        assert( fieldDecl );
     185                        if ( fieldName != fieldDecl->name ) {
     186                                throwError( "Head field did not have expected name." );
     187                        }
     188
     189                        const Type * fieldType = fieldDecl->type;
     190                        if ( nullptr == fieldType ) {
     191                                throwError( "Could not get head field." );
     192                        }
     193                        const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
     194                        if ( nullptr == ptrType ) {
     195                                throwError( "First field is not a pointer type." );
     196                        }
     197                        assert( ptrType->base );
     198                        newType = dynamic_cast<StructInstType *>( ptrType->base );
     199                        if ( nullptr == newType ) {
     200                                throwError( "First field does not point to a structure type." );
     201                        }
     202                }
     203
     204                // Now we can look into copying it.
     205                newType = newType->clone();
     206                if ( ! oldType->parameters.empty() ) {
     207                        deleteAll( newType->parameters );
     208                        newType->parameters.clear();
     209                        cloneAll( oldType->parameters, newType->parameters );
     210                }
     211                return newType;
     212        }
     213
     214        /// Get the type-id type from a virtual type.
     215        StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
     216                const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
     217                if ( nullptr == typeInst ) {
     218                        return nullptr;
     219                }
     220                StructInstType * tableInst =
     221                        followHeadPointerType( typeInst, "virtual_table", errorLocation );
     222                if ( nullptr == tableInst ) {
     223                        return nullptr;
     224                }
     225                StructInstType * typeIdInst =
     226                        followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
     227                delete tableInst;
     228                return typeIdInst;
    220229        }
    221230
     
    228237                assert( pvt_decl );
    229238
    230                 const Type * vtable_type = getVirtualTableType( castExpr );
    231                 ObjectDecl * table = indexer.lookup( vtable_type );
    232                 if ( nullptr == table ) {
    233                         SemanticError( castLocation( castExpr ),
    234                                 "Could not find virtual table instance." );
     239                const Type * base_type = getBaseType( castExpr->result );
     240                if ( nullptr == base_type ) {
     241                        castError( castExpr, "Virtual cast target must be a pointer or reference type." );
     242                }
     243                const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
     244                if ( nullptr == type_id_type ) {
     245                        castError( castExpr, "Ill formed virtual cast target type." );
     246                }
     247                ObjectDecl * type_id = indexer.lookup( type_id_type );
     248                delete type_id_type;
     249                if ( nullptr == type_id ) {
     250                        castError( castExpr, "Virtual cast does not target a virtual type." );
    235251                }
    236252
     
    238254                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    239255                                        new CastExpr(
    240                                                 new AddressExpr( new VariableExpr( table ) ),
     256                                                new AddressExpr( new VariableExpr( type_id ) ),
    241257                                                pointer_to_pvt(1)
    242258                                        ),
     
    252268                castExpr->set_result( nullptr );
    253269                delete castExpr;
    254                 delete vtable_type;
    255270                return result;
    256271        }
  • src/Virtual/Tables.cc

    re07b589 recfd758  
    1010// Created On       : Mon Aug 31 11:11:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep  3 14:56:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Thr Apr  8 15:51:00 2021
     13// Update Count     : 1
    1414//
    1515
     
    2222namespace Virtual {
    2323
     24std::string typeIdType( std::string const & type_name ) {
     25        return "__cfatid_struct_" + type_name;
     26}
     27
     28std::string typeIdName( std::string const & type_name ) {
     29        return "__cfatid_" + type_name;
     30}
     31
     32static std::string typeIdTypeToInstance( std::string const & type_name ) {
     33        return typeIdName(type_name.substr(16));
     34}
     35
    2436std::string vtableTypeName( std::string const & name ) {
    2537        return name + "_vtable";
     38}
     39
     40std::string baseTypeName( std::string const & vtable_type_name ) {
     41        return vtable_type_name.substr(0, vtable_type_name.size() - 7);
    2642}
    2743
     
    8197                                inits.push_back(
    8298                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
     99                        } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
     100                                std::string const & baseType = baseTypeName( vtableType->name );
     101                                std::string const & typeId = typeIdName( baseType );
     102                                inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
    83103                        } else if ( std::string( "size" ) == field->name ) {
    84104                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
     
    147167}
    148168
    149 }
     169ObjectDecl * makeTypeIdForward() {
     170        return nullptr;
     171}
     172
     173Attribute * linkonce( const std::string & subsection ) {
     174        const std::string section = "\".gnu.linkonce." + subsection + "\"";
     175        // Adjust for terminator and quotes.
     176        size_t str_size = section.size() + 1 - 2;
     177        return new Attribute( "section", {
     178                new ConstantExpr( Constant(
     179                        new ArrayType(
     180                                noQualifiers,
     181                                new BasicType( noQualifiers, BasicType::Char ),
     182                                new ConstantExpr( Constant::from_ulong( str_size ) ),
     183                                false, false ),
     184                        section,
     185                        std::nullopt
     186                ) ),
     187        } );
     188}
     189
     190ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
     191        assert( typeIdType );
     192        StructInstType * type = typeIdType->clone();
     193        type->tq.is_const = true;
     194        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
     195        return new ObjectDecl(
     196                typeid_name,
     197                noStorageClasses,
     198                LinkageSpec::Cforall,
     199                /* bitfieldWidth */ nullptr,
     200                type,
     201                new ListInit( { new SingleInit(
     202                        new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
     203                        ) } ),
     204                { linkonce( typeid_name ) },
     205                noFuncSpecifiers
     206        );
     207}
     208
     209}
  • src/Virtual/Tables.h

    re07b589 recfd758  
    1010// Created On       : Mon Aug 31 11:07:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep  1 14:29:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Thr Apr  8 15:55:00 2021
     13// Update Count     : 1
    1414//
    1515
     
    2222namespace Virtual {
    2323
     24std::string typeIdType( std::string const & type_name );
     25std::string typeIdName( std::string const & type_name );
    2426std::string vtableTypeName( std::string const & type_name );
    2527std::string instanceName( std::string const & vtable_name );
     
    5052 */
    5153
     54ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
     55/* Build an instance of the type-id from the type of the type-id.
     56 * TODO: Should take the parent type. Currently locked to the exception_t.
     57 */
     58
    5259}
Note: See TracChangeset for help on using the changeset viewer.