Changeset 082af5b


Ignore:
Timestamp:
Aug 12, 2022, 9:07:36 AM (7 weeks ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master, pthread-emulation
Children:
181036c
Parents:
283876d (diff), ccbc65c (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' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    r283876d r082af5b  
    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 : Thu Aug 11 12:06:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    2020#include <string>                  // for string, allocator, operator==, ope...
    2121
     22#include "AST/Decl.hpp"
     23#include "AST/Expr.hpp"
     24#include "AST/Pass.hpp"
    2225#include "Common/PassVisitor.h"    // for PassVisitor
    2326#include "Common/ScopedMap.h"      // for ScopedMap
     
    3235namespace Virtual {
    3336
    34 static bool is_prefix( const std::string & prefix, const std::string& entire ) {
     37namespace {
     38
     39bool is_prefix( const std::string & prefix, const std::string& entire ) {
    3540        size_t const p_size = prefix.size();
    3641        return (p_size < entire.size() && prefix == entire.substr(0, p_size));
    3742}
    3843
    39 static bool is_type_id_object( const ObjectDecl * objectDecl ) {
     44bool is_type_id_object( const ObjectDecl * objectDecl ) {
    4045        const std::string & objectName = objectDecl->name;
    4146        return is_prefix( "__cfatid_", objectName );
     47}
     48
     49bool is_type_id_object( const ast::ObjectDecl * decl ) {
     50        return is_prefix( "__cfatid_", decl->name );
    4251}
    4352
     
    124133                }
    125134        }
    126 
    127         namespace {
    128135
    129136        /// Better error locations for generated casts.
     
    229236        }
    230237
    231         } // namespace
    232 
    233238        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    234239                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
     
    265270        }
    266271
    267         void expandCasts( std::list< Declaration * > & translationUnit ) {
    268                 PassVisitor<VirtualCastCore> translator;
    269                 mutateAll( translationUnit, translator );
    270         }
    271 }
     272/// Better error locations for generated casts.
     273// TODO: Does the improved distribution of code locations make this unneeded?
     274CodeLocation castLocation( const ast::VirtualCastExpr * castExpr ) {
     275        if ( castExpr->location.isSet() ) {
     276                return castExpr->location;
     277        } else if ( castExpr->arg->location.isSet() ) {
     278                return castExpr->arg->location;
     279        } else {
     280                return CodeLocation();
     281        }
     282}
     283
     284[[noreturn]] void castError( ast::VirtualCastExpr const * castExpr, std::string const & message ) {
     285        SemanticError( castLocation( castExpr ), message );
     286}
     287
     288class TypeIdTable final {
     289        ScopedMap<std::string, ast::ObjectDecl const *> instances;
     290public:
     291        void enterScope() { instances.beginScope(); }
     292        void leaveScope() { instances.endScope(); }
     293
     294        // Attempt to insert an instance into the map. If there is a conflict,
     295        // returns the previous declaration for error messages.
     296        ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) {
     297                std::string const & mangledName =
     298                                Mangle::mangle( typeIdDecl->type, Mangle::typeMode() );
     299                ast::ObjectDecl const *& value = instances[ mangledName ];
     300                if ( value ) {
     301                        if ( typeIdDecl->storage.is_extern ) {
     302                                return nullptr;
     303                        } else if ( !value->storage.is_extern ) {
     304                                return value;
     305                        }
     306                }
     307                value = typeIdDecl;
     308                return nullptr;
     309        }
     310
     311        ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) {
     312                std::string const & mangledName =
     313                                Mangle::mangle( typeIdType, Mangle::typeMode() );
     314                auto const it = instances.find( mangledName );
     315                return ( instances.end() == it ) ? nullptr : it->second;
     316        }
     317};
     318
     319struct ExpandCastsCore {
     320        void previsit( ast::FunctionDecl const * decl );
     321        void previsit( ast::StructDecl const * decl );
     322        void previsit( ast::ObjectDecl const * decl );
     323        ast::Expr const * postvisit( ast::VirtualCastExpr const * expr );
     324
     325        ast::CastExpr const * cast_to_type_id(
     326                ast::Expr const * expr, unsigned int level_of_indirection );
     327
     328        ast::FunctionDecl const * vcast_decl = nullptr;
     329        ast::StructDecl const * info_decl = nullptr;
     330
     331        TypeIdTable symtab;
     332};
     333
     334void ExpandCastsCore::previsit( ast::FunctionDecl const * decl ) {
     335        if ( !vcast_decl && "__cfavir_virtual_cast" == decl->name ) {
     336                vcast_decl = decl;
     337        }
     338}
     339
     340void ExpandCastsCore::previsit( ast::StructDecl const * decl ) {
     341        if ( !info_decl && decl->body && "__cfavir_type_info" == decl->name ) {
     342                info_decl = decl;
     343        }
     344}
     345
     346void ExpandCastsCore::previsit( ast::ObjectDecl const * decl ) {
     347        if ( is_type_id_object( decl ) ) {
     348                // Multiple definitions should be fine because of linkonce.
     349                symtab.insert( decl );
     350        }
     351}
     352
     353/// Get the base type from a pointer or reference.
     354ast::Type const * getBaseType( ast::ptr<ast::Type> const & type ) {
     355        if ( auto target = type.as<ast::PointerType>() ) {
     356                return target->base.get();
     357        } else if ( auto target = type.as<ast::ReferenceType>() ) {
     358                return target->base.get();
     359        } else {
     360                return nullptr;
     361        }
     362}
     363
     364ast::StructInstType * polyCopy(
     365                ast::StructInstType const * oldType,
     366                ast::StructInstType const * newType ) {
     367        assert( oldType->params.size() == newType->params.size() );
     368        ast::StructInstType * retType = ast::deepCopy( newType );
     369        if ( ! oldType->params.empty() ) {
     370                retType->params.clear();
     371                for ( auto oldParams : oldType->params ) {
     372                        retType->params.push_back( ast::deepCopy( oldParams ) );
     373                }
     374        }
     375        return retType;
     376}
     377
     378/// Follow the "head" field of the structure to get the type that is pointed
     379/// to by that field.
     380ast::StructInstType const * followHeadPointerType(
     381                CodeLocation const & errorLocation,
     382                ast::StructInstType const * oldType,
     383                std::string const & fieldName ) {
     384        ast::StructDecl const * oldDecl = oldType->base;
     385        assert( oldDecl );
     386
     387        // Helper function for throwing semantic errors.
     388        auto throwError = [&fieldName, &errorLocation, &oldDecl](
     389                        std::string const & message ) {
     390                std::string const & context = "While following head pointer of " +
     391                        oldDecl->name + " named '" + fieldName + "': ";
     392                SemanticError( errorLocation, context + message );
     393        };
     394
     395        if ( oldDecl->members.empty() ) {
     396                throwError( "Type has no fields." );
     397        }
     398        ast::ptr<ast::Decl> const & memberDecl = oldDecl->members.front();
     399        assert( memberDecl );
     400        ast::ObjectDecl const * fieldDecl = memberDecl.as<ast::ObjectDecl>();
     401        assert( fieldDecl );
     402        if ( fieldName != fieldDecl->name ) {
     403                throwError( "Head field did not have expected name." );
     404        }
     405
     406        ast::ptr<ast::Type> const & fieldType = fieldDecl->type;
     407        if ( nullptr == fieldType ) {
     408                throwError( "Could not get head field." );
     409        }
     410        auto ptrType = fieldType.as<ast::PointerType>();
     411        if ( nullptr == ptrType ) {
     412                throwError( "First field is not a pointer type." );
     413        }
     414        assert( ptrType->base );
     415        auto newType = ptrType->base.as<ast::StructInstType>();
     416        if ( nullptr == newType ) {
     417                throwError( "First field does not point to a structure type." );
     418        }
     419
     420        return polyCopy( oldType, newType );
     421}
     422
     423/// Get the type-id type from a virtual type.
     424ast::StructInstType const * getTypeIdType(
     425                CodeLocation const & errorLocation,
     426                ast::Type const * type ) {
     427        auto typeInst = dynamic_cast<ast::StructInstType const *>( type );
     428        if ( nullptr == typeInst ) {
     429                return nullptr;
     430        }
     431        ast::ptr<ast::StructInstType> tableInst =
     432                followHeadPointerType( errorLocation, typeInst, "virtual_table" );
     433        if ( nullptr == tableInst ) {
     434                return nullptr;
     435        }
     436        ast::StructInstType const * typeIdInst =
     437                followHeadPointerType( errorLocation, tableInst, "__cfavir_typeid" );
     438        return typeIdInst;
     439}
     440
     441ast::Expr const * ExpandCastsCore::postvisit(
     442                ast::VirtualCastExpr const * expr ) {
     443        assertf( expr->result, "Virtual cast target not found before expansion." );
     444
     445        assert( vcast_decl );
     446        assert( info_decl );
     447
     448        ast::Type const * base_type = getBaseType( expr->result );
     449        if ( nullptr == base_type ) {
     450                castError( expr, "Virtual cast target must be a pointer or reference type." );
     451        }
     452        ast::StructInstType const * type_id_type =
     453                        getTypeIdType( castLocation( expr ), base_type );
     454        if ( nullptr == type_id_type ) {
     455                castError( expr, "Ill formed virtual cast target type." );
     456        }
     457        ast::ObjectDecl const * type_id = symtab.lookup( type_id_type );
     458        if ( nullptr == type_id ) {
     459                // I'm trying to give a different error for polymorpic types as
     460                // different things can go wrong there.
     461                if ( type_id_type->params.empty() ) {
     462                        castError( expr, "Virtual cast does not target a virtual type." );
     463                } else {
     464                        castError( expr, "Virtual cast does not target a type with a "
     465                                "type id (possible missing virtual table)." );
     466                }
     467        }
     468
     469        return new ast::CastExpr( expr->location,
     470                new ast::ApplicationExpr( expr->location,
     471                        ast::VariableExpr::functionPointer( expr->location, vcast_decl ),
     472                        {
     473                                cast_to_type_id(
     474                                        new ast::AddressExpr( expr->location,
     475                                                new ast::VariableExpr( expr->location, type_id ) ),
     476                                        1 ),
     477                                cast_to_type_id( expr->arg, 2 ),
     478                        }
     479                ),
     480                ast::deepCopy( expr->result )
     481        );
     482}
     483
     484ast::CastExpr const * ExpandCastsCore::cast_to_type_id(
     485                ast::Expr const * expr, unsigned int level_of_indirection ) {
     486        assert( info_decl );
     487        ast::Type * type = new ast::StructInstType( info_decl, ast::CV::Const );
     488        for ( unsigned int i = 0 ; i < level_of_indirection ; ++i ) {
     489                type = new ast::PointerType( type );
     490        }
     491        return new ast::CastExpr( expr->location, expr, type );
     492}
     493
     494} // namespace
     495
     496void expandCasts( std::list< Declaration * > & translationUnit ) {
     497        PassVisitor<VirtualCastCore> translator;
     498        mutateAll( translationUnit, translator );
     499}
     500
     501void expandCasts( ast::TranslationUnit & translationUnit ) {
     502        ast::Pass<ExpandCastsCore>::run( translationUnit );
     503}
     504
     505} // namespace Virtual
  • src/Virtual/ExpandCasts.h

    r283876d r082af5b  
    1010// Created On       : Mon Jul 24 13:54:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Jul 25 14:51:00 2017
    13 // Update Count     : 0
     12// Last Modified On : Fri Jul 29 14:40:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace Virtual {
    23         void expandCasts( std::list< Declaration * > & translationUnit );
    24         // Breaks all virtual cast nodes up into translatable nodes.
     26void expandCasts( std::list< Declaration * > & translationUnit );
     27void expandCasts( ast::TranslationUnit & translationUnit );
     28// Breaks all virtual cast nodes up into translatable nodes.
    2529
    26         // Later this might just set some information so it can happen at CodeGen.
     30// Later this might just set some information so it can happen at CodeGen.
    2731
    2832}
  • src/main.cc

    r283876d r082af5b  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 18 11:08:00 2022
    13 // Update Count     : 676
     12// Last Modified On : Thu 11 12:18:00 2022
     13// Update Count     : 677
    1414//
    1515
     
    445445                        PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
    446446
     447                        if ( tuplep ) {
     448                                dump( move( transUnit ) );
     449                                return EXIT_SUCCESS;
     450                        } // if
     451
     452                        // Must come after Translate Tries.
     453                        PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) );
     454
    447455                        translationUnit = convert( move( transUnit ) );
    448456                } else {
     
    520528                        PASS( "Convert Specializations",  GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded
    521529                        PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
     530
     531                        if ( tuplep ) {
     532                                dump( translationUnit );
     533                                return EXIT_SUCCESS;
     534                        } // if
     535
     536                        PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
    522537                }
    523 
    524                 if ( tuplep ) {
    525                         dump( translationUnit );
    526                         return EXIT_SUCCESS;
    527                 } // if
    528 
    529                 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
    530538
    531539                PASS( "Instantiate Generics", GenPoly::instantiateGeneric( translationUnit ) );
Note: See TracChangeset for help on using the changeset viewer.