Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    r6dba8755 r8e6214f  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 31 10:29:00 2020
    13 // Update Count     : 4
     12// Last Modified On : Tus Aug  2 14:59:00 2017
     13// Update Count     : 1
    1414//
    1515
     
    1818#include <cassert>                 // for assert, assertf
    1919#include <iterator>                // for back_inserter, inserter
     20#include <map>                     // for map, _Rb_tree_iterator, map<>::ite...
    2021#include <string>                  // for string, allocator, operator==, ope...
     22#include <utility>                 // for pair
    2123
    2224#include "Common/PassVisitor.h"    // for PassVisitor
    23 #include "Common/ScopedMap.h"      // for ScopedMap
    2425#include "Common/SemanticError.h"  // for SemanticError
    25 #include "SymTab/Mangler.h"        // for mangleType
    2626#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2727#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3232namespace Virtual {
    3333
    34         // Indented until the new ast code gets added.
    35 
    36         /// Maps virtual table types the instance for that type.
    37         class VirtualTableMap final {
    38                 ScopedMap<std::string, ObjectDecl *> vtable_instances;
    39         public:
    40                 void enterScope() {
    41                         vtable_instances.beginScope();
    42                 }
    43                 void leaveScope() {
    44                         vtable_instances.endScope();
    45                 }
    46 
    47                 ObjectDecl * insert( ObjectDecl * vtableDecl ) {
    48                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
    49                         ObjectDecl *& value = vtable_instances[ mangledName ];
    50                         if ( value ) {
    51                                 if ( vtableDecl->storageClasses.is_extern ) {
    52                                         return nullptr;
    53                                 } else if ( ! value->storageClasses.is_extern ) {
    54                                         return value;
    55                                 }
    56                         }
    57                         value = vtableDecl;
    58                         return nullptr;
    59                 }
    60 
    61                 ObjectDecl * lookup( const Type * vtableType ) {
    62                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
    63                         const auto it = vtable_instances.find( mangledName );
    64                         return ( vtable_instances.end() == it ) ? nullptr : it->second;
    65                 }
    66         };
    67 
    6834        /* Currently virtual depends on the rather brittle name matching between
    6935         * a (strict/explicate) virtual type, its vtable type and the vtable
     
    7238         * and use that information to create better error messages.
    7339         */
    74 
    75         namespace {
    7640
    7741        std::string get_vtable_name( std::string const & name ) {
     
    9155        }
    9256
     57        bool is_vtable_name( std::string const & name ) {
     58                return (name.substr( name.size() - 7 ) == "_vtable" );
     59        }
     60
    9361        bool is_vtable_inst_name( std::string const & name ) {
    9462                return 17 < name.size() &&
     
    9664        }
    9765
    98         } // namespace
     66        class VirtualCastCore {
     67        std::map<std::string, ObjectDecl *> vtable_instances;
     68        FunctionDecl *vcast_decl;
     69        StructDecl *pvt_decl;
    9970
    100         class VirtualCastCore {
    10171                Type * pointer_to_pvt(int level_of_indirection) {
    10272                        Type * type = new StructInstType(
     
    11080        public:
    11181                VirtualCastCore() :
    112                         indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
     82                        vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
    11383                {}
    11484
     
    11888
    11989                Expression * postmutate( VirtualCastExpr * castExpr );
    120 
    121                 VirtualTableMap indexer;
    122         private:
    123                 FunctionDecl *vcast_decl;
    124                 StructDecl *pvt_decl;
    12590        };
    12691
     
    142107        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    143108                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                         }
     109                        vtable_instances[objectDecl->get_name()] = objectDecl;
    150110                }
    151111        }
    152112
    153         namespace {
    154 
    155         /// Better error locations for generated casts.
    156         CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
    157                 if ( castExpr->location.isSet() ) {
    158                         return castExpr->location;
    159                 } else if ( castExpr->arg->location.isSet() ) {
    160                         return castExpr->arg->location;
    161                 } else if ( castExpr->result->location.isSet() ) {
    162                         return castExpr->result->location;
    163                 } else {
    164                         return CodeLocation();
    165                 }
    166         }
    167 
    168         [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
    169                 SemanticError( castLocation( castExpr ), message );
    170         }
    171 
    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;
    179                 } 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();
    194                         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;
    220         }
    221 
    222         } // namespace
    223 
    224113        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    225                 assertf( castExpr->result, "Virtual Cast target not found before expansion." );
     114                assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
    226115
    227116                assert( vcast_decl );
    228117                assert( pvt_decl );
    229118
    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." );
     119                // May only cast to a pointer or reference type.
     120                // A earlier validation should give a syntax error, this is
     121                // just to make sure errors don't creep during translation.
     122                // Move to helper with more detailed error messages.
     123                PointerType * target_type =
     124                        dynamic_cast<PointerType *>( castExpr->get_result() );
     125                assert( target_type );
     126
     127                StructInstType * target_struct =
     128                        dynamic_cast<StructInstType *>( target_type->get_base() );
     129                assert( target_struct );
     130
     131                StructDecl * target_decl = target_struct->get_baseStruct();
     132
     133                std::map<std::string, ObjectDecl *>::iterator found =
     134                        vtable_instances.find(
     135                                get_vtable_inst_name( target_decl->get_name() ) );
     136                if ( vtable_instances.end() == found ) {
     137                        assertf( false, "virtual table instance not found." );
    235138                }
     139                ObjectDecl * table = found->second;
    236140
    237141                Expression * result = new CastExpr(
     142                        //new ApplicationExpr(
     143                                //new AddressExpr( new VariableExpr( vcast_decl ) ),
     144                                //new CastExpr( new VariableExpr( vcast_decl ),
     145                                //      new PointerType( noQualifiers,
     146                                //              vcast_decl->get_type()->clone()
     147                                //              )
     148                                //      ),
    238149                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    239150                                        new CastExpr(
     
    252163                castExpr->set_result( nullptr );
    253164                delete castExpr;
    254                 delete vtable_type;
    255165                return result;
    256166        }
Note: See TracChangeset for help on using the changeset viewer.