source: src/Virtual/ExpandCasts.cc@ 86d5ba7c

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 86d5ba7c was a5f0529, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Virtual casts have been added. They still require a lot of hand coded support to work but for simple cases it should be enough.

  • Property mode set to 100644
File size: 4.4 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 : Wed Jul 26 14:16:00 2017
13// Update Count : 0
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) && functionDecl->get_statements() &&
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 in.
109 PointerType * target_type =
110 dynamic_cast<PointerType *>( castExpr->get_result() );
111 assert( target_type );
112
113 StructInstType * target_struct =
114 dynamic_cast<StructInstType *>( target_type->get_base() );
115 StructDecl * target_decl = target_struct->get_baseStruct();
116
117 std::map<std::string, ObjectDecl *>::iterator found =
118 vtable_instances.find(
119 get_vtable_inst_name( target_decl->get_name() ) );
120 if ( vtable_instances.end() == found ) {
121 assertf( false, "virtual table instance not found." );
122 }
123 ObjectDecl * table = found->second;
124
125 Expression * result = new CastExpr(
126 //new ApplicationExpr( new VariableExpr( vcast_decl ), {
127 new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
128 new CastExpr(
129 new AddressExpr( new VariableExpr( table ) ),
130 pointer_to_pvt(1)
131 ),
132 new CastExpr(
133 castExpr->get_arg(),
134 pointer_to_pvt(2)
135 ) }
136 ),
137 castExpr->get_result()
138 );
139
140 castExpr->set_arg( nullptr );
141 castExpr->set_result( nullptr );
142 delete castExpr;
143 return result;
144 }
145
146 void expandCasts( std::list< Declaration * > & translationUnit ) {
147 PassVisitor<VirtualCastCore> translator;
148 mutateAll( translationUnit, translator );
149 }
150}
Note: See TracBrowser for help on using the repository browser.