Changes in src/Virtual/ExpandCasts.cc [c6b4432:bccd70a]
- File:
-
- 1 edited
-
src/Virtual/ExpandCasts.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
rc6b4432 rbccd70a 24 24 #include "AST/Expr.hpp" 25 25 #include "AST/Pass.hpp" 26 #include "Common/PassVisitor.h" // for PassVisitor 26 27 #include "Common/ScopedMap.h" // for ScopedMap 27 28 #include "Common/SemanticError.h" // for SemanticError 28 29 #include "SymTab/Mangler.h" // for mangleType 30 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 31 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... 32 #include "SynTree/Mutator.h" // for mutateAll 33 #include "SynTree/Type.h" // for Type, PointerType, StructInstType 34 #include "SynTree/Visitor.h" // for acceptAll 29 35 30 36 namespace Virtual { … … 37 43 } 38 44 45 bool is_type_id_object( const ObjectDecl * objectDecl ) { 46 const std::string & objectName = objectDecl->name; 47 return is_prefix( "__cfatid_", objectName ); 48 } 49 39 50 bool is_type_id_object( const ast::ObjectDecl * decl ) { 40 51 return is_prefix( "__cfatid_", decl->name ); … … 44 55 45 56 /// Maps virtual table types the instance for that type. 57 class VirtualTableMap final { 58 ScopedMap<std::string, ObjectDecl *> vtable_instances; 59 public: 60 void enterScope() { 61 vtable_instances.beginScope(); 62 } 63 void leaveScope() { 64 vtable_instances.endScope(); 65 } 66 67 ObjectDecl * insert( ObjectDecl * vtableDecl ) { 68 std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type ); 69 ObjectDecl *& value = vtable_instances[ mangledName ]; 70 if ( value ) { 71 if ( vtableDecl->storageClasses.is_extern ) { 72 return nullptr; 73 } else if ( ! value->storageClasses.is_extern ) { 74 return value; 75 } 76 } 77 value = vtableDecl; 78 return nullptr; 79 } 80 81 ObjectDecl * lookup( const Type * vtableType ) { 82 std::string const & mangledName = SymTab::Mangler::mangleType( vtableType ); 83 const auto it = vtable_instances.find( mangledName ); 84 return ( vtable_instances.end() == it ) ? nullptr : it->second; 85 } 86 }; 87 88 class VirtualCastCore { 89 CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) { 90 Type * type = new StructInstType( 91 Type::Qualifiers( Type::Const ), pvt_decl ); 92 for (int i = 0 ; i < level_of_indirection ; ++i) { 93 type = new PointerType( noQualifiers, type ); 94 } 95 return new CastExpr( expr, type ); 96 } 97 98 public: 99 VirtualCastCore() : 100 indexer(), vcast_decl( nullptr ), pvt_decl( nullptr ) 101 {} 102 103 void premutate( FunctionDecl * functionDecl ); 104 void premutate( StructDecl * structDecl ); 105 void premutate( ObjectDecl * objectDecl ); 106 107 Expression * postmutate( VirtualCastExpr * castExpr ); 108 109 VirtualTableMap indexer; 110 private: 111 FunctionDecl *vcast_decl; 112 StructDecl *pvt_decl; 113 }; 114 115 void VirtualCastCore::premutate( FunctionDecl * functionDecl ) { 116 if ( (! vcast_decl) && 117 functionDecl->get_name() == "__cfavir_virtual_cast" ) { 118 vcast_decl = functionDecl; 119 } 120 } 121 122 void VirtualCastCore::premutate( StructDecl * structDecl ) { 123 if ( pvt_decl || ! structDecl->has_body() ) { 124 return; 125 } else if ( structDecl->get_name() == "__cfavir_type_info" ) { 126 pvt_decl = structDecl; 127 } 128 } 129 130 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 131 if ( is_type_id_object( objectDecl ) ) { 132 // Multiple definitions should be fine because of linkonce. 133 indexer.insert( objectDecl ); 134 } 135 } 136 137 /// Better error locations for generated casts. 138 CodeLocation castLocation( const VirtualCastExpr * castExpr ) { 139 if ( castExpr->location.isSet() ) { 140 return castExpr->location; 141 } else if ( castExpr->arg->location.isSet() ) { 142 return castExpr->arg->location; 143 } else if ( castExpr->result->location.isSet() ) { 144 return castExpr->result->location; 145 } else { 146 return CodeLocation(); 147 } 148 } 149 150 [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) { 151 SemanticError( castLocation( castExpr ), message ); 152 } 153 154 /// Get the base type from a pointer or reference. 155 const Type * getBaseType( const Type * type ) { 156 if ( auto target = dynamic_cast<const PointerType *>( type ) ) { 157 return target->base; 158 } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) { 159 return target->base; 160 } else { 161 return nullptr; 162 } 163 } 164 165 /* Attempt to follow the "head" field of the structure to get the... 166 * Returns nullptr on error, otherwise owner must free returned node. 167 */ 168 StructInstType * followHeadPointerType( 169 const StructInstType * oldType, 170 const std::string& fieldName, 171 const CodeLocation& errorLocation ) { 172 173 // First section of the function is all about trying to fill this variable in. 174 StructInstType * newType = nullptr; 175 { 176 const StructDecl * oldDecl = oldType->baseStruct; 177 assert( oldDecl ); 178 179 // Helper function for throwing semantic errors. 180 auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) { 181 const std::string& context = "While following head pointer of " + 182 oldDecl->name + " named '" + fieldName + "': "; 183 SemanticError( errorLocation, context + message ); 184 }; 185 186 if ( oldDecl->members.empty() ) { 187 throwError( "Type has no fields." ); 188 } 189 const Declaration * memberDecl = oldDecl->members.front(); 190 assert( memberDecl ); 191 const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl ); 192 assert( fieldDecl ); 193 if ( fieldName != fieldDecl->name ) { 194 throwError( "Head field did not have expected name." ); 195 } 196 197 const Type * fieldType = fieldDecl->type; 198 if ( nullptr == fieldType ) { 199 throwError( "Could not get head field." ); 200 } 201 const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType ); 202 if ( nullptr == ptrType ) { 203 throwError( "First field is not a pointer type." ); 204 } 205 assert( ptrType->base ); 206 newType = dynamic_cast<StructInstType *>( ptrType->base ); 207 if ( nullptr == newType ) { 208 throwError( "First field does not point to a structure type." ); 209 } 210 } 211 212 // Now we can look into copying it. 213 newType = newType->clone(); 214 if ( ! oldType->parameters.empty() ) { 215 deleteAll( newType->parameters ); 216 newType->parameters.clear(); 217 cloneAll( oldType->parameters, newType->parameters ); 218 } 219 return newType; 220 } 221 222 /// Get the type-id type from a virtual type. 223 StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) { 224 const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type ); 225 if ( nullptr == typeInst ) { 226 return nullptr; 227 } 228 StructInstType * tableInst = 229 followHeadPointerType( typeInst, "virtual_table", errorLocation ); 230 if ( nullptr == tableInst ) { 231 return nullptr; 232 } 233 StructInstType * typeIdInst = 234 followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation ); 235 delete tableInst; 236 return typeIdInst; 237 } 238 239 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 240 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); 241 242 assert( vcast_decl ); 243 assert( pvt_decl ); 244 245 const Type * base_type = getBaseType( castExpr->result ); 246 if ( nullptr == base_type ) { 247 castError( castExpr, "Virtual cast target must be a pointer or reference type." ); 248 } 249 const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) ); 250 if ( nullptr == type_id_type ) { 251 castError( castExpr, "Ill formed virtual cast target type." ); 252 } 253 ObjectDecl * type_id = indexer.lookup( type_id_type ); 254 delete type_id_type; 255 if ( nullptr == type_id ) { 256 castError( castExpr, "Virtual cast does not target a virtual type." ); 257 } 258 259 Expression * result = new CastExpr( 260 new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), { 261 cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ), 262 cast_to_type_id( castExpr->get_arg(), 2 ), 263 } ), 264 castExpr->get_result()->clone() 265 ); 266 267 castExpr->set_arg( nullptr ); 268 castExpr->set_result( nullptr ); 269 delete castExpr; 270 return result; 271 } 46 272 47 273 /// Better error locations for generated casts. … … 268 494 } // namespace 269 495 496 void expandCasts( std::list< Declaration * > & translationUnit ) { 497 PassVisitor<VirtualCastCore> translator; 498 mutateAll( translationUnit, translator ); 499 } 500 270 501 void expandCasts( ast::TranslationUnit & translationUnit ) { 271 502 ast::Pass<ExpandCastsCore>::run( translationUnit );
Note:
See TracChangeset
for help on using the changeset viewer.