Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (8 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode? and clean-up.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    r790d835 rc6b4432  
    2424#include "AST/Expr.hpp"
    2525#include "AST/Pass.hpp"
    26 #include "Common/PassVisitor.h"    // for PassVisitor
    2726#include "Common/ScopedMap.h"      // for ScopedMap
    2827#include "Common/SemanticError.h"  // for SemanticError
    2928#include "SymTab/Mangler.h"        // for mangleType
    30 #include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    31 #include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
    32 #include "SynTree/Mutator.h"       // for mutateAll
    33 #include "SynTree/Type.h"          // for Type, PointerType, StructInstType
    34 #include "SynTree/Visitor.h"       // for acceptAll
    3529
    3630namespace Virtual {
     
    4337}
    4438
    45 bool is_type_id_object( const ObjectDecl * objectDecl ) {
    46         const std::string & objectName = objectDecl->name;
    47         return is_prefix( "__cfatid_", objectName );
    48 }
    49 
    5039bool is_type_id_object( const ast::ObjectDecl * decl ) {
    5140        return is_prefix( "__cfatid_", decl->name );
     
    5544
    5645        /// Maps virtual table types the instance for that type.
    57         class VirtualTableMap final {
    58                 ScopedMap<std::string, ObjectDecl *> vtable_instances;
    59         public:
    60                 void enterScope() {
    61                         vtable_instances.beginScope();
    62                 }
    63                 void leaveScope() {
    64                         vtable_instances.endScope();
    65                 }
    66 
    67                 ObjectDecl * insert( ObjectDecl * vtableDecl ) {
    68                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
    69                         ObjectDecl *& value = vtable_instances[ mangledName ];
    70                         if ( value ) {
    71                                 if ( vtableDecl->storageClasses.is_extern ) {
    72                                         return nullptr;
    73                                 } else if ( ! value->storageClasses.is_extern ) {
    74                                         return value;
    75                                 }
    76                         }
    77                         value = vtableDecl;
    78                         return nullptr;
    79                 }
    80 
    81                 ObjectDecl * lookup( const Type * vtableType ) {
    82                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
    83                         const auto it = vtable_instances.find( mangledName );
    84                         return ( vtable_instances.end() == it ) ? nullptr : it->second;
    85                 }
    86         };
    87 
    88         class VirtualCastCore {
    89                 CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) {
    90                         Type * type = new StructInstType(
    91                                 Type::Qualifiers( Type::Const ), pvt_decl );
    92                         for (int i = 0 ; i < level_of_indirection ; ++i) {
    93                                 type = new PointerType( noQualifiers, type );
    94                         }
    95                         return new CastExpr( expr, type );
    96                 }
    97 
    98         public:
    99                 VirtualCastCore() :
    100                         indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
    101                 {}
    102 
    103                 void premutate( FunctionDecl * functionDecl );
    104                 void premutate( StructDecl * structDecl );
    105                 void premutate( ObjectDecl * objectDecl );
    106 
    107                 Expression * postmutate( VirtualCastExpr * castExpr );
    108 
    109                 VirtualTableMap indexer;
    110         private:
    111                 FunctionDecl *vcast_decl;
    112                 StructDecl *pvt_decl;
    113         };
    114 
    115         void VirtualCastCore::premutate( FunctionDecl * functionDecl ) {
    116                 if ( (! vcast_decl) &&
    117                      functionDecl->get_name() == "__cfavir_virtual_cast" ) {
    118                         vcast_decl = functionDecl;
    119                 }
    120         }
    121 
    122         void VirtualCastCore::premutate( StructDecl * structDecl ) {
    123                 if ( pvt_decl || ! structDecl->has_body() ) {
    124                         return;
    125                 } else if ( structDecl->get_name() == "__cfavir_type_info" ) {
    126                         pvt_decl = structDecl;
    127                 }
    128         }
    129 
    130         void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    131                 if ( is_type_id_object( objectDecl ) ) {
    132                         // Multiple definitions should be fine because of linkonce.
    133                         indexer.insert( objectDecl );
    134                 }
    135         }
    136 
    137         /// Better error locations for generated casts.
    138         CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
    139                 if ( castExpr->location.isSet() ) {
    140                         return castExpr->location;
    141                 } else if ( castExpr->arg->location.isSet() ) {
    142                         return castExpr->arg->location;
    143                 } else if ( castExpr->result->location.isSet() ) {
    144                         return castExpr->result->location;
    145                 } else {
    146                         return CodeLocation();
    147                 }
    148         }
    149 
    150         [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
    151                 SemanticError( castLocation( castExpr ), message );
    152         }
    153 
    154         /// Get the base type from a pointer or reference.
    155         const Type * getBaseType( const Type * type ) {
    156                 if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
    157                         return target->base;
    158                 } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
    159                         return target->base;
    160                 } else {
    161                         return nullptr;
    162                 }
    163         }
    164 
    165         /* Attempt to follow the "head" field of the structure to get the...
    166          * Returns nullptr on error, otherwise owner must free returned node.
    167          */
    168         StructInstType * followHeadPointerType(
    169                         const StructInstType * oldType,
    170                         const std::string& fieldName,
    171                         const CodeLocation& errorLocation ) {
    172 
    173                 // First section of the function is all about trying to fill this variable in.
    174                 StructInstType * newType = nullptr;
    175                 {
    176                         const StructDecl * oldDecl = oldType->baseStruct;
    177                         assert( oldDecl );
    178 
    179                         // Helper function for throwing semantic errors.
    180                         auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
    181                                 const std::string& context = "While following head pointer of " +
    182                                         oldDecl->name + " named '" + fieldName + "': ";
    183                                 SemanticError( errorLocation, context + message );
    184                         };
    185 
    186                         if ( oldDecl->members.empty() ) {
    187                                 throwError( "Type has no fields." );
    188                         }
    189                         const Declaration * memberDecl = oldDecl->members.front();
    190                         assert( memberDecl );
    191                         const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    192                         assert( fieldDecl );
    193                         if ( fieldName != fieldDecl->name ) {
    194                                 throwError( "Head field did not have expected name." );
    195                         }
    196 
    197                         const Type * fieldType = fieldDecl->type;
    198                         if ( nullptr == fieldType ) {
    199                                 throwError( "Could not get head field." );
    200                         }
    201                         const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
    202                         if ( nullptr == ptrType ) {
    203                                 throwError( "First field is not a pointer type." );
    204                         }
    205                         assert( ptrType->base );
    206                         newType = dynamic_cast<StructInstType *>( ptrType->base );
    207                         if ( nullptr == newType ) {
    208                                 throwError( "First field does not point to a structure type." );
    209                         }
    210                 }
    211 
    212                 // Now we can look into copying it.
    213                 newType = newType->clone();
    214                 if ( ! oldType->parameters.empty() ) {
    215                         deleteAll( newType->parameters );
    216                         newType->parameters.clear();
    217                         cloneAll( oldType->parameters, newType->parameters );
    218                 }
    219                 return newType;
    220         }
    221 
    222         /// Get the type-id type from a virtual type.
    223         StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
    224                 const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
    225                 if ( nullptr == typeInst ) {
    226                         return nullptr;
    227                 }
    228                 StructInstType * tableInst =
    229                         followHeadPointerType( typeInst, "virtual_table", errorLocation );
    230                 if ( nullptr == tableInst ) {
    231                         return nullptr;
    232                 }
    233                 StructInstType * typeIdInst =
    234                         followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
    235                 delete tableInst;
    236                 return typeIdInst;
    237         }
    238 
    239         Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    240                 assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    241 
    242                 assert( vcast_decl );
    243                 assert( pvt_decl );
    244 
    245                 const Type * base_type = getBaseType( castExpr->result );
    246                 if ( nullptr == base_type ) {
    247                         castError( castExpr, "Virtual cast target must be a pointer or reference type." );
    248                 }
    249                 const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
    250                 if ( nullptr == type_id_type ) {
    251                         castError( castExpr, "Ill formed virtual cast target type." );
    252                 }
    253                 ObjectDecl * type_id = indexer.lookup( type_id_type );
    254                 delete type_id_type;
    255                 if ( nullptr == type_id ) {
    256                         castError( castExpr, "Virtual cast does not target a virtual type." );
    257                 }
    258 
    259                 Expression * result = new CastExpr(
    260                         new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    261                                 cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ),
    262                                 cast_to_type_id( castExpr->get_arg(), 2 ),
    263                         } ),
    264                         castExpr->get_result()->clone()
    265                 );
    266 
    267                 castExpr->set_arg( nullptr );
    268                 castExpr->set_result( nullptr );
    269                 delete castExpr;
    270                 return result;
    271         }
    27246
    27347/// Better error locations for generated casts.
     
    494268} // namespace
    495269
    496 void expandCasts( std::list< Declaration * > & translationUnit ) {
    497         PassVisitor<VirtualCastCore> translator;
    498         mutateAll( translationUnit, translator );
    499 }
    500 
    501270void expandCasts( ast::TranslationUnit & translationUnit ) {
    502271        ast::Pass<ExpandCastsCore>::run( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.