source: src/Virtual/ExpandCasts.cc @ d104b02

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since d104b02 was cbce272, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Structure based exception handling.

  • Property mode set to 100644
File size: 4.6 KB
Line 
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
12// Last Modified On : Tus Aug  2 14:59:00 2017
13// Update Count     : 1
14//
15
16#include "ExpandCasts.h"
17#include "Common/PassVisitor.h"
18
19namespace Virtual {
20
21        /* Currently virtual depends on the rather brittle name matching between
22         * a (strict/explicate) virtual type, its vtable type and the vtable
23         * instance.
24         * A stronger implementation, would probably keep track of those triads
25         * and use that information to create better error messages.
26         */
27
28        std::string get_vtable_name( std::string const & name ) {
29                return name + "_vtable";
30        }
31
32        std::string get_vtable_inst_name( std::string const & name ) {
33                return std::string("_") + get_vtable_name( name ) + "_instance";
34        }
35
36        std::string get_vtable_name_root( std::string const & name ) {
37                return name.substr(0, name.size() - 7 );
38        }
39
40        std::string get_vtable_inst_name_root( std::string const & name ) {
41                return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
42        }
43
44        bool is_vtable_name( std::string const & name ) {
45                return (name.substr( name.size() - 7 ) == "_vtable" );
46        }
47
48        bool is_vtable_inst_name( std::string const & name ) {
49                return 17 < name.size() &&
50                        name == get_vtable_inst_name( get_vtable_inst_name_root( name ) );
51        }
52
53        class VirtualCastCore {
54        std::map<std::string, ObjectDecl *> vtable_instances;
55        FunctionDecl *vcast_decl;
56        StructDecl *pvt_decl;
57
58                Type * pointer_to_pvt(int level_of_indirection) {
59                        Type * type = new StructInstType(
60                                Type::Qualifiers( Type::Const ), pvt_decl );
61                        for (int i = 0 ; i < level_of_indirection ; ++i) {
62                                type = new PointerType( noQualifiers, type );
63                        }
64                        return type;
65                }
66
67        public:
68                VirtualCastCore() :
69                        vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
70                {}
71
72                void premutate( FunctionDecl * functionDecl );
73                void premutate( StructDecl * structDecl );
74                void premutate( ObjectDecl * objectDecl );
75
76                Expression * postmutate( VirtualCastExpr * castExpr );
77        };
78
79        void VirtualCastCore::premutate( FunctionDecl * functionDecl ) {
80                if ( (! vcast_decl) &&
81                     functionDecl->get_name() == "__cfa__virtual_cast" ) {
82                        vcast_decl = functionDecl;
83                }
84        }
85
86        void VirtualCastCore::premutate( StructDecl * structDecl ) {
87                if ( pvt_decl || ! structDecl->has_body() ) {
88                        return;
89                } else if ( structDecl->get_name() == "__cfa__parent_vtable" ) {
90                        pvt_decl = structDecl;
91                }
92        }
93
94        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
95                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
96                        vtable_instances[objectDecl->get_name()] = objectDecl;
97                }
98        }
99
100        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
101                assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
102
103                assert( vcast_decl );
104                assert( pvt_decl );
105
106                // May only cast to a pointer or reference type.
107                // A earlier validation should give a syntax error, this is
108                // just to make sure errors don't creep during translation.
109                // Move to helper with more detailed error messages.
110                PointerType * target_type =
111                        dynamic_cast<PointerType *>( castExpr->get_result() );
112                assert( target_type );
113
114                StructInstType * target_struct =
115                        dynamic_cast<StructInstType *>( target_type->get_base() );
116                assert( target_struct );
117
118                StructDecl * target_decl = target_struct->get_baseStruct();
119
120                std::map<std::string, ObjectDecl *>::iterator found =
121                        vtable_instances.find(
122                                get_vtable_inst_name( target_decl->get_name() ) );
123                if ( vtable_instances.end() == found ) {
124                        assertf( false, "virtual table instance not found." );
125                }
126                ObjectDecl * table = found->second;
127
128                Expression * result = new CastExpr(
129                        //new ApplicationExpr(
130                                //new AddressExpr( new VariableExpr( vcast_decl ) ),
131                                //new CastExpr( new VariableExpr( vcast_decl ),
132                                //      new PointerType( noQualifiers,
133                                //              vcast_decl->get_type()->clone()
134                                //              )
135                                //      ),
136                        new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
137                                        new CastExpr(
138                                                new AddressExpr( new VariableExpr( table ) ),
139                                                pointer_to_pvt(1)
140                                                ),
141                                        new CastExpr(
142                                                castExpr->get_arg(),
143                                                pointer_to_pvt(2)
144                                                )
145                                } ),
146                        castExpr->get_result()->clone()
147                        );
148
149                castExpr->set_arg( nullptr );
150                castExpr->set_result( nullptr );
151                delete castExpr;
152                return result;
153        }
154
155        void expandCasts( std::list< Declaration * > & translationUnit ) {
156                PassVisitor<VirtualCastCore> translator;
157                mutateAll( translationUnit, translator );
158        }
159}
Note: See TracBrowser for help on using the repository browser.