Changeset f19fbbc for src/Virtual


Ignore:
Timestamp:
Jul 22, 2020, 11:24:33 AM (4 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
54eb5ebd
Parents:
4a32319
Message:

Fixed the virtual system so it can handle in polymorphic virtual tables at least as well as the resolver does.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    r4a32319 rf19fbbc  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 26 14:37:00 2020
    13 // Update Count     : 2
     12// Last Modified On : Tue Jul 22 10:04:00 2020
     13// Update Count     : 3
    1414//
    1515
     
    2424#include "Common/PassVisitor.h"    // for PassVisitor
    2525#include "Common/SemanticError.h"  // for SemanticError
     26#include "SymTab/Mangler.h"        // for mangleType
    2627#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2728#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3132
    3233namespace Virtual {
     34
     35        // Indented until the new ast code gets added.
     36
     37        /// Maps virtual table types the instance for that type.
     38        class VirtualTableMap final {
     39                std::unordered_map<std::string, ObjectDecl *> vtable_instances;
     40        public:
     41                ObjectDecl * insert( ObjectDecl * vtableDecl ) {
     42                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
     43                        ObjectDecl *& value = vtable_instances[ mangledName ];
     44                        if ( value ) {
     45                                if ( vtableDecl->storageClasses.is_extern ) {
     46                                        return nullptr;
     47                                } else if ( ! value->storageClasses.is_extern ) {
     48                                        return value;
     49                                }
     50                        }
     51                        value = vtableDecl;
     52                        return nullptr;
     53                }
     54
     55                ObjectDecl * lookup( const Type * vtableType ) {
     56                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
     57                        const auto it = vtable_instances.find( mangledName );
     58                        return ( vtable_instances.end() == it ) ? nullptr : it->second;
     59                }
     60        };
    3361
    3462        /* Currently virtual depends on the rather brittle name matching between
     
    3967         */
    4068
     69        namespace {
     70
    4171        std::string get_vtable_name( std::string const & name ) {
    4272                return name + "_vtable";
     
    5383        std::string get_vtable_inst_name_root( std::string const & name ) {
    5484                return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
    55         }
    56 
    57         bool is_vtable_name( std::string const & name ) {
    58                 return (name.substr( name.size() - 7 ) == "_vtable" );
    5985        }
    6086
     
    6490        }
    6591
     92        } // namespace
     93
    6694        class VirtualCastCore {
    67         std::map<std::string, ObjectDecl *> vtable_instances;
    68         FunctionDecl *vcast_decl;
    69         StructDecl *pvt_decl;
     95                VirtualTableMap vtable_instances;
     96                FunctionDecl *vcast_decl;
     97                StructDecl *pvt_decl;
    7098
    7199                Type * pointer_to_pvt(int level_of_indirection) {
     
    107135        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    108136                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    109                         vtable_instances[objectDecl->get_name()] = objectDecl;
    110                 }
    111         }
    112 
    113         // Better error locations for generated casts.
    114         static CodeLocation castLocation( VirtualCastExpr * castExpr ) {
     137                        if ( ObjectDecl * existing = vtable_instances.insert( objectDecl ) ) {
     138                                std::string msg = "Repeated instance of virtual table, original found at: ";
     139                                msg += existing->location.filename;
     140                                msg += ":" + toString( existing->location.first_line );
     141                                SemanticError( objectDecl->location, msg );
     142                        }
     143                }
     144        }
     145
     146        namespace {
     147
     148        /// Better error locations for generated casts.
     149        CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
    115150                if ( castExpr->location.isSet() ) {
    116151                        return castExpr->location;
     
    124159        }
    125160
     161        [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
     162                SemanticError( castLocation( castExpr ), message );
     163        }
     164
     165        /// Get the virtual table type used in a virtual cast.
     166        Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
     167                const Type * objectType;
     168                if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
     169                        objectType = target->base;
     170                } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
     171                        objectType = target->base;
     172                } else {
     173                        castError( castExpr, "Virtual cast type must be a pointer or reference type." );
     174                }
     175                assert( objectType );
     176
     177                const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
     178                if ( nullptr == structType ) {
     179                        castError( castExpr, "Virtual cast type must refer to a structure type." );
     180                }
     181                const StructDecl * structDecl = structType->baseStruct;
     182                assert( structDecl );
     183
     184                const ObjectDecl * fieldDecl = nullptr;
     185                if ( 0 < structDecl->members.size() ) {
     186                        const Declaration * memberDecl = structDecl->members.front();
     187                        assert( memberDecl );
     188                        fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     189                        if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
     190                                fieldDecl = nullptr;
     191                        }
     192                }
     193                if ( nullptr == fieldDecl ) {
     194                        castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
     195                }
     196                const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
     197                if ( nullptr == fieldType ) {
     198                        castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
     199                }
     200                assert( fieldType->base );
     201                auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
     202                assert( virtualStructType );
     203
     204                // Here is the type, but if it is polymorphic it will have lost information.
     205                // (Always a clone so that it may always be deleted.)
     206                StructInstType * virtualType = virtualStructType->clone();
     207                if ( ! structType->parameters.empty() ) {
     208                        deleteAll( virtualType->parameters );
     209                        virtualType->parameters.clear();
     210                        cloneAll( structType->parameters, virtualType->parameters );
     211                }
     212                return virtualType;
     213        }
     214
     215        } // namespace
     216
    126217        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    127                 assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
     218                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    128219
    129220                assert( vcast_decl );
    130221                assert( pvt_decl );
    131222
    132                 // Get the base type of the pointer/reference.
    133                 Type * base;
    134                 Type * result_type = castExpr->result;
    135                 if ( PointerType * target = dynamic_cast<PointerType *>( result_type ) ) {
    136                         base = target->base;
    137                 } else if ( ReferenceType * target = dynamic_cast<ReferenceType *>( result_type ) ) {
    138                         base = target->base;
    139                 } else {
     223                const Type * vtable_type = getVirtualTableType( castExpr );
     224                ObjectDecl * table = vtable_instances.lookup( vtable_type );
     225                if ( nullptr == table ) {
    140226                        SemanticError( castLocation( castExpr ),
    141                                 "Virtual cast type must be a pointer or reference type." );
    142                 }
    143 
    144                 StructInstType * target_struct = dynamic_cast<StructInstType *>( base );
    145                 if ( nullptr == target_struct ) {
    146                         SemanticError( castLocation( castExpr ),
    147                                 "Virtual cast type must refer to a structure type." );
    148                 }
    149                 StructDecl * target_decl = target_struct->get_baseStruct();
    150 
    151                 std::map<std::string, ObjectDecl *>::iterator found =
    152                         vtable_instances.find( get_vtable_inst_name( target_decl->get_name() ) );
    153                 if ( vtable_instances.end() == found ) {
    154                         SemanticError( castLocation( castExpr ),
    155                                 "Virtual cast type does not have a virtual table instance." );
    156                 }
    157                 ObjectDecl * table = found->second;
     227                                "Could not find virtual table instance." );
     228                }
    158229
    159230                Expression * result = new CastExpr(
     
    174245                castExpr->set_result( nullptr );
    175246                delete castExpr;
     247                delete vtable_type;
    176248                return result;
    177249        }
Note: See TracChangeset for help on using the changeset viewer.