Changeset c6b4432 for src/Virtual


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

Remove BaseSyntaxNode and clean-up.

Location:
src/Virtual
Files:
3 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 );
  • src/Virtual/Tables.cc

    r790d835 rc6b4432  
    2121#include "AST/Stmt.hpp"
    2222#include "AST/Type.hpp"
    23 #include <SynTree/Attribute.h>
    24 #include <SynTree/Declaration.h>
    25 #include <SynTree/Expression.h>
    26 #include <SynTree/Statement.h>
    27 #include <SynTree/Type.h>
    2823
    2924namespace Virtual {
     
    6560        return 17 < name.size() && '_' == name[0] &&
    6661                std::string("_vtable_instance") == name.substr(1, name.size() - 17);
    67 }
    68 
    69 static ObjectDecl * makeVtableDeclaration(
    70                 std::string const & name,
    71                 StructInstType * type, Initializer * init ) {
    72         Type::StorageClasses storage = noStorageClasses;
    73         if ( nullptr == init ) {
    74                 storage.is_extern = true;
    75         }
    76         return new ObjectDecl(
    77                 name,
    78                 storage,
    79                 LinkageSpec::Cforall,
    80                 nullptr,
    81                 type,
    82                 init
    83         );
    8462}
    8563
     
    10179}
    10280
    103 ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
    104         assert( type );
    105         return makeVtableDeclaration( name, type, nullptr );
    106 }
    107 
    10881ast::ObjectDecl * makeVtableForward(
    10982                CodeLocation const & location, std::string const & name,
     
    11184        assert( vtableType );
    11285        return makeVtableDeclaration( location, name, vtableType, nullptr );
    113 }
    114 
    115 ObjectDecl * makeVtableInstance(
    116                 std::string const & name, StructInstType * vtableType,
    117                 Type * objectType, Initializer * init ) {
    118         assert( vtableType );
    119         assert( objectType );
    120         StructDecl * vtableStruct = vtableType->baseStruct;
    121         // Build the initialization
    122         if ( nullptr == init ) {
    123                 std::list< Initializer * > inits;
    124 
    125                 // This is going to have to be run before the resolver to connect expressions.
    126                 for ( auto field : vtableStruct->members ) {
    127                         if ( std::string( "parent" ) == field->name ) {
    128                                 // This will not work with polymorphic state.
    129                                 auto oField = strict_dynamic_cast< ObjectDecl * >( field );
    130                                 auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
    131                                 auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
    132                                 std::string const & parentInstance = instanceName( parentType->name );
    133                                 inits.push_back(
    134                                                 new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
    135                         } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
    136                                 std::string const & baseType = baseTypeName( vtableType->name );
    137                                 std::string const & typeId = typeIdName( baseType );
    138                                 inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
    139                         } else if ( std::string( "size" ) == field->name ) {
    140                                 inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
    141                         } else if ( std::string( "align" ) == field->name ) {
    142                                 inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
    143                         } else {
    144                                 inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
    145                         }
    146                 }
    147                 init = new ListInit( inits );
    148         // This should initialize everything except the parent pointer, the
    149         // size-of and align-of fields. These should be inserted.
    150         } else {
    151                 assert(false);
    152         }
    153         return makeVtableDeclaration( name, vtableType, init );
    15486}
    15587
     
    224156}
    225157
    226 FunctionDecl * makeGetExceptionForward(
    227                 Type * vtableType, Type * exceptType ) {
    228         assert( vtableType );
    229         assert( exceptType );
    230         FunctionType * type = new FunctionType( noQualifiers, false );
    231         vtableType->tq.is_const = true;
    232         type->returnVals.push_back( new ObjectDecl(
    233                 "_retvalue",
    234                 noStorageClasses,
    235                 LinkageSpec::Cforall,
    236                 nullptr,
    237                 new ReferenceType( noQualifiers, vtableType ),
    238                 nullptr,
    239                 { new Attribute("unused") }
    240         ) );
    241         type->parameters.push_back( new ObjectDecl(
    242                 "__unused",
    243                 noStorageClasses,
    244                 LinkageSpec::Cforall,
    245                 nullptr,
    246                 new PointerType( noQualifiers, exceptType ),
    247                 nullptr,
    248                 { new Attribute("unused") }
    249         ) );
    250         return new FunctionDecl(
    251                 functionName,
    252                 noStorageClasses,
    253                 LinkageSpec::Cforall,
    254                 type,
    255                 nullptr
    256         );
    257 }
    258 
    259158ast::FunctionDecl * makeGetExceptionForward(
    260159                CodeLocation const & location,
     
    284183}
    285184
    286 FunctionDecl * makeGetExceptionFunction(
    287                 ObjectDecl * vtableInstance, Type * exceptType ) {
    288         assert( vtableInstance );
    289         assert( exceptType );
    290         FunctionDecl * func = makeGetExceptionForward(
    291                 vtableInstance->type->clone(), exceptType );
    292         func->statements = new CompoundStmt( {
    293                 new ReturnStmt( new VariableExpr( vtableInstance ) ),
    294         } );
    295         return func;
    296 }
    297 
    298185ast::FunctionDecl * makeGetExceptionFunction(
    299186                CodeLocation const & location,
     
    307194        } );
    308195        return func;
    309 }
    310 
    311 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
    312         assert( typeIdType );
    313         StructInstType * type = typeIdType->clone();
    314         type->tq.is_const = true;
    315         std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
    316         return new ObjectDecl(
    317                 typeid_name,
    318                 noStorageClasses,
    319                 LinkageSpec::Cforall,
    320                 /* bitfieldWidth */ nullptr,
    321                 type,
    322                 new ListInit( { new SingleInit(
    323                         new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
    324                         ) } ),
    325                 { new Attribute( "cfa_linkonce", {} ) },
    326                 noFuncSpecifiers
    327         );
    328196}
    329197
  • src/Virtual/Tables.h

    r790d835 rc6b4432  
    1818#include <string>
    1919#include "AST/Fwd.hpp"
    20 class Declaration;
    21 class Expression;
    22 class FunctionDecl;
    23 class Initializer;
    24 class ObjectDecl;
    25 class StructDecl;
    26 class StructInstType;
    27 class Type;
    2820
    2921namespace Virtual {
     
    3729bool isVTableInstanceName( std::string const & name );
    3830
    39 ObjectDecl * makeVtableForward(
    40         std::string const & name, StructInstType * vtableType );
    4131/* Create a forward declaration of a vtable of the given type.
    4232 * vtableType node is consumed.
     
    4636        ast::StructInstType const * vtableType );
    4737
    48 ObjectDecl * makeVtableInstance(
    49         std::string const & name,
    50         StructInstType * vtableType, Type * objectType,
    51         Initializer * init = nullptr );
    5238/* Create an initialized definition of a vtable.
    5339 * vtableType and init (if provided) nodes are consumed.
     
    6147
    6248// Some special code for how exceptions interact with virtual tables.
    63 FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
     49
    6450/* Create a forward declaration of the exception virtual function
    6551 * linking the vtableType to the exceptType. Both nodes are consumed.
     
    7056        ast::Type const * exceptType );
    7157
    72 FunctionDecl * makeGetExceptionFunction(
    73         ObjectDecl * vtableInstance, Type * exceptType );
    7458/* Create the definition of the exception virtual function.
    7559 * exceptType node is consumed.
     
    7963        ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType );
    8064
    81 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
    8265/* Build an instance of the type-id from the type of the type-id.
    8366 * TODO: Should take the parent type. Currently locked to the exception_t.
Note: See TracChangeset for help on using the changeset viewer.