Changeset 8941b6b


Ignore:
Timestamp:
Oct 25, 2023, 6:33:25 PM (9 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
bef4f1a
Parents:
d22bf87
Message:

Direct translation of code generation.

Location:
src
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.cpp

    rd22bf87 r8941b6b  
    2020#include <unordered_map>
    2121
     22#include "CodeGen/FixMain.h"   // for FixMain
    2223#include "Common/Eval.h"       // for eval
    2324
     
    7576        }
    7677        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        }
    7784}
    7885
     
    101108        }
    102109        this->type = type;
     110        // See note above about this hack.
     111        if ( name == "main" ) {
     112                this->linkage = CodeGen::FixMain::getMainLinkage();
     113        }
    103114}
    104115
  • src/CodeGen/FixMain.h

    rd22bf87 r8941b6b  
    2020#include <list>
    2121
     22#include "AST/LinkageSpec.hpp"
    2223#include "SynTree/LinkageSpec.h"
    2324
     
    3435        static inline LinkageSpec::Spec mainLinkage() {
    3536                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;
    3640        }
    3741
  • src/CodeGen/GenType.cc

    rd22bf87 r8941b6b  
    1919#include <sstream>                // for operator<<, ostringstream, basic_os...
    2020
     21#include "AST/Print.hpp"          // for print
     22#include "AST/Vector.hpp"         // for vector
    2123#include "CodeGenerator.h"        // for CodeGenerator
     24#include "CodeGeneratorNew.hpp"   // for CodeGenerator_new
    2225#include "SynTree/Declaration.h"  // for DeclarationWithType
    2326#include "SynTree/Expression.h"   // for Expression
     
    352355                } // if
    353356        }
     357
     358namespace {
     359
     360#warning Remove the _new when old version is removed.
     361struct 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
     390private:
     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
     399GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
     400
     401void 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
     407void 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
     413void GenType_new::postvisit( ast::VoidType const * type ) {
     414        result = "void " + result;
     415        handleQualifiers( type );
     416}
     417
     418void 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
     425void 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
     463void 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
     477void GenType_new::postvisit( ast::ArrayType const * type ) {
     478        genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
     479}
     480
     481void 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
     488void 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
     536std::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
     548void 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
     554void 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
     560void 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
     572void 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
     578void 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
     591void GenType_new::postvisit( ast::VarArgsType const * type ) {
     592        result = "__builtin_va_list " + result;
     593        handleQualifiers( type );
     594}
     595
     596void 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
     602void 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
     608void GenType_new::postvisit( ast::GlobalScopeType const * type ) {
     609        assertf( !options.genC, "GlobalScopeType should not reach code generation." );
     610        handleQualifiers( type );
     611}
     612
     613void 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
     619void 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
     628void 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
     636void 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
     644void 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
     659std::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
     674std::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
     684std::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
    354688} // namespace CodeGen
    355689
  • src/CodeGen/GenType.h

    rd22bf87 r8941b6b  
    2121
    2222class Type;
     23namespace ast {
     24        class Type;
     25}
    2326
    2427namespace CodeGen {
     
    2629        std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false );
    2730        std::string genPrettyType( Type * type, const std::string & baseString );
     31
     32std::string genType( ast::Type const * type, const std::string & base, const Options & options );
     33std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options );
     34
    2835} // namespace CodeGen
    2936
  • src/CodeGen/Generate.cc

    rd22bf87 r8941b6b  
    1919#include <string>                    // for operator<<
    2020
     21#include "CodeGeneratorNew.hpp"      // for CodeGenerator_new, doSemicolon, ...
    2122#include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
    2223#include "GenType.h"                 // for genPrettyType
     
    9394                }
    9495        } // namespace
     96
     97namespace {
     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
     119void 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
    95138} // namespace CodeGen
    96139
  • src/CodeGen/Generate.h

    rd22bf87 r8941b6b  
    2222class Declaration;
    2323
     24namespace ast {
     25        class TranslationUnit;
     26}
     27
    2428namespace CodeGen {
    2529        /// 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.)
     
    2832        /// Generate code for a single node -- helpful for debugging in gdb
    2933        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.
     41void generate( ast::TranslationUnit & transUnit, std::ostream &os, bool doIntrinsics,
     42                bool pretty, bool generateC, bool lineMarks, bool printExprTypes );
     43
    3044} // namespace CodeGen
    3145
  • src/CodeGen/module.mk

    rd22bf87 r8941b6b  
    2424        CodeGen/CodeGenerator.cc \
    2525        CodeGen/CodeGenerator.h \
     26        CodeGen/CodeGeneratorNew.cpp \
     27        CodeGen/CodeGeneratorNew.hpp \
    2628        CodeGen/Generate.cc \
    2729        CodeGen/Generate.h \
  • src/main.cc

    rd22bf87 r8941b6b  
    427427                PASS( "Link-Once", CodeGen::translateLinkOnce, transUnit );
    428428
    429                 translationUnit = convert( std::move( transUnit ) );
    430 
    431429                // Code has been lowered to C, now we can start generation.
    432430
    433                 DUMP( bcodegenp, translationUnit );
     431                DUMP( bcodegenp, std::move( transUnit ) );
    434432
    435433                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    437435                } // if
    438436
    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 ) );
    441440
    442441                CodeGen::FixMain::fix( translationUnit, *output,
Note: See TracChangeset for help on using the changeset viewer.