- Timestamp:
- Jul 22, 2020, 11:24:33 AM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 54eb5ebd
- Parents:
- 4a32319
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
r4a32319 rf19fbbc 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue May 26 14:37:00 202013 // Update Count : 212 // Last Modified On : Tue Jul 22 10:04:00 2020 13 // Update Count : 3 14 14 // 15 15 … … 24 24 #include "Common/PassVisitor.h" // for PassVisitor 25 25 #include "Common/SemanticError.h" // for SemanticError 26 #include "SymTab/Mangler.h" // for mangleType 26 27 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 27 28 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... … … 31 32 32 33 namespace Virtual { 34 35 // Indented until the new ast code gets added. 36 37 /// Maps virtual table types the instance for that type. 38 class VirtualTableMap final { 39 std::unordered_map<std::string, ObjectDecl *> vtable_instances; 40 public: 41 ObjectDecl * insert( ObjectDecl * vtableDecl ) { 42 std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type ); 43 ObjectDecl *& value = vtable_instances[ mangledName ]; 44 if ( value ) { 45 if ( vtableDecl->storageClasses.is_extern ) { 46 return nullptr; 47 } else if ( ! value->storageClasses.is_extern ) { 48 return value; 49 } 50 } 51 value = vtableDecl; 52 return nullptr; 53 } 54 55 ObjectDecl * lookup( const Type * vtableType ) { 56 std::string const & mangledName = SymTab::Mangler::mangleType( vtableType ); 57 const auto it = vtable_instances.find( mangledName ); 58 return ( vtable_instances.end() == it ) ? nullptr : it->second; 59 } 60 }; 33 61 34 62 /* Currently virtual depends on the rather brittle name matching between … … 39 67 */ 40 68 69 namespace { 70 41 71 std::string get_vtable_name( std::string const & name ) { 42 72 return name + "_vtable"; … … 53 83 std::string get_vtable_inst_name_root( std::string const & name ) { 54 84 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 85 } 60 86 … … 64 90 } 65 91 92 } // namespace 93 66 94 class VirtualCastCore { 67 std::map<std::string, ObjectDecl *>vtable_instances;68 69 95 VirtualTableMap vtable_instances; 96 FunctionDecl *vcast_decl; 97 StructDecl *pvt_decl; 70 98 71 99 Type * pointer_to_pvt(int level_of_indirection) { … … 107 135 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 108 136 if ( is_vtable_inst_name( objectDecl->get_name() ) ) { 109 vtable_instances[objectDecl->get_name()] = objectDecl; 110 } 111 } 112 113 // Better error locations for generated casts. 114 static CodeLocation castLocation( VirtualCastExpr * castExpr ) { 137 if ( ObjectDecl * existing = vtable_instances.insert( objectDecl ) ) { 138 std::string msg = "Repeated instance of virtual table, original found at: "; 139 msg += existing->location.filename; 140 msg += ":" + toString( existing->location.first_line ); 141 SemanticError( objectDecl->location, msg ); 142 } 143 } 144 } 145 146 namespace { 147 148 /// Better error locations for generated casts. 149 CodeLocation castLocation( const VirtualCastExpr * castExpr ) { 115 150 if ( castExpr->location.isSet() ) { 116 151 return castExpr->location; … … 124 159 } 125 160 161 [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) { 162 SemanticError( castLocation( castExpr ), message ); 163 } 164 165 /// Get the virtual table type used in a virtual cast. 166 Type * getVirtualTableType( const VirtualCastExpr * castExpr ) { 167 const Type * objectType; 168 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) { 169 objectType = target->base; 170 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) { 171 objectType = target->base; 172 } else { 173 castError( castExpr, "Virtual cast type must be a pointer or reference type." ); 174 } 175 assert( objectType ); 176 177 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType ); 178 if ( nullptr == structType ) { 179 castError( castExpr, "Virtual cast type must refer to a structure type." ); 180 } 181 const StructDecl * structDecl = structType->baseStruct; 182 assert( structDecl ); 183 184 const ObjectDecl * fieldDecl = nullptr; 185 if ( 0 < structDecl->members.size() ) { 186 const Declaration * memberDecl = structDecl->members.front(); 187 assert( memberDecl ); 188 fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl ); 189 if ( fieldDecl && fieldDecl->name != "virtual_table" ) { 190 fieldDecl = nullptr; 191 } 192 } 193 if ( nullptr == fieldDecl ) { 194 castError( castExpr, "Virtual cast type must have a leading virtual_table field." ); 195 } 196 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type ); 197 if ( nullptr == fieldType ) { 198 castError( castExpr, "Virtual cast type virtual_table field is not a pointer." ); 199 } 200 assert( fieldType->base ); 201 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base ); 202 assert( virtualStructType ); 203 204 // Here is the type, but if it is polymorphic it will have lost information. 205 // (Always a clone so that it may always be deleted.) 206 StructInstType * virtualType = virtualStructType->clone(); 207 if ( ! structType->parameters.empty() ) { 208 deleteAll( virtualType->parameters ); 209 virtualType->parameters.clear(); 210 cloneAll( structType->parameters, virtualType->parameters ); 211 } 212 return virtualType; 213 } 214 215 } // namespace 216 126 217 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 127 assertf( castExpr-> get_result(), "Virtual Cast target not found before expansion." );218 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); 128 219 129 220 assert( vcast_decl ); 130 221 assert( pvt_decl ); 131 222 132 // Get the base type of the pointer/reference. 133 Type * base; 134 Type * result_type = castExpr->result; 135 if ( PointerType * target = dynamic_cast<PointerType *>( result_type ) ) { 136 base = target->base; 137 } else if ( ReferenceType * target = dynamic_cast<ReferenceType *>( result_type ) ) { 138 base = target->base; 139 } else { 223 const Type * vtable_type = getVirtualTableType( castExpr ); 224 ObjectDecl * table = vtable_instances.lookup( vtable_type ); 225 if ( nullptr == table ) { 140 226 SemanticError( castLocation( castExpr ), 141 "Virtual cast type must be a pointer or reference type." ); 142 } 143 144 StructInstType * target_struct = dynamic_cast<StructInstType *>( base ); 145 if ( nullptr == target_struct ) { 146 SemanticError( castLocation( castExpr ), 147 "Virtual cast type must refer to a structure type." ); 148 } 149 StructDecl * target_decl = target_struct->get_baseStruct(); 150 151 std::map<std::string, ObjectDecl *>::iterator found = 152 vtable_instances.find( get_vtable_inst_name( target_decl->get_name() ) ); 153 if ( vtable_instances.end() == found ) { 154 SemanticError( castLocation( castExpr ), 155 "Virtual cast type does not have a virtual table instance." ); 156 } 157 ObjectDecl * table = found->second; 227 "Could not find virtual table instance." ); 228 } 158 229 159 230 Expression * result = new CastExpr( … … 174 245 castExpr->set_result( nullptr ); 175 246 delete castExpr; 247 delete vtable_type; 176 248 return result; 177 249 }
Note: See TracChangeset
for help on using the changeset viewer.