Changes in src/Virtual/ExpandCasts.cc [8f910430:c36814a]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
r8f910430 rc36814a 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 31 10:29:00 202013 // Update Count : 412 // Last Modified On : Thu Aug 11 12:06:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 20 20 #include <string> // for string, allocator, operator==, ope... 21 21 22 #include "AST/Decl.hpp" 23 #include "AST/Expr.hpp" 24 #include "AST/Pass.hpp" 22 25 #include "Common/PassVisitor.h" // for PassVisitor 23 26 #include "Common/ScopedMap.h" // for ScopedMap … … 32 35 namespace Virtual { 33 36 34 static bool is_prefix( const std::string & prefix, const std::string& entire ) { 37 namespace { 38 39 bool is_prefix( const std::string & prefix, const std::string& entire ) { 35 40 size_t const p_size = prefix.size(); 36 41 return (p_size < entire.size() && prefix == entire.substr(0, p_size)); 37 42 } 38 43 39 staticbool is_type_id_object( const ObjectDecl * objectDecl ) {44 bool is_type_id_object( const ObjectDecl * objectDecl ) { 40 45 const std::string & objectName = objectDecl->name; 41 46 return is_prefix( "__cfatid_", objectName ); 47 } 48 49 bool is_type_id_object( const ast::ObjectDecl * decl ) { 50 return is_prefix( "__cfatid_", decl->name ); 42 51 } 43 52 … … 124 133 } 125 134 } 126 127 namespace {128 135 129 136 /// Better error locations for generated casts. … … 229 236 } 230 237 231 } // namespace232 233 238 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 234 239 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); … … 265 270 } 266 271 267 void expandCasts( std::list< Declaration * > & translationUnit ) { 268 PassVisitor<VirtualCastCore> translator; 269 mutateAll( translationUnit, translator ); 270 } 271 } 272 /// Better error locations for generated casts. 273 // TODO: Does the improved distribution of code locations make this unneeded? 274 CodeLocation castLocation( const ast::VirtualCastExpr * castExpr ) { 275 if ( castExpr->location.isSet() ) { 276 return castExpr->location; 277 } else if ( castExpr->arg->location.isSet() ) { 278 return castExpr->arg->location; 279 } else { 280 return CodeLocation(); 281 } 282 } 283 284 [[noreturn]] void castError( ast::VirtualCastExpr const * castExpr, std::string const & message ) { 285 SemanticError( castLocation( castExpr ), message ); 286 } 287 288 class TypeIdTable final { 289 ScopedMap<std::string, ast::ObjectDecl const *> instances; 290 public: 291 void enterScope() { instances.beginScope(); } 292 void leaveScope() { instances.endScope(); } 293 294 // Attempt to insert an instance into the map. If there is a conflict, 295 // returns the previous declaration for error messages. 296 ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) { 297 std::string const & mangledName = 298 Mangle::mangle( typeIdDecl->type, Mangle::typeMode() ); 299 ast::ObjectDecl const *& value = instances[ mangledName ]; 300 if ( value ) { 301 if ( typeIdDecl->storage.is_extern ) { 302 return nullptr; 303 } else if ( !value->storage.is_extern ) { 304 return value; 305 } 306 } 307 value = typeIdDecl; 308 return nullptr; 309 } 310 311 ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) { 312 std::string const & mangledName = 313 Mangle::mangle( typeIdType, Mangle::typeMode() ); 314 auto const it = instances.find( mangledName ); 315 return ( instances.end() == it ) ? nullptr : it->second; 316 } 317 }; 318 319 struct ExpandCastsCore final { 320 void previsit( ast::FunctionDecl const * decl ); 321 void previsit( ast::StructDecl const * decl ); 322 void previsit( ast::ObjectDecl const * decl ); 323 ast::Expr const * postvisit( ast::VirtualCastExpr const * expr ); 324 325 ast::CastExpr const * cast_to_type_id( 326 ast::Expr const * expr, unsigned int level_of_indirection ); 327 328 ast::FunctionDecl const * vcast_decl = nullptr; 329 ast::StructDecl const * info_decl = nullptr; 330 331 TypeIdTable symtab; 332 }; 333 334 void ExpandCastsCore::previsit( ast::FunctionDecl const * decl ) { 335 if ( !vcast_decl && "__cfavir_virtual_cast" == decl->name ) { 336 vcast_decl = decl; 337 } 338 } 339 340 void ExpandCastsCore::previsit( ast::StructDecl const * decl ) { 341 if ( !info_decl && decl->body && "__cfavir_type_info" == decl->name ) { 342 info_decl = decl; 343 } 344 } 345 346 void ExpandCastsCore::previsit( ast::ObjectDecl const * decl ) { 347 if ( is_type_id_object( decl ) ) { 348 // Multiple definitions should be fine because of linkonce. 349 symtab.insert( decl ); 350 } 351 } 352 353 /// Get the base type from a pointer or reference. 354 ast::Type const * getBaseType( ast::ptr<ast::Type> const & type ) { 355 if ( auto target = type.as<ast::PointerType>() ) { 356 return target->base.get(); 357 } else if ( auto target = type.as<ast::ReferenceType>() ) { 358 return target->base.get(); 359 } else { 360 return nullptr; 361 } 362 } 363 364 /// Copy newType, but give the copy the params of the oldType. 365 ast::StructInstType * polyCopy( 366 ast::StructInstType const * oldType, 367 ast::StructInstType const * newType ) { 368 assert( oldType->params.size() == newType->params.size() ); 369 ast::StructInstType * retType = ast::deepCopy( newType ); 370 if ( ! oldType->params.empty() ) { 371 retType->params.clear(); 372 for ( auto oldParams : oldType->params ) { 373 retType->params.push_back( ast::deepCopy( oldParams ) ); 374 } 375 } 376 return retType; 377 } 378 379 /// Follow the "head" field of the structure to get the type that is pointed 380 /// to by that field. 381 ast::StructInstType const * followHeadPointerType( 382 CodeLocation const & errorLocation, 383 ast::StructInstType const * oldType, 384 std::string const & fieldName ) { 385 ast::StructDecl const * oldDecl = oldType->base; 386 assert( oldDecl ); 387 388 // Helper function for throwing semantic errors. 389 auto throwError = [&fieldName, &errorLocation, &oldDecl]( 390 std::string const & message ) { 391 std::string const & context = "While following head pointer of " + 392 oldDecl->name + " named '" + fieldName + "': "; 393 SemanticError( errorLocation, context + message ); 394 }; 395 396 if ( oldDecl->members.empty() ) { 397 throwError( "Type has no fields." ); 398 } 399 ast::ptr<ast::Decl> const & memberDecl = oldDecl->members.front(); 400 assert( memberDecl ); 401 ast::ObjectDecl const * fieldDecl = memberDecl.as<ast::ObjectDecl>(); 402 assert( fieldDecl ); 403 if ( fieldName != fieldDecl->name ) { 404 throwError( "Head field did not have expected name." ); 405 } 406 407 ast::ptr<ast::Type> const & fieldType = fieldDecl->type; 408 if ( nullptr == fieldType ) { 409 throwError( "Could not get head field." ); 410 } 411 auto ptrType = fieldType.as<ast::PointerType>(); 412 if ( nullptr == ptrType ) { 413 throwError( "First field is not a pointer type." ); 414 } 415 assert( ptrType->base ); 416 auto newType = ptrType->base.as<ast::StructInstType>(); 417 if ( nullptr == newType ) { 418 throwError( "First field does not point to a structure type." ); 419 } 420 421 return polyCopy( oldType, newType ); 422 } 423 424 /// Get the type-id type from a virtual type. 425 ast::StructInstType const * getTypeIdType( 426 CodeLocation const & errorLocation, 427 ast::Type const * type ) { 428 auto typeInst = dynamic_cast<ast::StructInstType const *>( type ); 429 if ( nullptr == typeInst ) { 430 return nullptr; 431 } 432 ast::ptr<ast::StructInstType> tableInst = 433 followHeadPointerType( errorLocation, typeInst, "virtual_table" ); 434 if ( nullptr == tableInst ) { 435 return nullptr; 436 } 437 ast::StructInstType const * typeIdInst = 438 followHeadPointerType( errorLocation, tableInst, "__cfavir_typeid" ); 439 return typeIdInst; 440 } 441 442 ast::Expr const * ExpandCastsCore::postvisit( 443 ast::VirtualCastExpr const * expr ) { 444 assertf( expr->result, "Virtual cast target not found before expansion." ); 445 446 assert( vcast_decl ); 447 assert( info_decl ); 448 449 ast::Type const * base_type = getBaseType( expr->result ); 450 if ( nullptr == base_type ) { 451 castError( expr, "Virtual cast target must be a pointer or reference type." ); 452 } 453 ast::StructInstType const * type_id_type = 454 getTypeIdType( castLocation( expr ), base_type ); 455 if ( nullptr == type_id_type ) { 456 castError( expr, "Ill formed virtual cast target type." ); 457 } 458 ast::ObjectDecl const * type_id = symtab.lookup( type_id_type ); 459 if ( nullptr == type_id ) { 460 // I'm trying to give a different error for polymorpic types as 461 // different things can go wrong there. 462 if ( type_id_type->params.empty() ) { 463 castError( expr, "Virtual cast does not target a virtual type." ); 464 } else { 465 castError( expr, "Virtual cast does not target a type with a " 466 "type id (possible missing virtual table)." ); 467 } 468 } 469 470 return new ast::CastExpr( expr->location, 471 new ast::ApplicationExpr( expr->location, 472 ast::VariableExpr::functionPointer( expr->location, vcast_decl ), 473 { 474 cast_to_type_id( 475 new ast::AddressExpr( expr->location, 476 new ast::VariableExpr( expr->location, type_id ) ), 477 1 ), 478 cast_to_type_id( expr->arg, 2 ), 479 } 480 ), 481 ast::deepCopy( expr->result ) 482 ); 483 } 484 485 ast::CastExpr const * ExpandCastsCore::cast_to_type_id( 486 ast::Expr const * expr, unsigned int level_of_indirection ) { 487 assert( info_decl ); 488 ast::Type * type = new ast::StructInstType( info_decl, ast::CV::Const ); 489 for ( unsigned int i = 0 ; i < level_of_indirection ; ++i ) { 490 type = new ast::PointerType( type ); 491 } 492 return new ast::CastExpr( expr->location, expr, type ); 493 } 494 495 } // namespace 496 497 void expandCasts( std::list< Declaration * > & translationUnit ) { 498 PassVisitor<VirtualCastCore> translator; 499 mutateAll( translationUnit, translator ); 500 } 501 502 void expandCasts( ast::TranslationUnit & translationUnit ) { 503 ast::Pass<ExpandCastsCore>::run( translationUnit ); 504 } 505 506 } // namespace Virtual
Note:
See TracChangeset
for help on using the changeset viewer.