source: src/Virtual/ExpandCasts.cc @ 6a9d4b4

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 6a9d4b4 was 8e6214f, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

Update virtual cast handling to use ApplicationExpr? rather than UntypedExpr? for cfavirtual_cast

  • Property mode set to 100644
File size: 5.3 KB
RevLine 
[a5f0529]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExpandCasts.cc --
8//
9// Author           : Andrew Beach
10// Created On       : Mon Jul 24 13:59:00 2017
11// Last Modified By : Andrew Beach
[cbce272]12// Last Modified On : Tus Aug  2 14:59:00 2017
13// Update Count     : 1
[a5f0529]14//
15
16#include "ExpandCasts.h"
[08fc48f]17
18#include <cassert>                 // for assert, assertf
19#include <iterator>                // for back_inserter, inserter
20#include <map>                     // for map, _Rb_tree_iterator, map<>::ite...
21#include <string>                  // for string, allocator, operator==, ope...
22#include <utility>                 // for pair
23
24#include "Common/PassVisitor.h"    // for PassVisitor
25#include "Common/SemanticError.h"  // for SemanticError
26#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
27#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
28#include "SynTree/Mutator.h"       // for mutateAll
29#include "SynTree/Type.h"          // for Type, PointerType, StructInstType
30#include "SynTree/Visitor.h"       // for acceptAll
[a5f0529]31
32namespace Virtual {
33
34        /* Currently virtual depends on the rather brittle name matching between
35         * a (strict/explicate) virtual type, its vtable type and the vtable
36         * instance.
37         * A stronger implementation, would probably keep track of those triads
38         * and use that information to create better error messages.
39         */
40
41        std::string get_vtable_name( std::string const & name ) {
42                return name + "_vtable";
43        }
44
45        std::string get_vtable_inst_name( std::string const & name ) {
46                return std::string("_") + get_vtable_name( name ) + "_instance";
47        }
48
49        std::string get_vtable_name_root( std::string const & name ) {
50                return name.substr(0, name.size() - 7 );
51        }
52
53        std::string get_vtable_inst_name_root( std::string const & name ) {
54                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" );
59        }
60
61        bool is_vtable_inst_name( std::string const & name ) {
62                return 17 < name.size() &&
63                        name == get_vtable_inst_name( get_vtable_inst_name_root( name ) );
64        }
65
66        class VirtualCastCore {
67        std::map<std::string, ObjectDecl *> vtable_instances;
68        FunctionDecl *vcast_decl;
69        StructDecl *pvt_decl;
70
71                Type * pointer_to_pvt(int level_of_indirection) {
72                        Type * type = new StructInstType(
73                                Type::Qualifiers( Type::Const ), pvt_decl );
74                        for (int i = 0 ; i < level_of_indirection ; ++i) {
75                                type = new PointerType( noQualifiers, type );
76                        }
77                        return type;
78                }
79
80        public:
81                VirtualCastCore() :
82                        vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
83                {}
84
85                void premutate( FunctionDecl * functionDecl );
86                void premutate( StructDecl * structDecl );
87                void premutate( ObjectDecl * objectDecl );
88
89                Expression * postmutate( VirtualCastExpr * castExpr );
90        };
91
92        void VirtualCastCore::premutate( FunctionDecl * functionDecl ) {
[cbce272]93                if ( (! vcast_decl) &&
[a5f0529]94                     functionDecl->get_name() == "__cfa__virtual_cast" ) {
95                        vcast_decl = functionDecl;
96                }
97        }
98
99        void VirtualCastCore::premutate( StructDecl * structDecl ) {
100                if ( pvt_decl || ! structDecl->has_body() ) {
101                        return;
102                } else if ( structDecl->get_name() == "__cfa__parent_vtable" ) {
103                        pvt_decl = structDecl;
104                }
105        }
106
107        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
108                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
109                        vtable_instances[objectDecl->get_name()] = objectDecl;
110                }
111        }
112
113        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
114                assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
115
[cbce272]116                assert( vcast_decl );
[a5f0529]117                assert( pvt_decl );
118
119                // May only cast to a pointer or reference type.
120                // A earlier validation should give a syntax error, this is
[cbce272]121                // just to make sure errors don't creep during translation.
122                // Move to helper with more detailed error messages.
[a5f0529]123                PointerType * target_type =
124                        dynamic_cast<PointerType *>( castExpr->get_result() );
[cbce272]125                assert( target_type );
[a5f0529]126
127                StructInstType * target_struct =
128                        dynamic_cast<StructInstType *>( target_type->get_base() );
[cbce272]129                assert( target_struct );
130
[a5f0529]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;
140
141                Expression * result = new CastExpr(
[cbce272]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                                //      ),
[8e6214f]149                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
[cbce272]150                                        new CastExpr(
151                                                new AddressExpr( new VariableExpr( table ) ),
152                                                pointer_to_pvt(1)
[8e6214f]153                                        ),
[cbce272]154                                        new CastExpr(
155                                                castExpr->get_arg(),
156                                                pointer_to_pvt(2)
[8e6214f]157                                        )
158                        } ),
[cbce272]159                        castExpr->get_result()->clone()
[8e6214f]160                );
[a5f0529]161
162                castExpr->set_arg( nullptr );
163                castExpr->set_result( nullptr );
164                delete castExpr;
165                return result;
166        }
167
168        void expandCasts( std::list< Declaration * > & translationUnit ) {
169                PassVisitor<VirtualCastCore> translator;
170                mutateAll( translationUnit, translator );
171        }
172}
Note: See TracBrowser for help on using the repository browser.