Ignore:
Timestamp:
Aug 11, 2020, 4:40:15 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
0d070ca
Parents:
07d867b (diff), 129674b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into new-ast

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    r07d867b r22f94a4  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Aug  2 14:59:00 2017
    13 // Update Count     : 1
     12// Last Modified On : Fri Jul 31 10:29:00 2020
     13// Update Count     : 4
    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...
    2120#include <string>                  // for string, allocator, operator==, ope...
    22 #include <utility>                 // for pair
    2321
    2422#include "Common/PassVisitor.h"    // for PassVisitor
     23#include "Common/ScopedMap.h"      // for ScopedMap
    2524#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...
     
    3131
    3232namespace Virtual {
     33
     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        };
    3367
    3468        /* Currently virtual depends on the rather brittle name matching between
     
    3973         */
    4074
     75        namespace {
     76
    4177        std::string get_vtable_name( std::string const & name ) {
    4278                return name + "_vtable";
     
    5389        std::string get_vtable_inst_name_root( std::string const & name ) {
    5490                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" );
    5991        }
    6092
     
    6496        }
    6597
     98        } // namespace
     99
    66100        class VirtualCastCore {
    67         std::map<std::string, ObjectDecl *> vtable_instances;
    68         FunctionDecl *vcast_decl;
    69         StructDecl *pvt_decl;
    70 
    71101                Type * pointer_to_pvt(int level_of_indirection) {
    72102                        Type * type = new StructInstType(
     
    80110        public:
    81111                VirtualCastCore() :
    82                         vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
     112                        indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
    83113                {}
    84114
     
    88118
    89119                Expression * postmutate( VirtualCastExpr * castExpr );
     120
     121                VirtualTableMap indexer;
     122        private:
     123                FunctionDecl *vcast_decl;
     124                StructDecl *pvt_decl;
    90125        };
    91126
     
    107142        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    108143                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    109                         vtable_instances[objectDecl->get_name()] = objectDecl;
    110                 }
    111         }
     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                        }
     150                }
     151        }
     152
     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
    112223
    113224        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    114                 assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
     225                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    115226
    116227                assert( vcast_decl );
    117228                assert( pvt_decl );
    118229
    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." );
    138                 }
    139                 ObjectDecl * table = found->second;
     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." );
     235                }
    140236
    141237                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                                 //      ),
    149238                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    150239                                        new CastExpr(
     
    163252                castExpr->set_result( nullptr );
    164253                delete castExpr;
     254                delete vtable_type;
    165255                return result;
    166256        }
Note: See TracChangeset for help on using the changeset viewer.