Changeset 8941b6b
- Timestamp:
- Oct 25, 2023, 6:33:25 PM (14 months ago)
- Branches:
- master
- Children:
- bef4f1a
- Parents:
- d22bf87
- Location:
- src
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Decl.cpp
rd22bf87 r8941b6b 20 20 #include <unordered_map> 21 21 22 #include "CodeGen/FixMain.h" // for FixMain 22 23 #include "Common/Eval.h" // for eval 23 24 … … 75 76 } 76 77 this->type = ftype; 78 // Hack forcing the function "main" to have Cforall linkage to replace 79 // main even if it is inside an extern "C", and also makes sure the 80 // replacing function is always a C function. 81 if ( name == "main" ) { 82 this->linkage = CodeGen::FixMain::getMainLinkage(); 83 } 77 84 } 78 85 … … 101 108 } 102 109 this->type = type; 110 // See note above about this hack. 111 if ( name == "main" ) { 112 this->linkage = CodeGen::FixMain::getMainLinkage(); 113 } 103 114 } 104 115 -
src/CodeGen/FixMain.h
rd22bf87 r8941b6b 20 20 #include <list> 21 21 22 #include "AST/LinkageSpec.hpp" 22 23 #include "SynTree/LinkageSpec.h" 23 24 … … 34 35 static inline LinkageSpec::Spec mainLinkage() { 35 36 return replace_main ? LinkageSpec::Cforall : LinkageSpec::C; 37 } 38 static inline ast::Linkage::Spec getMainLinkage() { 39 return replace_main ? ast::Linkage::Cforall : ast::Linkage::C; 36 40 } 37 41 -
src/CodeGen/GenType.cc
rd22bf87 r8941b6b 19 19 #include <sstream> // for operator<<, ostringstream, basic_os... 20 20 21 #include "AST/Print.hpp" // for print 22 #include "AST/Vector.hpp" // for vector 21 23 #include "CodeGenerator.h" // for CodeGenerator 24 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new 22 25 #include "SynTree/Declaration.h" // for DeclarationWithType 23 26 #include "SynTree/Expression.h" // for Expression … … 352 355 } // if 353 356 } 357 358 namespace { 359 360 #warning Remove the _new when old version is removed. 361 struct GenType_new : 362 public ast::WithShortCircuiting, 363 public ast::WithVisitorRef<GenType_new> { 364 std::string result; 365 GenType_new( const std::string &typeString, const Options &options ); 366 367 void previsit( ast::Node const * ); 368 void postvisit( ast::Node const * ); 369 370 void postvisit( ast::FunctionType const * type ); 371 void postvisit( ast::VoidType const * type ); 372 void postvisit( ast::BasicType const * type ); 373 void postvisit( ast::PointerType const * type ); 374 void postvisit( ast::ArrayType const * type ); 375 void postvisit( ast::ReferenceType const * type ); 376 void postvisit( ast::StructInstType const * type ); 377 void postvisit( ast::UnionInstType const * type ); 378 void postvisit( ast::EnumInstType const * type ); 379 void postvisit( ast::TypeInstType const * type ); 380 void postvisit( ast::TupleType const * type ); 381 void postvisit( ast::VarArgsType const * type ); 382 void postvisit( ast::ZeroType const * type ); 383 void postvisit( ast::OneType const * type ); 384 void postvisit( ast::GlobalScopeType const * type ); 385 void postvisit( ast::TraitInstType const * type ); 386 void postvisit( ast::TypeofType const * type ); 387 void postvisit( ast::VTableType const * type ); 388 void postvisit( ast::QualifiedType const * type ); 389 390 private: 391 void handleQualifiers( ast::Type const *type ); 392 std::string handleGeneric( ast::BaseInstType const * type ); 393 void genArray( const ast::CV::Qualifiers &qualifiers, ast::Type const *base, ast::Expr const *dimension, bool isVarLen, bool isStatic ); 394 std::string genParamList( const ast::vector<ast::Type> & ); 395 396 Options options; 397 }; 398 399 GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {} 400 401 void GenType_new::previsit( ast::Node const * ) { 402 // Turn off automatic recursion for all nodes, to allow each visitor to 403 // precisely control the order in which its children are visited. 404 visit_children = false; 405 } 406 407 void GenType_new::postvisit( ast::Node const * node ) { 408 std::stringstream ss; 409 ast::print( ss, node ); 410 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() ); 411 } 412 413 void GenType_new::postvisit( ast::VoidType const * type ) { 414 result = "void " + result; 415 handleQualifiers( type ); 416 } 417 418 void GenType_new::postvisit( ast::BasicType const * type ) { 419 ast::BasicType::Kind kind = type->kind; 420 assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES ); 421 result = std::string( ast::BasicType::typeNames[kind] ) + " " + result; 422 handleQualifiers( type ); 423 } 424 425 void GenType_new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) { 426 std::ostringstream os; 427 if ( result != "" ) { 428 if ( result[ 0 ] == '*' ) { 429 os << "(" << result << ")"; 430 } else { 431 os << result; 432 } 433 } 434 os << "["; 435 if ( isStatic ) { 436 os << "static "; 437 } 438 if ( qualifiers.is_const ) { 439 os << "const "; 440 } 441 if ( qualifiers.is_volatile ) { 442 os << "volatile "; 443 } 444 if ( qualifiers.is_restrict ) { 445 os << "__restrict "; 446 } 447 if ( qualifiers.is_atomic ) { 448 os << "_Atomic "; 449 } 450 if ( dimension != 0 ) { 451 ast::Pass<CodeGenerator_new>::read( dimension, os, options ); 452 } else if ( isVarLen ) { 453 // no dimension expression on a VLA means it came in with the * token 454 os << "*"; 455 } 456 os << "]"; 457 458 result = os.str(); 459 460 base->accept( *visitor ); 461 } 462 463 void GenType_new::postvisit( ast::PointerType const * type ) { 464 if ( type->isStatic || type->isVarLen || type->dimension ) { 465 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 466 } else { 467 handleQualifiers( type ); 468 if ( result[ 0 ] == '?' ) { 469 result = "* " + result; 470 } else { 471 result = "*" + result; 472 } 473 type->base->accept( *visitor ); 474 } 475 } 476 477 void GenType_new::postvisit( ast::ArrayType const * type ) { 478 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 479 } 480 481 void GenType_new::postvisit( ast::ReferenceType const * type ) { 482 assertf( !options.genC, "Reference types should not reach code generation." ); 483 handleQualifiers( type ); 484 result = "&" + result; 485 type->base->accept( *visitor ); 486 } 487 488 void GenType_new::postvisit( ast::FunctionType const * type ) { 489 std::ostringstream os; 490 491 if ( result != "" ) { 492 if ( result[ 0 ] == '*' ) { 493 os << "(" << result << ")"; 494 } else { 495 os << result; 496 } 497 } 498 499 if ( type->params.empty() ) { 500 if ( type->isVarArgs ) { 501 os << "()"; 502 } else { 503 os << "(void)"; 504 } 505 } else { 506 os << "(" ; 507 508 os << genParamList( type->params ); 509 510 if ( type->isVarArgs ) { 511 os << ", ..."; 512 } 513 os << ")"; 514 } 515 516 result = os.str(); 517 518 if ( type->returns.size() == 0 ) { 519 result = "void " + result; 520 } else { 521 type->returns.front()->accept( *visitor ); 522 } 523 524 // Add forall clause. 525 if( !type->forall.empty() && !options.genC ) { 526 //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." ); 527 std::ostringstream os; 528 ast::Pass<CodeGenerator_new> cg( os, options ); 529 os << "forall("; 530 cg.core.genCommaList( type->forall ); 531 os << ")" << std::endl; 532 result = os.str() + result; 533 } 534 } 535 536 std::string GenType_new::handleGeneric( ast::BaseInstType const * type ) { 537 if ( !type->params.empty() ) { 538 std::ostringstream os; 539 ast::Pass<CodeGenerator_new> cg( os, options ); 540 os << "("; 541 cg.core.genCommaList( type->params ); 542 os << ") "; 543 return os.str(); 544 } 545 return ""; 546 } 547 548 void GenType_new::postvisit( ast::StructInstType const * type ) { 549 result = type->name + handleGeneric( type ) + " " + result; 550 if ( options.genC ) result = "struct " + result; 551 handleQualifiers( type ); 552 } 553 554 void GenType_new::postvisit( ast::UnionInstType const * type ) { 555 result = type->name + handleGeneric( type ) + " " + result; 556 if ( options.genC ) result = "union " + result; 557 handleQualifiers( type ); 558 } 559 560 void GenType_new::postvisit( ast::EnumInstType const * type ) { 561 if ( type->base && type->base->base ) { 562 result = genType( type->base->base, result, options ); 563 } else { 564 result = type->name + " " + result; 565 if ( options.genC ) { 566 result = "enum " + result; 567 } 568 } 569 handleQualifiers( type ); 570 } 571 572 void GenType_new::postvisit( ast::TypeInstType const * type ) { 573 assertf( !options.genC, "TypeInstType should not reach code generation." ); 574 result = type->name + " " + result; 575 handleQualifiers( type ); 576 } 577 578 void GenType_new::postvisit( ast::TupleType const * type ) { 579 assertf( !options.genC, "TupleType should not reach code generation." ); 580 unsigned int i = 0; 581 std::ostringstream os; 582 os << "["; 583 for ( ast::ptr<ast::Type> const & t : type->types ) { 584 i++; 585 os << genType( t, "", options ) << (i == type->size() ? "" : ", "); 586 } 587 os << "] "; 588 result = os.str() + result; 589 } 590 591 void GenType_new::postvisit( ast::VarArgsType const * type ) { 592 result = "__builtin_va_list " + result; 593 handleQualifiers( type ); 594 } 595 596 void GenType_new::postvisit( ast::ZeroType const * type ) { 597 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 598 result = (options.pretty ? "zero_t " : "long int ") + result; 599 handleQualifiers( type ); 600 } 601 602 void GenType_new::postvisit( ast::OneType const * type ) { 603 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 604 result = (options.pretty ? "one_t " : "long int ") + result; 605 handleQualifiers( type ); 606 } 607 608 void GenType_new::postvisit( ast::GlobalScopeType const * type ) { 609 assertf( !options.genC, "GlobalScopeType should not reach code generation." ); 610 handleQualifiers( type ); 611 } 612 613 void GenType_new::postvisit( ast::TraitInstType const * type ) { 614 assertf( !options.genC, "TraitInstType should not reach code generation." ); 615 result = type->name + " " + result; 616 handleQualifiers( type ); 617 } 618 619 void GenType_new::postvisit( ast::TypeofType const * type ) { 620 std::ostringstream os; 621 os << "typeof("; 622 ast::Pass<CodeGenerator_new>::read( type, os, options ); 623 os << ") " << result; 624 result = os.str(); 625 handleQualifiers( type ); 626 } 627 628 void GenType_new::postvisit( ast::VTableType const * type ) { 629 assertf( !options.genC, "Virtual table types should not reach code generation." ); 630 std::ostringstream os; 631 os << "vtable(" << genType( type->base, "", options ) << ") " << result; 632 result = os.str(); 633 handleQualifiers( type ); 634 } 635 636 void GenType_new::postvisit( ast::QualifiedType const * type ) { 637 assertf( !options.genC, "QualifiedType should not reach code generation." ); 638 std::ostringstream os; 639 os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result; 640 result = os.str(); 641 handleQualifiers( type ); 642 } 643 644 void GenType_new::handleQualifiers( ast::Type const * type ) { 645 if ( type->is_const() ) { 646 result = "const " + result; 647 } 648 if ( type->is_volatile() ) { 649 result = "volatile " + result; 650 } 651 if ( type->is_restrict() ) { 652 result = "__restrict " + result; 653 } 654 if ( type->is_atomic() ) { 655 result = "_Atomic " + result; 656 } 657 } 658 659 std::string GenType_new::genParamList( const ast::vector<ast::Type> & range ) { 660 auto cur = range.begin(); 661 auto end = range.end(); 662 if ( cur == end ) return ""; 663 std::ostringstream oss; 664 for ( unsigned int i = 0 ; ; ++i ) { 665 oss << genType( *cur++, "__param_" + std::to_string(i), options ); 666 if ( cur == end ) break; 667 oss << ", "; 668 } 669 return oss.str(); 670 } 671 672 } // namespace 673 674 std::string genType( ast::Type const * type, const std::string & base, const Options & options ) { 675 std::ostringstream os; 676 if ( !type->attributes.empty() ) { 677 ast::Pass<CodeGenerator_new> cg( os, options ); 678 cg.core.genAttributes( type->attributes ); 679 } 680 681 return os.str() + ast::Pass<GenType_new>::read( type, base, options ); 682 } 683 684 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) { 685 return ast::Pass<GenType_new>::read( type, base, options ); 686 } 687 354 688 } // namespace CodeGen 355 689 -
src/CodeGen/GenType.h
rd22bf87 r8941b6b 21 21 22 22 class Type; 23 namespace ast { 24 class Type; 25 } 23 26 24 27 namespace CodeGen { … … 26 29 std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false ); 27 30 std::string genPrettyType( Type * type, const std::string & baseString ); 31 32 std::string genType( ast::Type const * type, const std::string & base, const Options & options ); 33 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ); 34 28 35 } // namespace CodeGen 29 36 -
src/CodeGen/Generate.cc
rd22bf87 r8941b6b 19 19 #include <string> // for operator<< 20 20 21 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new, doSemicolon, ... 21 22 #include "CodeGenerator.h" // for CodeGenerator, doSemicolon, oper... 22 23 #include "GenType.h" // for genPrettyType … … 93 94 } 94 95 } // namespace 96 97 namespace { 98 bool shouldClean( ast::Decl const * decl ) { 99 return dynamic_cast<ast::TraitDecl const *>( decl ); 100 } 101 102 /// Removes various nodes that should not exist in CodeGen. 103 struct TreeCleaner_new { 104 ast::CompoundStmt const * previsit( ast::CompoundStmt const * stmt ) { 105 auto mutStmt = ast::mutate( stmt ); 106 erase_if( mutStmt->kids, []( ast::Stmt const * stmt ){ 107 auto declStmt = dynamic_cast<ast::DeclStmt const *>( stmt ); 108 return ( declStmt ) ? shouldClean( declStmt->decl ) : false; 109 } ); 110 return mutStmt; 111 } 112 113 ast::Stmt const * postvisit( ast::ImplicitCtorDtorStmt const * stmt ) { 114 return stmt->callStmt; 115 } 116 }; 117 } // namespace 118 119 void generate( ast::TranslationUnit & translationUnit, std::ostream & os, bool doIntrinsics, 120 bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) { 121 erase_if( translationUnit.decls, shouldClean ); 122 ast::Pass<TreeCleaner_new>::run( translationUnit ); 123 124 ast::Pass<CodeGenerator_new> cgv( os, 125 Options( pretty, generateC, lineMarks, printExprTypes ) ); 126 for ( auto & decl : translationUnit.decls ) { 127 if ( decl->linkage.is_generatable && (doIntrinsics || !decl->linkage.is_builtin ) ) { 128 cgv.core.updateLocation( decl ); 129 decl->accept( cgv ); 130 if ( doSemicolon( decl ) ) { 131 os << ";"; 132 } 133 os << cgv.core.endl; 134 } 135 } 136 } 137 95 138 } // namespace CodeGen 96 139 -
src/CodeGen/Generate.h
rd22bf87 r8941b6b 22 22 class Declaration; 23 23 24 namespace ast { 25 class TranslationUnit; 26 } 27 24 28 namespace CodeGen { 25 29 /// Generates code. doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.) … … 28 32 /// Generate code for a single node -- helpful for debugging in gdb 29 33 void generate( BaseSyntaxNode * node, std::ostream & os ); 34 35 /// Generates all code in transUnit and writing it to the os. 36 /// doIntrinsics: Should intrinsic functions be printed? 37 /// pretty: Format output nicely (e.g., uses unmangled names, etc.). 38 /// generateC: Make sure the output only consists of C code (allows some assertions, etc.) 39 /// lineMarks: Output line marks (processed line directives) in the output. 40 /// printExprTypes: Print the types of expressions in comments. 41 void generate( ast::TranslationUnit & transUnit, std::ostream &os, bool doIntrinsics, 42 bool pretty, bool generateC, bool lineMarks, bool printExprTypes ); 43 30 44 } // namespace CodeGen 31 45 -
src/CodeGen/module.mk
rd22bf87 r8941b6b 24 24 CodeGen/CodeGenerator.cc \ 25 25 CodeGen/CodeGenerator.h \ 26 CodeGen/CodeGeneratorNew.cpp \ 27 CodeGen/CodeGeneratorNew.hpp \ 26 28 CodeGen/Generate.cc \ 27 29 CodeGen/Generate.h \ -
src/main.cc
rd22bf87 r8941b6b 427 427 PASS( "Link-Once", CodeGen::translateLinkOnce, transUnit ); 428 428 429 translationUnit = convert( std::move( transUnit ) );430 431 429 // Code has been lowered to C, now we can start generation. 432 430 433 DUMP( bcodegenp, translationUnit);431 DUMP( bcodegenp, std::move( transUnit ) ); 434 432 435 433 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 437 435 } // if 438 436 439 CodeTools::fillLocations( translationUnit ); 440 PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ); 437 PASS( "Code Gen", CodeGen::generate, transUnit, *output, !genproto, prettycodegenp, true, linemarks, false ); 438 439 translationUnit = convert( std::move( transUnit ) ); 441 440 442 441 CodeGen::FixMain::fix( translationUnit, *output,
Note: See TracChangeset
for help on using the changeset viewer.