source: src/Virtual/ExpandCasts.cc@ a8615fd1

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 no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since a8615fd1 was 08fc48f, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Big header cleaning pass - commit 1

  • Property mode set to 100644
File size: 5.3 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
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
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 ) {
93 if ( (! vcast_decl) &&
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
116 assert( vcast_decl );
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
121 // just to make sure errors don't creep during translation.
122 // Move to helper with more detailed error messages.
123 PointerType * target_type =
124 dynamic_cast<PointerType *>( castExpr->get_result() );
125 assert( target_type );
126
127 StructInstType * target_struct =
128 dynamic_cast<StructInstType *>( target_type->get_base() );
129 assert( target_struct );
130
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(
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 // ),
149 new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
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()
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}
Note: See TracBrowser for help on using the repository browser.