| [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 | 
 | 
|---|
 | 32 | namespace 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 |                                 //      ),
 | 
|---|
| [a5f0529] | 149 |                         new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
 | 
|---|
| [cbce272] | 150 |                                         new CastExpr(
 | 
|---|
 | 151 |                                                 new AddressExpr( new VariableExpr( table ) ),
 | 
|---|
 | 152 |                                                 pointer_to_pvt(1)
 | 
|---|
 | 153 |                                                 ),
 | 
|---|
 | 154 |                                         new CastExpr(
 | 
|---|
 | 155 |                                                 castExpr->get_arg(),
 | 
|---|
 | 156 |                                                 pointer_to_pvt(2)
 | 
|---|
 | 157 |                                                 )
 | 
|---|
 | 158 |                                 } ),
 | 
|---|
 | 159 |                         castExpr->get_result()->clone()
 | 
|---|
| [a5f0529] | 160 |                         );
 | 
|---|
 | 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 | }
 | 
|---|