Changeset 22f94a4 for src/Virtual/ExpandCasts.cc
- Timestamp:
- Aug 11, 2020, 4:40:15 PM (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:
- 0d070ca
- Parents:
- 07d867b (diff), 129674b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
r07d867b r22f94a4 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Aug 2 14:59:00 201713 // Update Count : 112 // Last Modified On : Fri Jul 31 10:29:00 2020 13 // Update Count : 4 14 14 // 15 15 … … 18 18 #include <cassert> // for assert, assertf 19 19 #include <iterator> // for back_inserter, inserter 20 #include <map> // for map, _Rb_tree_iterator, map<>::ite...21 20 #include <string> // for string, allocator, operator==, ope... 22 #include <utility> // for pair23 21 24 22 #include "Common/PassVisitor.h" // for PassVisitor 23 #include "Common/ScopedMap.h" // for ScopedMap 25 24 #include "Common/SemanticError.h" // for SemanticError 25 #include "SymTab/Mangler.h" // for mangleType 26 26 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 27 27 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... … … 31 31 32 32 namespace Virtual { 33 34 // Indented until the new ast code gets added. 35 36 /// Maps virtual table types the instance for that type. 37 class VirtualTableMap final { 38 ScopedMap<std::string, ObjectDecl *> vtable_instances; 39 public: 40 void enterScope() { 41 vtable_instances.beginScope(); 42 } 43 void leaveScope() { 44 vtable_instances.endScope(); 45 } 46 47 ObjectDecl * insert( ObjectDecl * vtableDecl ) { 48 std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type ); 49 ObjectDecl *& value = vtable_instances[ mangledName ]; 50 if ( value ) { 51 if ( vtableDecl->storageClasses.is_extern ) { 52 return nullptr; 53 } else if ( ! value->storageClasses.is_extern ) { 54 return value; 55 } 56 } 57 value = vtableDecl; 58 return nullptr; 59 } 60 61 ObjectDecl * lookup( const Type * vtableType ) { 62 std::string const & mangledName = SymTab::Mangler::mangleType( vtableType ); 63 const auto it = vtable_instances.find( mangledName ); 64 return ( vtable_instances.end() == it ) ? nullptr : it->second; 65 } 66 }; 33 67 34 68 /* Currently virtual depends on the rather brittle name matching between … … 39 73 */ 40 74 75 namespace { 76 41 77 std::string get_vtable_name( std::string const & name ) { 42 78 return name + "_vtable"; … … 53 89 std::string get_vtable_inst_name_root( std::string const & name ) { 54 90 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 91 } 60 92 … … 64 96 } 65 97 98 } // namespace 99 66 100 class VirtualCastCore { 67 std::map<std::string, ObjectDecl *> vtable_instances;68 FunctionDecl *vcast_decl;69 StructDecl *pvt_decl;70 71 101 Type * pointer_to_pvt(int level_of_indirection) { 72 102 Type * type = new StructInstType( … … 80 110 public: 81 111 VirtualCastCore() : 82 vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )112 indexer(), vcast_decl( nullptr ), pvt_decl( nullptr ) 83 113 {} 84 114 … … 88 118 89 119 Expression * postmutate( VirtualCastExpr * castExpr ); 120 121 VirtualTableMap indexer; 122 private: 123 FunctionDecl *vcast_decl; 124 StructDecl *pvt_decl; 90 125 }; 91 126 … … 107 142 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 108 143 if ( is_vtable_inst_name( objectDecl->get_name() ) ) { 109 vtable_instances[objectDecl->get_name()] = objectDecl; 110 } 111 } 144 if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) { 145 std::string msg = "Repeated instance of virtual table, original found at: "; 146 msg += existing->location.filename; 147 msg += ":" + toString( existing->location.first_line ); 148 SemanticError( objectDecl->location, msg ); 149 } 150 } 151 } 152 153 namespace { 154 155 /// Better error locations for generated casts. 156 CodeLocation castLocation( const VirtualCastExpr * castExpr ) { 157 if ( castExpr->location.isSet() ) { 158 return castExpr->location; 159 } else if ( castExpr->arg->location.isSet() ) { 160 return castExpr->arg->location; 161 } else if ( castExpr->result->location.isSet() ) { 162 return castExpr->result->location; 163 } else { 164 return CodeLocation(); 165 } 166 } 167 168 [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) { 169 SemanticError( castLocation( castExpr ), message ); 170 } 171 172 /// Get the virtual table type used in a virtual cast. 173 Type * getVirtualTableType( const VirtualCastExpr * castExpr ) { 174 const Type * objectType; 175 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) { 176 objectType = target->base; 177 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) { 178 objectType = target->base; 179 } else { 180 castError( castExpr, "Virtual cast type must be a pointer or reference type." ); 181 } 182 assert( objectType ); 183 184 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType ); 185 if ( nullptr == structType ) { 186 castError( castExpr, "Virtual cast type must refer to a structure type." ); 187 } 188 const StructDecl * structDecl = structType->baseStruct; 189 assert( structDecl ); 190 191 const ObjectDecl * fieldDecl = nullptr; 192 if ( 0 < structDecl->members.size() ) { 193 const Declaration * memberDecl = structDecl->members.front(); 194 assert( memberDecl ); 195 fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl ); 196 if ( fieldDecl && fieldDecl->name != "virtual_table" ) { 197 fieldDecl = nullptr; 198 } 199 } 200 if ( nullptr == fieldDecl ) { 201 castError( castExpr, "Virtual cast type must have a leading virtual_table field." ); 202 } 203 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type ); 204 if ( nullptr == fieldType ) { 205 castError( castExpr, "Virtual cast type virtual_table field is not a pointer." ); 206 } 207 assert( fieldType->base ); 208 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base ); 209 assert( virtualStructType ); 210 211 // Here is the type, but if it is polymorphic it will have lost information. 212 // (Always a clone so that it may always be deleted.) 213 StructInstType * virtualType = virtualStructType->clone(); 214 if ( ! structType->parameters.empty() ) { 215 deleteAll( virtualType->parameters ); 216 virtualType->parameters.clear(); 217 cloneAll( structType->parameters, virtualType->parameters ); 218 } 219 return virtualType; 220 } 221 222 } // namespace 112 223 113 224 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 114 assertf( castExpr-> get_result(), "Virtual Cast target not found before expansion." );225 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); 115 226 116 227 assert( vcast_decl ); 117 228 assert( pvt_decl ); 118 229 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; 230 const Type * vtable_type = getVirtualTableType( castExpr ); 231 ObjectDecl * table = indexer.lookup( vtable_type ); 232 if ( nullptr == table ) { 233 SemanticError( castLocation( castExpr ), 234 "Could not find virtual table instance." ); 235 } 140 236 141 237 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 238 new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), { 150 239 new CastExpr( … … 163 252 castExpr->set_result( nullptr ); 164 253 delete castExpr; 254 delete vtable_type; 165 255 return result; 166 256 }
Note: See TracChangeset
for help on using the changeset viewer.