Changeset fc12f05 for src/CodeGen


Ignore:
Timestamp:
Nov 13, 2023, 3:43:43 AM (23 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
25f2798
Parents:
0030b508 (diff), 2174191 (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/CodeGen
Files:
2 added
3 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/FixMain.cc

    r0030b508 rfc12f05  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixMain.cc --
     7// FixMain.cc -- Tools to change a Cforall main into a C main.
    88//
    99// Author           : Thierry Delisle
     
    1313// Update Count     : 0
    1414//
    15 
    1615
    1716#include "FixMain.h"
     
    2322
    2423#include "AST/Decl.hpp"
     24#include "AST/Pass.hpp"
    2525#include "AST/Type.hpp"
    26 #include "Common/PassVisitor.h"
     26#include "AST/Vector.hpp"
    2727#include "Common/SemanticError.h"  // for SemanticError
    2828#include "CodeGen/GenType.h"       // for GenType
    29 #include "SynTree/Declaration.h"   // for FunctionDecl, operator<<
    30 #include "SynTree/Type.h"          // for FunctionType
    3129#include "SymTab/Mangler.h"
    3230
     
    3533namespace {
    3634
    37 struct FindMainCore {
    38         FunctionDecl * main_signature = nullptr;
     35struct FindMainCore final {
     36        ast::FunctionDecl const * main_declaration = nullptr;
    3937
    40         void previsit( FunctionDecl * decl ) {
    41                 if ( FixMain::isMain( decl ) ) {
    42                         if ( main_signature ) {
     38        void previsit( ast::FunctionDecl const * decl ) {
     39                if ( isMain( decl ) ) {
     40                        if ( main_declaration ) {
    4341                                SemanticError( decl, "Multiple definition of main routine\n" );
    4442                        }
    45                         main_signature = decl;
     43                        main_declaration = decl;
    4644                }
    4745        }
    4846};
    4947
     48std::string genTypeAt( const ast::vector<ast::Type> & types, size_t at ) {
     49        return genType( types[at], "", Options( false, false, false, false ) );
    5050}
    5151
    52         template<typename container>
    53         std::string genTypeAt(const container& p, size_t idx) {
    54                 return genType((*std::next(p.begin(), idx))->get_type(), "");
    55         }
    56 
    57         void FixMain::fix( std::list< Declaration * > & translationUnit,
    58                         std::ostream &os, const char* bootloader_filename ) {
    59                 PassVisitor< FindMainCore > main_finder;
    60                 acceptAll( translationUnit, main_finder );
    61                 FunctionDecl * main_signature = main_finder.pass.main_signature;
    62 
    63                 if( main_signature ) {
    64                         os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
    65                         main_signature->mangleName = SymTab::Mangler::mangle(main_signature);
    66 
    67                         os << main_signature->get_scopedMangleName() << "(";
    68                         const auto& params = main_signature->get_functionType()->get_parameters();
    69                         switch(params.size()) {
    70                                 case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break;
    71                                 case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break;
    72                                 case 0: break;
    73                                 default : assert(false);
    74                         }
    75                         os << "); }\n";
    76 
    77                         std::ifstream bootloader(bootloader_filename, std::ios::in);
    78                         assertf( bootloader.is_open(), "cannot open bootloader.c\n" );
    79                         os << bootloader.rdbuf();
    80                 }
    81         }
    82 
    83 namespace {
    84 
    85 ObjectDecl * signedIntObj() {
    86         return new ObjectDecl(
    87                 "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
    88                 new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr );
     52ast::ObjectDecl * makeIntObj(){
     53        return new ast::ObjectDecl( CodeLocation(), "",
     54                new ast::BasicType( ast::BasicType::SignedInt ) );
    8955}
    9056
    91 ObjectDecl * makeArgvObj() {
    92         return new ObjectDecl(
    93                 "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
    94                 new PointerType( Type::Qualifiers(),
    95                         new PointerType( Type::Qualifiers(),
    96                                 new BasicType( Type::Qualifiers(), BasicType::Char ) ) ),
    97                 nullptr );
     57ast::ObjectDecl * makeCharStarStarObj() {
     58        return new ast::ObjectDecl( CodeLocation(), "",
     59                new ast::PointerType(
     60                        new ast::PointerType(
     61                                new ast::BasicType( ast::BasicType::Char ) ) ) );
    9862}
    9963
    100 std::string create_mangled_main_function_name( FunctionType * function_type ) {
    101         std::unique_ptr<FunctionDecl> decl( new FunctionDecl(
    102                 "main", Type::StorageClasses(), LinkageSpec::Cforall,
    103                 function_type, nullptr ) );
    104         return SymTab::Mangler::mangle( decl.get() );
     64std::string getMangledNameOfMain(
     65                ast::vector<ast::DeclWithType> && params, ast::ArgumentFlag isVarArgs ) {
     66        ast::ptr<ast::FunctionDecl> decl = new ast::FunctionDecl(
     67                CodeLocation(),
     68                "main",
     69                ast::vector<ast::TypeDecl>(),
     70                ast::vector<ast::DeclWithType>(),
     71                std::move( params ),
     72                { makeIntObj() },
     73                nullptr,
     74                ast::Storage::Classes(),
     75                ast::Linkage::Spec(),
     76                ast::vector<ast::Attribute>(),
     77                ast::Function::Specs(),
     78                isVarArgs
     79        );
     80        return Mangle::mangle( decl.get() );
    10581}
    10682
    107 std::string mangled_0_argument_main() {
    108         FunctionType* main_type = new FunctionType( Type::Qualifiers(), true );
    109         main_type->get_returnVals().push_back( signedIntObj() );
    110         return create_mangled_main_function_name( main_type );
     83std::string getMangledNameOf0ParameterMain() {
     84        return getMangledNameOfMain( {}, ast::VariableArgs );
    11185}
    11286
    113 std::string mangled_2_argument_main() {
    114         FunctionType* main_type = new FunctionType( Type::Qualifiers(), false );
    115         main_type->get_returnVals().push_back( signedIntObj() );
    116         main_type->get_parameters().push_back( signedIntObj() );
    117         main_type->get_parameters().push_back( makeArgvObj() );
    118         return create_mangled_main_function_name( main_type );
     87std::string getMangledNameOf2ParameterMain() {
     88        return getMangledNameOfMain( {
     89                makeIntObj(),
     90                makeCharStarStarObj(),
     91        }, ast::FixedArgs );
    11992}
    12093
     
    12295        // This breaks if you move it out of the function.
    12396        static const std::string mangled_mains[] = {
    124                 mangled_0_argument_main(),
    125                 mangled_2_argument_main(),
    126                 //mangled_3_argument_main(),
     97                getMangledNameOf0ParameterMain(),
     98                getMangledNameOf2ParameterMain(),
     99                //getMangledNameOf3ParameterMain(),
    127100        };
    128101
     
    133106}
    134107
     108struct FixLinkageCore final {
     109        ast::Linkage::Spec const spec;
     110        FixLinkageCore( ast::Linkage::Spec spec ) : spec( spec ) {}
     111
     112        ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl ) {
     113                if ( decl->name != "main" ) return decl;
     114                return ast::mutate_field( decl, &ast::FunctionDecl::linkage, spec );
     115        }
     116};
     117
    135118} // namespace
    136119
    137 bool FixMain::isMain( FunctionDecl * decl ) {
    138         if ( std::string("main") != decl->name ) {
    139                 return false;
    140         }
    141         return is_main( SymTab::Mangler::mangle( decl, true, true ) );
    142 }
    143 
    144 bool FixMain::isMain( const ast::FunctionDecl * decl ) {
     120bool isMain( const ast::FunctionDecl * decl ) {
    145121        if ( std::string("main") != decl->name ) {
    146122                return false;
     
    149125}
    150126
    151 };
     127void fixMainLinkage( ast::TranslationUnit & translationUnit,
     128                bool replace_main ) {
     129        ast::Linkage::Spec const spec =
     130                ( replace_main ) ? ast::Linkage::Cforall : ast::Linkage::C;
     131        ast::Pass<FixLinkageCore>::run( translationUnit, spec );
     132}
     133
     134void fixMainInvoke( ast::TranslationUnit & translationUnit,
     135                std::ostream &os, const char * bootloader_filename ) {
     136
     137        ast::Pass<FindMainCore> main_finder;
     138        ast::accept_all( translationUnit, main_finder );
     139        if ( nullptr == main_finder.core.main_declaration ) return;
     140
     141        ast::FunctionDecl * main_declaration =
     142                ast::mutate( main_finder.core.main_declaration );
     143
     144        main_declaration->mangleName = Mangle::mangle( main_declaration );
     145
     146        os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
     147        os << main_declaration->scopedMangleName() << "(";
     148        const auto& params = main_declaration->type->params;
     149        switch ( params.size() ) {
     150                case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break;
     151                case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break;
     152                case 0: break;
     153                default : assert(false);
     154        }
     155        os << "); }\n";
     156
     157        std::ifstream bootloader( bootloader_filename, std::ios::in );
     158        assertf( bootloader.is_open(), "cannot open bootloader.c\n" );
     159        os << bootloader.rdbuf();
     160}
     161
     162} // namespace CodeGen
  • src/CodeGen/FixMain.h

    r0030b508 rfc12f05  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixMain.h --
     7// FixMain.h -- Tools to change a Cforall main into a C main.
    88//
    99// Author           : Thierry Delisle
     
    1717
    1818#include <iosfwd>
    19 #include <memory>
    20 #include <list>
    2119
    22 #include "SynTree/LinkageSpec.h"
    23 
    24 class Declaration;
    25 class FunctionDecl;
    2620namespace ast {
    2721        class FunctionDecl;
     22        class TranslationUnit;
    2823}
    2924
    3025namespace CodeGen {
    3126
    32 class FixMain {
    33 public :
    34         static inline LinkageSpec::Spec mainLinkage() {
    35                 return replace_main ? LinkageSpec::Cforall : LinkageSpec::C;
    36         }
     27/// Is this function a program main function?
     28bool isMain( const ast::FunctionDecl * decl );
    3729
    38         static inline void setReplaceMain(bool val) {
    39                 replace_main = val;
    40         }
     30/// Adjust the linkage of main functions.
     31void fixMainLinkage( ast::TranslationUnit & transUnit, bool replaceMain );
    4132
    42         static bool isMain(FunctionDecl* decl);
    43         static bool isMain(const ast::FunctionDecl * decl);
    44 
    45         static void fix( std::list< Declaration * > & decls,
    46                         std::ostream &os, const char* bootloader_filename );
    47 
    48 private:
    49         static bool replace_main;
    50 };
     33/// Add a wrapper around to run the Cforall main.
     34void fixMainInvoke( ast::TranslationUnit & transUnit,
     35                std::ostream & os, const char * bootloaderFilename );
    5136
    5237} // namespace CodeGen
  • src/CodeGen/FixNames.cc

    r0030b508 rfc12f05  
    2222#include "AST/Expr.hpp"
    2323#include "AST/Pass.hpp"
    24 #include "Common/PassVisitor.h"
    2524#include "Common/SemanticError.h"  // for SemanticError
    2625#include "FixMain.h"               // for FixMain
    2726#include "SymTab/Mangler.h"        // for Mangler
    28 #include "SynTree/LinkageSpec.h"   // for Cforall, isMangled
    29 #include "SynTree/Constant.h"      // for Constant
    30 #include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declarat...
    31 #include "SynTree/Expression.h"    // for ConstantExpr
    32 #include "SynTree/Label.h"         // for Label, noLabels
    33 #include "SynTree/Statement.h"     // for ReturnStmt, CompoundStmt
    34 #include "SynTree/Type.h"          // for Type, BasicType, Type::Qualifiers
    35 #include "SynTree/Visitor.h"       // for Visitor, acceptAll
    3627#include "CompilationState.h"
    3728
    3829namespace CodeGen {
    39         class FixNames : public WithGuards {
    40           public:
    41                 void postvisit( ObjectDecl *objectDecl );
    42                 void postvisit( FunctionDecl *functionDecl );
    4330
    44                 void previsit( CompoundStmt *compoundStmt );
    45           private:
    46                 int scopeLevel = 1;
    47 
    48                 void fixDWT( DeclarationWithType *dwt );
    49         };
    50 
    51         void fixNames( std::list< Declaration* > & translationUnit ) {
    52                 PassVisitor<FixNames> fixer;
    53                 acceptAll( translationUnit, fixer );
    54         }
    55 
    56         void FixNames::fixDWT( DeclarationWithType * dwt ) {
    57                 if ( dwt->get_name() != "" ) {
    58                         if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) {
    59                                 if (!useNewAST) {
    60                                         dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
    61                                 }
    62                                 dwt->set_scopeLevel( scopeLevel );
    63                         } // if
    64                 } // if
    65         }
    66 
    67         void FixNames::postvisit( ObjectDecl * objectDecl ) {
    68                 fixDWT( objectDecl );
    69         }
    70 
    71         void FixNames::postvisit( FunctionDecl * functionDecl ) {
    72                 fixDWT( functionDecl );
    73 
    74                 if ( FixMain::isMain( functionDecl ) ) {
    75                         int nargs = functionDecl->get_functionType()->get_parameters().size();
    76                         if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
    77                                 SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
    78                         }
    79                         functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
    80                 }
    81         }
    82 
    83         void FixNames::previsit( CompoundStmt * ) {
    84                 scopeLevel++;
    85                 GuardAction( [this](){ scopeLevel--; } );
    86         }
     31namespace {
    8732
    8833/// Does work with the main function and scopeLevels.
    89 class FixNames_new final {
     34class FixNames final {
    9035        int scopeLevel = 1;
    9136
     
    10348
    10449        const ast::FunctionDecl *postvisit( const ast::FunctionDecl *functionDecl ) {
    105                 if ( FixMain::isMain( functionDecl ) ) {
     50                if ( isMain( functionDecl ) ) {
    10651                        auto mutDecl = ast::mutate( functionDecl );
    10752
     
    13883};
    13984
     85} // namespace
     86
    14087void fixNames( ast::TranslationUnit & translationUnit ) {
    141         ast::Pass<FixNames_new>::run( translationUnit );
     88        ast::Pass<FixNames>::run( translationUnit );
    14289}
    14390
  • src/CodeGen/FixNames.h

    r0030b508 rfc12f05  
    1616#pragma once
    1717
    18 #include <list>  // for list
    19 
    20 class Declaration;
    2118namespace ast {
    2219        class TranslationUnit;
     
    2421
    2522namespace CodeGen {
    26         /// mangles object and function names
    27         void fixNames( std::list< Declaration* > & translationUnit );
     23
    2824/// Sets scope levels and fills in main's default return.
    2925void fixNames( ast::TranslationUnit & translationUnit );
     26
    3027} // namespace CodeGen
    3128
  • src/CodeGen/GenType.cc

    r0030b508 rfc12f05  
    1919#include <sstream>                // for operator<<, ostringstream, basic_os...
    2020
    21 #include "CodeGenerator.h"        // for CodeGenerator
    22 #include "SynTree/Declaration.h"  // for DeclarationWithType
    23 #include "SynTree/Expression.h"   // for Expression
    24 #include "SynTree/Type.h"         // for PointerType, Type, FunctionType
    25 #include "SynTree/Visitor.h"      // for Visitor
     21#include "AST/Print.hpp"          // for print
     22#include "AST/Vector.hpp"         // for vector
     23#include "CodeGeneratorNew.hpp"   // for CodeGenerator_new
     24#include "Common/UniqueName.h"    // for UniqueName
    2625
    2726namespace CodeGen {
    28         struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
    29                 std::string typeString;
    30                 GenType( const std::string &typeString, const Options &options );
    31 
    32                 void previsit( BaseSyntaxNode * );
    33                 void postvisit( BaseSyntaxNode * );
    34 
    35                 void postvisit( FunctionType * funcType );
    36                 void postvisit( VoidType * voidType );
    37                 void postvisit( BasicType * basicType );
    38                 void postvisit( PointerType * pointerType );
    39                 void postvisit( ArrayType * arrayType );
    40                 void postvisit( ReferenceType * refType );
    41                 void postvisit( StructInstType * structInst );
    42                 void postvisit( UnionInstType * unionInst );
    43                 void postvisit( EnumInstType * enumInst );
    44                 void postvisit( TypeInstType * typeInst );
    45                 void postvisit( TupleType  * tupleType );
    46                 void postvisit( VarArgsType * varArgsType );
    47                 void postvisit( ZeroType * zeroType );
    48                 void postvisit( OneType * oneType );
    49                 void postvisit( GlobalScopeType * globalType );
    50                 void postvisit( TraitInstType * inst );
    51                 void postvisit( TypeofType * typeof );
    52                 void postvisit( VTableType * vtable );
    53                 void postvisit( QualifiedType * qualType );
    54 
    55           private:
    56                 void handleQualifiers( Type *type );
    57                 std::string handleGeneric( ReferenceToType * refType );
    58                 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
    59 
    60                 Options options;
    61         };
    62 
    63         std::string genType( Type *type, const std::string &baseString, const Options &options ) {
    64                 PassVisitor<GenType> gt( baseString, options );
     27
     28namespace {
     29
     30#warning Remove the _new when old version is removed.
     31struct GenType_new :
     32                public ast::WithShortCircuiting,
     33                public ast::WithVisitorRef<GenType_new> {
     34        std::string result;
     35        GenType_new( const std::string &typeString, const Options &options );
     36
     37        void previsit( ast::Node const * );
     38        void postvisit( ast::Node const * );
     39
     40        void postvisit( ast::FunctionType const * type );
     41        void postvisit( ast::VoidType const * type );
     42        void postvisit( ast::BasicType const * type );
     43        void postvisit( ast::PointerType const * type );
     44        void postvisit( ast::ArrayType const * type );
     45        void postvisit( ast::ReferenceType const * type );
     46        void postvisit( ast::StructInstType const * type );
     47        void postvisit( ast::UnionInstType const * type );
     48        void postvisit( ast::EnumInstType const * type );
     49        void postvisit( ast::TypeInstType const * type );
     50        void postvisit( ast::TupleType const * type );
     51        void postvisit( ast::VarArgsType const * type );
     52        void postvisit( ast::ZeroType const * type );
     53        void postvisit( ast::OneType const * type );
     54        void postvisit( ast::GlobalScopeType const * type );
     55        void postvisit( ast::TraitInstType const * type );
     56        void postvisit( ast::TypeofType const * type );
     57        void postvisit( ast::VTableType const * type );
     58        void postvisit( ast::QualifiedType const * type );
     59
     60private:
     61        void handleQualifiers( ast::Type const *type );
     62        std::string handleGeneric( ast::BaseInstType const * type );
     63        void genArray( const ast::CV::Qualifiers &qualifiers, ast::Type const *base, ast::Expr const *dimension, bool isVarLen, bool isStatic );
     64        std::string genParamList( const ast::vector<ast::Type> & );
     65
     66        Options options;
     67};
     68
     69GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
     70
     71void GenType_new::previsit( ast::Node const * ) {
     72        // Turn off automatic recursion for all nodes, to allow each visitor to
     73        // precisely control the order in which its children are visited.
     74        visit_children = false;
     75}
     76
     77void GenType_new::postvisit( ast::Node const * node ) {
     78        std::stringstream ss;
     79        ast::print( ss, node );
     80        assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
     81}
     82
     83void GenType_new::postvisit( ast::VoidType const * type ) {
     84        result = "void " + result;
     85        handleQualifiers( type );
     86}
     87
     88void GenType_new::postvisit( ast::BasicType const * type ) {
     89        ast::BasicType::Kind kind = type->kind;
     90        assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES );
     91        result = std::string( ast::BasicType::typeNames[kind] ) + " " + result;
     92        handleQualifiers( type );
     93}
     94
     95void GenType_new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {
     96        std::ostringstream os;
     97        if ( result != "" ) {
     98                if ( result[ 0 ] == '*' ) {
     99                        os << "(" << result << ")";
     100                } else {
     101                        os << result;
     102                }
     103        }
     104        os << "[";
     105        if ( isStatic ) {
     106                os << "static ";
     107        }
     108        if ( qualifiers.is_const ) {
     109                os << "const ";
     110        }
     111        if ( qualifiers.is_volatile ) {
     112                os << "volatile ";
     113        }
     114        if ( qualifiers.is_restrict ) {
     115                os << "__restrict ";
     116        }
     117        if ( qualifiers.is_atomic ) {
     118                os << "_Atomic ";
     119        }
     120        if ( dimension != 0 ) {
     121                ast::Pass<CodeGenerator_new>::read( dimension, os, options );
     122        } else if ( isVarLen ) {
     123                // no dimension expression on a VLA means it came in with the * token
     124                os << "*";
     125        }
     126        os << "]";
     127
     128        result = os.str();
     129
     130        base->accept( *visitor );
     131}
     132
     133void GenType_new::postvisit( ast::PointerType const * type ) {
     134        if ( type->isStatic || type->isVarLen || type->dimension ) {
     135                genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
     136        } else {
     137                handleQualifiers( type );
     138                if ( result[ 0 ] == '?' ) {
     139                        result = "* " + result;
     140                } else {
     141                        result = "*" + result;
     142                }
     143                type->base->accept( *visitor );
     144        }
     145}
     146
     147void GenType_new::postvisit( ast::ArrayType const * type ) {
     148        genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
     149}
     150
     151void GenType_new::postvisit( ast::ReferenceType const * type ) {
     152        assertf( !options.genC, "Reference types should not reach code generation." );
     153        handleQualifiers( type );
     154        result = "&" + result;
     155        type->base->accept( *visitor );
     156}
     157
     158void GenType_new::postvisit( ast::FunctionType const * type ) {
     159        std::ostringstream os;
     160
     161        if ( result != "" ) {
     162                if ( result[ 0 ] == '*' ) {
     163                        os << "(" << result << ")";
     164                } else {
     165                        os << result;
     166                }
     167        }
     168
     169        if ( type->params.empty() ) {
     170                if ( type->isVarArgs ) {
     171                        os << "()";
     172                } else {
     173                        os << "(void)";
     174                }
     175        } else {
     176                os << "(" ;
     177
     178                os << genParamList( type->params );
     179
     180                if ( type->isVarArgs ) {
     181                        os << ", ...";
     182                }
     183                os << ")";
     184        }
     185
     186        result = os.str();
     187
     188        if ( type->returns.size() == 0 ) {
     189                result = "void " + result;
     190        } else {
     191                type->returns.front()->accept( *visitor );
     192        }
     193
     194        // Add forall clause.
     195        if( !type->forall.empty() && !options.genC ) {
     196                //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." );
    65197                std::ostringstream os;
    66 
    67                 if ( ! type->get_attributes().empty() ) {
    68                         PassVisitor<CodeGenerator> cg( os, options );
    69                         cg.pass.genAttributes( type->get_attributes() );
    70                 } // if
    71 
    72                 type->accept( gt );
    73                 return os.str() + gt.pass.typeString;
    74         }
    75 
    76         std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
    77                 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );
    78         }
    79 
    80         std::string genPrettyType( Type * type, const std::string & baseString ) {
    81                 return genType( type, baseString, true, false );
    82         }
    83 
    84         GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}
    85 
    86         // *** BaseSyntaxNode
    87         void GenType::previsit( BaseSyntaxNode * ) {
    88                 // turn off automatic recursion for all nodes, to allow each visitor to
    89                 // precisely control the order in which its children are visited.
    90                 visit_children = false;
    91         }
    92 
    93         void GenType::postvisit( BaseSyntaxNode * node ) {
    94                 std::stringstream ss;
    95                 node->print( ss );
    96                 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
    97         }
    98 
    99         void GenType::postvisit( VoidType * voidType ) {
    100                 typeString = "void " + typeString;
    101                 handleQualifiers( voidType );
    102         }
    103 
    104         void GenType::postvisit( BasicType * basicType ) {
    105                 BasicType::Kind kind = basicType->kind;
    106                 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
    107                 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
    108                 handleQualifiers( basicType );
    109         }
    110 
    111         void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) {
     198                ast::Pass<CodeGenerator_new> cg( os, options );
     199                os << "forall(";
     200                cg.core.genCommaList( type->forall );
     201                os << ")" << std::endl;
     202                result = os.str() + result;
     203        }
     204}
     205
     206std::string GenType_new::handleGeneric( ast::BaseInstType const * type ) {
     207        if ( !type->params.empty() ) {
    112208                std::ostringstream os;
    113                 if ( typeString != "" ) {
    114                         if ( typeString[ 0 ] == '*' ) {
    115                                 os << "(" << typeString << ")";
    116                         } else {
    117                                 os << typeString;
    118                         } // if
    119                 } // if
    120                 os << "[";
    121 
    122                 if ( isStatic ) {
    123                         os << "static ";
    124                 } // if
    125                 if ( qualifiers.is_const ) {
    126                         os << "const ";
    127                 } // if
    128                 if ( qualifiers.is_volatile ) {
    129                         os << "volatile ";
    130                 } // if
    131                 if ( qualifiers.is_restrict ) {
    132                         os << "__restrict ";
    133                 } // if
    134                 if ( qualifiers.is_atomic ) {
    135                         os << "_Atomic ";
    136                 } // if
    137                 if ( dimension != 0 ) {
    138                         PassVisitor<CodeGenerator> cg( os, options );
    139                         dimension->accept( cg );
    140                 } else if ( isVarLen ) {
    141                         // no dimension expression on a VLA means it came in with the * token
    142                         os << "*";
    143                 } // if
    144                 os << "]";
    145 
    146                 typeString = os.str();
    147 
    148                 base->accept( *visitor );
    149         }
    150 
    151         void GenType::postvisit( PointerType * pointerType ) {
    152                 assert( pointerType->base != 0);
    153                 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
    154                         genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
    155                 } else {
    156                         handleQualifiers( pointerType );
    157                         if ( typeString[ 0 ] == '?' ) {
    158                                 typeString = "* " + typeString;
    159                         } else {
    160                                 typeString = "*" + typeString;
    161                         } // if
    162                         pointerType->base->accept( *visitor );
    163                 } // if
    164         }
    165 
    166         void GenType::postvisit( ArrayType * arrayType ) {
    167                 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
    168         }
    169 
    170         void GenType::postvisit( ReferenceType * refType ) {
    171                 assert( 0 != refType->base );
    172                 assertf( ! options.genC, "Reference types should not reach code generation." );
    173                 handleQualifiers( refType );
    174                 typeString = "&" + typeString;
    175                 refType->base->accept( *visitor );
    176         }
    177 
    178         void GenType::postvisit( FunctionType * funcType ) {
    179                 std::ostringstream os;
    180 
    181                 if ( typeString != "" ) {
    182                         if ( typeString[ 0 ] == '*' ) {
    183                                 os << "(" << typeString << ")";
    184                         } else {
    185                                 os << typeString;
    186                         } // if
    187                 } // if
    188 
    189                 /************* parameters ***************/
    190 
    191                 const std::list<DeclarationWithType *> &pars = funcType->parameters;
    192 
    193                 if ( pars.empty() ) {
    194                         if ( funcType->get_isVarArgs() ) {
    195                                 os << "()";
    196                         } else {
    197                                 os << "(void)";
    198                         } // if
    199                 } else {
    200                         PassVisitor<CodeGenerator> cg( os, options );
    201                         os << "(" ;
    202 
    203                         cg.pass.genCommaList( pars.begin(), pars.end() );
    204 
    205                         if ( funcType->get_isVarArgs() ) {
    206                                 os << ", ...";
    207                         } // if
    208                         os << ")";
    209                 } // if
    210 
    211                 typeString = os.str();
    212 
    213                 if ( funcType->returnVals.size() == 0 ) {
    214                         typeString = "void " + typeString;
    215                 } else {
    216                         funcType->returnVals.front()->get_type()->accept( *visitor );
    217                 } // if
    218 
    219                 // add forall
    220                 if( ! funcType->forall.empty() && ! options.genC ) {
    221                         // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    222                         std::ostringstream os;
    223                         PassVisitor<CodeGenerator> cg( os, options );
    224                         os << "forall(";
    225                         cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );
    226                         os << ")" << std::endl;
    227                         typeString = os.str() + typeString;
    228                 }
    229         }
    230 
    231         std::string GenType::handleGeneric( ReferenceToType * refType ) {
    232                 if ( ! refType->parameters.empty() ) {
    233                         std::ostringstream os;
    234                         PassVisitor<CodeGenerator> cg( os, options );
    235                         os << "(";
    236                         cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
    237                         os << ") ";
    238                         return os.str();
    239                 }
    240                 return "";
    241         }
    242 
    243         void GenType::postvisit( StructInstType * structInst )  {
    244                 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;
    245                 if ( options.genC ) typeString = "struct " + typeString;
    246                 handleQualifiers( structInst );
    247         }
    248 
    249         void GenType::postvisit( UnionInstType * unionInst ) {
    250                 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;
    251                 if ( options.genC ) typeString = "union " + typeString;
    252                 handleQualifiers( unionInst );
    253         }
    254 
    255         void GenType::postvisit( EnumInstType * enumInst ) {
    256                 if ( enumInst->baseEnum && enumInst->baseEnum->base ) {
    257                         typeString = genType(enumInst->baseEnum->base, typeString, options);
    258                 } else {
    259                         typeString = enumInst->name + " " + typeString;
    260                         if ( options.genC ) {
    261                                 typeString = "enum " + typeString;
    262                         }
    263                 }
    264                 handleQualifiers( enumInst );
    265         }
    266 
    267         void GenType::postvisit( TypeInstType * typeInst ) {
    268                 assertf( ! options.genC, "Type instance types should not reach code generation." );
    269                 typeString = typeInst->name + " " + typeString;
    270                 handleQualifiers( typeInst );
    271         }
    272 
    273         void GenType::postvisit( TupleType * tupleType ) {
    274                 assertf( ! options.genC, "Tuple types should not reach code generation." );
    275                 unsigned int i = 0;
    276                 std::ostringstream os;
    277                 os << "[";
    278                 for ( Type * t : *tupleType ) {
    279                         i++;
    280                         os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");
    281                 }
    282                 os << "] ";
    283                 typeString = os.str() + typeString;
    284         }
    285 
    286         void GenType::postvisit( VarArgsType * varArgsType ) {
    287                 typeString = "__builtin_va_list " + typeString;
    288                 handleQualifiers( varArgsType );
    289         }
    290 
    291         void GenType::postvisit( ZeroType * zeroType ) {
    292                 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    293                 typeString = (options.pretty ? "zero_t " : "long int ") + typeString;
    294                 handleQualifiers( zeroType );
    295         }
    296 
    297         void GenType::postvisit( OneType * oneType ) {
    298                 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    299                 typeString = (options.pretty ? "one_t " : "long int ") + typeString;
    300                 handleQualifiers( oneType );
    301         }
    302 
    303         void GenType::postvisit( GlobalScopeType * globalType ) {
    304                 assertf( ! options.genC, "Global scope type should not reach code generation." );
    305                 handleQualifiers( globalType );
    306         }
    307 
    308         void GenType::postvisit( TraitInstType * inst ) {
    309                 assertf( ! options.genC, "Trait types should not reach code generation." );
    310                 typeString = inst->name + " " + typeString;
    311                 handleQualifiers( inst );
    312         }
    313 
    314         void GenType::postvisit( TypeofType * typeof ) {
    315                 std::ostringstream os;
    316                 PassVisitor<CodeGenerator> cg( os, options );
    317                 os << "typeof(";
    318                 typeof->expr->accept( cg );
    319                 os << ") " << typeString;
    320                 typeString = os.str();
    321                 handleQualifiers( typeof );
    322         }
    323 
    324         void GenType::postvisit( VTableType * vtable ) {
    325                 assertf( ! options.genC, "Virtual table types should not reach code generation." );
    326                 std::ostringstream os;
    327                 os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString;
    328                 typeString = os.str();
    329                 handleQualifiers( vtable );
    330         }
    331 
    332         void GenType::postvisit( QualifiedType * qualType ) {
    333                 assertf( ! options.genC, "Qualified types should not reach code generation." );
    334                 std::ostringstream os;
    335                 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString;
    336                 typeString = os.str();
    337                 handleQualifiers( qualType );
    338         }
    339 
    340         void GenType::handleQualifiers( Type * type ) {
    341                 if ( type->get_const() ) {
    342                         typeString = "const " + typeString;
    343                 } // if
    344                 if ( type->get_volatile() ) {
    345                         typeString = "volatile " + typeString;
    346                 } // if
    347                 if ( type->get_restrict() ) {
    348                         typeString = "__restrict " + typeString;
    349                 } // if
    350                 if ( type->get_atomic() ) {
    351                         typeString = "_Atomic " + typeString;
    352                 } // if
    353         }
     209                ast::Pass<CodeGenerator_new> cg( os, options );
     210                os << "(";
     211                cg.core.genCommaList( type->params );
     212                os << ") ";
     213                return os.str();
     214        }
     215        return "";
     216}
     217
     218void GenType_new::postvisit( ast::StructInstType const * type )  {
     219        result = type->name + handleGeneric( type ) + " " + result;
     220        if ( options.genC ) result = "struct " + result;
     221        handleQualifiers( type );
     222}
     223
     224void GenType_new::postvisit( ast::UnionInstType const * type ) {
     225        result = type->name + handleGeneric( type ) + " " + result;
     226        if ( options.genC ) result = "union " + result;
     227        handleQualifiers( type );
     228}
     229
     230void GenType_new::postvisit( ast::EnumInstType const * type ) {
     231        if ( type->base && type->base->base ) {
     232                result = genType( type->base->base, result, options );
     233        } else {
     234                result = type->name + " " + result;
     235                if ( options.genC ) {
     236                        result = "enum " + result;
     237                }
     238        }
     239        handleQualifiers( type );
     240}
     241
     242void GenType_new::postvisit( ast::TypeInstType const * type ) {
     243        assertf( !options.genC, "TypeInstType should not reach code generation." );
     244        result = type->name + " " + result;
     245        handleQualifiers( type );
     246}
     247
     248void GenType_new::postvisit( ast::TupleType const * type ) {
     249        assertf( !options.genC, "TupleType should not reach code generation." );
     250        unsigned int i = 0;
     251        std::ostringstream os;
     252        os << "[";
     253        for ( ast::ptr<ast::Type> const & t : type->types ) {
     254                i++;
     255                os << genType( t, "", options ) << (i == type->size() ? "" : ", ");
     256        }
     257        os << "] ";
     258        result = os.str() + result;
     259}
     260
     261void GenType_new::postvisit( ast::VarArgsType const * type ) {
     262        result = "__builtin_va_list " + result;
     263        handleQualifiers( type );
     264}
     265
     266void GenType_new::postvisit( ast::ZeroType const * type ) {
     267        // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
     268        result = (options.pretty ? "zero_t " : "long int ") + result;
     269        handleQualifiers( type );
     270}
     271
     272void GenType_new::postvisit( ast::OneType const * type ) {
     273        // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
     274        result = (options.pretty ? "one_t " : "long int ") + result;
     275        handleQualifiers( type );
     276}
     277
     278void GenType_new::postvisit( ast::GlobalScopeType const * type ) {
     279        assertf( !options.genC, "GlobalScopeType should not reach code generation." );
     280        handleQualifiers( type );
     281}
     282
     283void GenType_new::postvisit( ast::TraitInstType const * type ) {
     284        assertf( !options.genC, "TraitInstType should not reach code generation." );
     285        result = type->name + " " + result;
     286        handleQualifiers( type );
     287}
     288
     289void GenType_new::postvisit( ast::TypeofType const * type ) {
     290        std::ostringstream os;
     291        os << "typeof(";
     292        ast::Pass<CodeGenerator_new>::read( type, os, options );
     293        os << ") " << result;
     294        result = os.str();
     295        handleQualifiers( type );
     296}
     297
     298void GenType_new::postvisit( ast::VTableType const * type ) {
     299        assertf( !options.genC, "Virtual table types should not reach code generation." );
     300        std::ostringstream os;
     301        os << "vtable(" << genType( type->base, "", options ) << ") " << result;
     302        result = os.str();
     303        handleQualifiers( type );
     304}
     305
     306void GenType_new::postvisit( ast::QualifiedType const * type ) {
     307        assertf( !options.genC, "QualifiedType should not reach code generation." );
     308        std::ostringstream os;
     309        os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result;
     310        result = os.str();
     311        handleQualifiers( type );
     312}
     313
     314void GenType_new::handleQualifiers( ast::Type const * type ) {
     315        if ( type->is_const() ) {
     316                result = "const " + result;
     317        }
     318        if ( type->is_volatile() ) {
     319                result = "volatile " + result;
     320        }
     321        if ( type->is_restrict() ) {
     322                result = "__restrict " + result;
     323        }
     324        if ( type->is_atomic() ) {
     325                result = "_Atomic " + result;
     326        }
     327}
     328
     329std::string GenType_new::genParamList( const ast::vector<ast::Type> & range ) {
     330        auto cur = range.begin();
     331        auto end = range.end();
     332        if ( cur == end ) return "";
     333        std::ostringstream oss;
     334        UniqueName param( "__param_" );
     335        while ( true ) {
     336                oss << genType( *cur++, options.genC ? param.newName() : "", options );
     337                if ( cur == end ) break;
     338                oss << ", ";
     339        }
     340        return oss.str();
     341}
     342
     343} // namespace
     344
     345std::string genType( ast::Type const * type, const std::string & base, const Options & options ) {
     346        std::ostringstream os;
     347        if ( !type->attributes.empty() ) {
     348                ast::Pass<CodeGenerator_new> cg( os, options );
     349                cg.core.genAttributes( type->attributes );
     350        }
     351
     352        return os.str() + ast::Pass<GenType_new>::read( type, base, options );
     353}
     354
     355std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) {
     356        return ast::Pass<GenType_new>::read( type, base, options );
     357}
     358
    354359} // namespace CodeGen
    355360
  • src/CodeGen/GenType.h

    r0030b508 rfc12f05  
    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

    r0030b508 rfc12f05  
    1919#include <string>                    // for operator<<
    2020
    21 #include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
     21#include "CodeGeneratorNew.hpp"      // for CodeGenerator_new, doSemicolon, ...
    2222#include "GenType.h"                 // for genPrettyType
    23 #include "Common/PassVisitor.h"      // for PassVisitor
    24 #include "SynTree/LinkageSpec.h"     // for isBuiltin, isGeneratable
    25 #include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
    26 #include "SynTree/Declaration.h"     // for Declaration
    27 #include "SynTree/Type.h"            // for Type
    2823
    2924using namespace std;
    3025
    3126namespace CodeGen {
    32         namespace {
    33                 /// Removes misc. nodes that should not exist in CodeGen
    34                 struct TreeCleaner {
    35                         void premutate( CompoundStmt * stmt );
    36                         Statement * postmutate( ImplicitCtorDtorStmt * stmt );
    3727
    38                         static bool shouldClean( Declaration * );
    39                 };
    40 
    41                 void cleanTree( std::list< Declaration * > & translationUnit ) {
    42                         PassVisitor<TreeCleaner> cleaner;
    43                         filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
    44                         mutateAll( translationUnit, cleaner );
    45                 } // cleanTree
    46         } // namespace
    47 
    48         void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) {
    49                 cleanTree( translationUnit );
    50 
    51                 PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks, printExprTypes );
    52                 for ( auto & dcl : translationUnit ) {
    53                         if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) {
    54                                 cgv.pass.updateLocation( dcl );
    55                                 dcl->accept(cgv);
    56                                 if ( doSemicolon( dcl ) ) {
    57                                         os << ";";
    58                                 } // if
    59                                 os << cgv.pass.endl;
    60                         } // if
    61                 } // for
     28namespace {
     29        bool shouldClean( ast::Decl const * decl ) {
     30                return dynamic_cast<ast::TraitDecl const *>( decl );
    6231        }
    6332
    64         void generate( BaseSyntaxNode * node, std::ostream & os ) {
    65                 if ( Type * type = dynamic_cast< Type * >( node ) ) {
    66                         os << genPrettyType( type, "" );
    67                 } else {
    68                         PassVisitor<CodeGenerator> cgv( os, true, false, false, false );
    69                         node->accept( cgv );
    70                 }
    71                 os << std::endl;
    72         }
    73 
    74         namespace {
    75                 void TreeCleaner::premutate( CompoundStmt * cstmt ) {
    76                         filter( cstmt->kids, [](Statement * stmt) {
    77                                 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
    78                                         return shouldClean( declStmt->decl );
    79                                 }
    80                                 return false;
    81                         }, false );
     33        /// Removes various nodes that should not exist in CodeGen.
     34        struct TreeCleaner_new {
     35                ast::CompoundStmt const * previsit( ast::CompoundStmt const * stmt ) {
     36                        auto mutStmt = ast::mutate( stmt );
     37                        erase_if( mutStmt->kids, []( ast::Stmt const * stmt ){
     38                                auto declStmt = dynamic_cast<ast::DeclStmt const *>( stmt );
     39                                return ( declStmt ) ? shouldClean( declStmt->decl ) : false;
     40                        } );
     41                        return mutStmt;
    8242                }
    8343
    84                 Statement * TreeCleaner::postmutate( ImplicitCtorDtorStmt * stmt ) {
    85                         Statement * callStmt = nullptr;
    86                         std::swap( stmt->callStmt, callStmt );
    87                         delete stmt;
    88                         return callStmt;
     44                ast::Stmt const * postvisit( ast::ImplicitCtorDtorStmt const * stmt ) {
     45                        return stmt->callStmt;
    8946                }
     47        };
     48} // namespace
    9049
    91                 bool TreeCleaner::shouldClean( Declaration * decl ) {
    92                         return dynamic_cast< TraitDecl * >( decl );
     50void generate( ast::TranslationUnit & translationUnit, std::ostream & os, bool doIntrinsics,
     51                bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) {
     52        erase_if( translationUnit.decls, shouldClean );
     53        ast::Pass<TreeCleaner_new>::run( translationUnit );
     54
     55        ast::Pass<CodeGenerator_new> cgv( os,
     56                        Options( pretty, generateC, lineMarks, printExprTypes ) );
     57        for ( auto & decl : translationUnit.decls ) {
     58                if ( decl->linkage.is_generatable && (doIntrinsics || !decl->linkage.is_builtin ) ) {
     59                        cgv.core.updateLocation( decl );
     60                        decl->accept( cgv );
     61                        if ( doSemicolon( decl ) ) {
     62                                os << ";";
     63                        }
     64                        os << cgv.core.endl;
    9365                }
    94         } // namespace
     66        }
     67}
     68
    9569} // namespace CodeGen
    9670
  • src/CodeGen/Generate.h

    r0030b508 rfc12f05  
    2222class Declaration;
    2323
     24namespace ast {
     25        class TranslationUnit;
     26}
     27
    2428namespace CodeGen {
    25         /// 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.)
    26         void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC = false , bool lineMarks = false, bool printTypeExpr = false );
    2729
    28         /// Generate code for a single node -- helpful for debugging in gdb
    29         void generate( BaseSyntaxNode * node, std::ostream & os );
     30/// Generates all code in transUnit and writing it to the os.
     31/// doIntrinsics: Should intrinsic functions be printed?
     32/// pretty: Format output nicely (e.g., uses unmangled names, etc.).
     33/// generateC: Make sure the output only consists of C code (allows some assertions, etc.)
     34/// lineMarks: Output line marks (processed line directives) in the output.
     35/// printExprTypes: Print the types of expressions in comments.
     36void generate( ast::TranslationUnit & transUnit, std::ostream &os, bool doIntrinsics,
     37                bool pretty, bool generateC, bool lineMarks, bool printExprTypes );
     38
    3039} // namespace CodeGen
    3140
  • src/CodeGen/LinkOnce.cc

    r0030b508 rfc12f05  
    2222#include "AST/Expr.hpp"
    2323#include "AST/Pass.hpp"
    24 #include "Common/PassVisitor.h"       // for PassVisitor, WithShortCircuiting
    2524
    2625namespace CodeGen {
    2726
    2827namespace {
    29 
    30 bool is_cfa_linkonce_old( Attribute const * attr ) {
    31         return std::string("cfa_linkonce") == attr->name;
    32 }
    33 
    34 bool is_section_attribute_old( Attribute const * attr ) {
    35         return std::string("section") == attr->name;
    36 }
    37 
    38 class LinkOnceVisitorCore : public WithShortCircuiting {
    39 public:
    40         void previsit( Declaration * ) {
    41                 visit_children = false;
    42         }
    43 
    44         void previsit( DeclarationWithType * decl ) {
    45                 std::list< Attribute * > & attributes = decl->attributes;
    46                 // See if we can find the element:
    47                 auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );
    48                 if ( attributes.end() != found ) {
    49                         // Remove any other sections:
    50                         attributes.remove_if( is_section_attribute_old );
    51                         // Iterator to the cfa_linkonce attribute should still be valid.
    52                         Attribute * attribute = *found;
    53                         assert( attribute->parameters.empty() );
    54                         assert( !decl->mangleName.empty() );
    55                         // Overwrite the attribute in place.
    56                         const std::string section_name = ".gnu.linkonce." + decl->mangleName;
    57                         attribute->name = "section";
    58                         attribute->parameters.push_back(
    59                                 new ConstantExpr( Constant::from_string( section_name ) )
    60                         );
    61 
    62                         // Unconditionnaly add "visibility(default)" to anything with gnu.linkonce
    63                         // visibility is a mess otherwise
    64                         attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));
    65 
    66                 }
    67                 visit_children = false;
    68         }
    69 };
    7028
    7129bool is_cfa_linkonce( ast::Attribute const * attr ) {
     
    12280} // namespace
    12381
    124 void translateLinkOnce( std::list< Declaration *> & translationUnit ) {
    125         PassVisitor<LinkOnceVisitorCore> translator;
    126         acceptAll( translationUnit, translator );
    127 }
    128 
    12982void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
    13083        ast::Pass<LinkOnceCore>::run( translationUnit );
  • src/CodeGen/LinkOnce.h

    r0030b508 rfc12f05  
    2020// for now its almost the only attribute we handle.
    2121
    22 #include <list>  // for list
    2322
    24 class Declaration;
    2523namespace ast {
    2624        class TranslationUnit;
     
    2927namespace CodeGen {
    3028
    31 void translateLinkOnce( std::list< Declaration *> & translationUnit );
    3229void translateLinkOnce( ast::TranslationUnit & translationUnit );
    3330/* Convert the cfa_linkonce attribute on top level declaration into
  • src/CodeGen/OperatorTable.cc

    r0030b508 rfc12f05  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb 18 15:55:01 2020
    13 // Update Count     : 55
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov  3 16:00:00 2023
     13// Update Count     : 56
    1414//
    1515
    16 #include <algorithm>  // for any_of
    17 #include <map>        // for map, _Rb_tree_const_iterator, map<>::const_iterator
    18 #include <utility>    // for pair
    19 using namespace std;
     16#include "OperatorTable.h"
    2017
    21 #include "OperatorTable.h"
    22 #include "Common/utility.h"
     18#include <cassert>         // for assert
     19#include <unordered_map>   // for unordered_map
    2320
    2421namespace CodeGen {
    25         const OperatorInfo CodeGen::tableValues[] = {
    26                 // inputName symbol   outputName                     friendlyName                  type
    27                 {       "?[?]",   "",     "_operator_index",             "Index",                      OT_INDEX          },
    28                 {       "?{}",    "=",    "_constructor",                "Constructor",                OT_CTOR           },
    29                 {       "^?{}",   "",     "_destructor",                 "Destructor",                 OT_DTOR           },
    30                 {       "?()",    "",     "_operator_call",              "Call Operator",              OT_CALL           },
    31                 {       "?++",    "++",   "_operator_postincr",          "Postfix Increment",          OT_POSTFIXASSIGN  },
    32                 {       "?--",    "--",   "_operator_postdecr",          "Postfix Decrement",          OT_POSTFIXASSIGN  },
    33                 {       "*?",     "*",    "_operator_deref",             "Dereference",                OT_PREFIX         },
    34                 {       "+?",     "+",    "_operator_unaryplus",         "Plus",                       OT_PREFIX         },
    35                 {       "-?",     "-",    "_operator_unaryminus",        "Minus",                      OT_PREFIX         },
    36                 {       "~?",     "~",    "_operator_bitnot",            "Bitwise Not",                OT_PREFIX         },
    37                 {       "!?",     "!",    "_operator_lognot",            "Logical Not",                OT_PREFIX         },
    38                 {       "++?",    "++",   "_operator_preincr",           "Prefix Increment",           OT_PREFIXASSIGN   },
    39                 {       "--?",    "--",   "_operator_predecr",           "Prefix Decrement",           OT_PREFIXASSIGN   },
    40                 {       "?\\?",   "\\",   "_operator_exponential",       "Exponentiation",             OT_INFIX          },
    41                 {       "?*?",    "*",    "_operator_multiply",          "Multiplication",             OT_INFIX          },
    42                 {       "?/?",    "/",    "_operator_divide",            "Division",                   OT_INFIX          },
    43                 {       "?%?",    "%",    "_operator_modulus",           "Modulo",                     OT_INFIX          },
    44                 {       "?+?",    "+",    "_operator_add",               "Addition",                   OT_INFIX          },
    45                 {       "?-?",    "-",    "_operator_subtract",          "Substraction",               OT_INFIX          },
    46                 {       "?<<?",   "<<",   "_operator_shiftleft",         "Shift Left",                 OT_INFIX          },
    47                 {       "?>>?",   ">>",   "_operator_shiftright",        "Shift Right",                OT_INFIX          },
    48                 {       "?<?",    "<",    "_operator_less",              "Less-than",                  OT_INFIX          },
    49                 {       "?>?",    ">",    "_operator_greater",           "Greater-than",               OT_INFIX          },
    50                 {       "?<=?",   "<=",   "_operator_lessequal",         "Less-than-or-Equal",         OT_INFIX          },
    51                 {       "?>=?",   ">=",   "_operator_greaterequal",      "Greater-than-or-Equal",      OT_INFIX          },
    52                 {       "?==?",   "==",   "_operator_equal",             "Equality",                   OT_INFIX          },
    53                 {       "?!=?",   "!=",   "_operator_notequal",          "Not-Equal",                  OT_INFIX          },
    54                 {       "?&?",    "&",    "_operator_bitand",            "Bitwise And",                OT_INFIX          },
    55                 {       "?^?",    "^",    "_operator_bitxor",            "Bitwise Xor",                OT_INFIX          },
    56                 {       "?|?",    "|",    "_operator_bitor",             "Bitwise Or",                 OT_INFIX          },
    57                 {       "?=?",    "=",    "_operator_assign",            "Assignment",                 OT_INFIXASSIGN    },
    58                 {       "?\\=?",  "\\=",  "_operator_expassign",         "Exponentiation Assignment",  OT_INFIXASSIGN    },
    59                 {       "?*=?",   "*=",   "_operator_multassign",        "Multiplication Assignment",  OT_INFIXASSIGN    },
    60                 {       "?/=?",   "/=",   "_operator_divassign",         "Division Assignment",        OT_INFIXASSIGN    },
    61                 {       "?%=?",   "%=",   "_operator_modassign",         "Modulo Assignment",          OT_INFIXASSIGN    },
    62                 {       "?+=?",   "+=",   "_operator_addassign",         "Addition Assignment",        OT_INFIXASSIGN    },
    63                 {       "?-=?",   "-=",   "_operator_subassign",         "Substrction Assignment",     OT_INFIXASSIGN    },
    64                 {       "?<<=?",  "<<=",  "_operator_shiftleftassign",   "Shift Left Assignment",      OT_INFIXASSIGN    },
    65                 {       "?>>=?",  ">>=",  "_operator_shiftrightassign",  "Shift Right Assignment",     OT_INFIXASSIGN    },
    66                 {       "?&=?",   "&=",   "_operator_bitandassign",      "Bitwise And Assignment",     OT_INFIXASSIGN    },
    67                 {       "?^=?",   "^=",   "_operator_bitxorassign",      "Bitwise Xor Assignment",     OT_INFIXASSIGN    },
    68                 {       "?|=?",   "|=",   "_operator_bitorassign",       "Bitwise Or Assignment",      OT_INFIXASSIGN    },
    69         }; // tableValues
    7022
    71         std::map< std::string, OperatorInfo > CodeGen::table;
     23static const OperatorInfo tableValues[] = {
     24        //  inputName symbol  outputName                     friendlyName                  type
     25        {       "?[?]",   "",     "_operator_index",             "Index",                      OT_INDEX          },
     26        {       "?{}",    "=",    "_constructor",                "Constructor",                OT_CTOR           },
     27        {       "^?{}",   "",     "_destructor",                 "Destructor",                 OT_DTOR           },
     28        {       "?()",    "",     "_operator_call",              "Call Operator",              OT_CALL           },
     29        {       "?++",    "++",   "_operator_postincr",          "Postfix Increment",          OT_POSTFIXASSIGN  },
     30        {       "?--",    "--",   "_operator_postdecr",          "Postfix Decrement",          OT_POSTFIXASSIGN  },
     31        {       "*?",     "*",    "_operator_deref",             "Dereference",                OT_PREFIX         },
     32        {       "+?",     "+",    "_operator_unaryplus",         "Plus",                       OT_PREFIX         },
     33        {       "-?",     "-",    "_operator_unaryminus",        "Minus",                      OT_PREFIX         },
     34        {       "~?",     "~",    "_operator_bitnot",            "Bitwise Not",                OT_PREFIX         },
     35        {       "!?",     "!",    "_operator_lognot",            "Logical Not",                OT_PREFIX         },
     36        {       "++?",    "++",   "_operator_preincr",           "Prefix Increment",           OT_PREFIXASSIGN   },
     37        {       "--?",    "--",   "_operator_predecr",           "Prefix Decrement",           OT_PREFIXASSIGN   },
     38        {       "?\\?",   "\\",   "_operator_exponential",       "Exponentiation",             OT_INFIX          },
     39        {       "?*?",    "*",    "_operator_multiply",          "Multiplication",             OT_INFIX          },
     40        {       "?/?",    "/",    "_operator_divide",            "Division",                   OT_INFIX          },
     41        {       "?%?",    "%",    "_operator_modulus",           "Modulo",                     OT_INFIX          },
     42        {       "?+?",    "+",    "_operator_add",               "Addition",                   OT_INFIX          },
     43        {       "?-?",    "-",    "_operator_subtract",          "Substraction",               OT_INFIX          },
     44        {       "?<<?",   "<<",   "_operator_shiftleft",         "Shift Left",                 OT_INFIX          },
     45        {       "?>>?",   ">>",   "_operator_shiftright",        "Shift Right",                OT_INFIX          },
     46        {       "?<?",    "<",    "_operator_less",              "Less-than",                  OT_INFIX          },
     47        {       "?>?",    ">",    "_operator_greater",           "Greater-than",               OT_INFIX          },
     48        {       "?<=?",   "<=",   "_operator_lessequal",         "Less-than-or-Equal",         OT_INFIX          },
     49        {       "?>=?",   ">=",   "_operator_greaterequal",      "Greater-than-or-Equal",      OT_INFIX          },
     50        {       "?==?",   "==",   "_operator_equal",             "Equality",                   OT_INFIX          },
     51        {       "?!=?",   "!=",   "_operator_notequal",          "Not-Equal",                  OT_INFIX          },
     52        {       "?&?",    "&",    "_operator_bitand",            "Bitwise And",                OT_INFIX          },
     53        {       "?^?",    "^",    "_operator_bitxor",            "Bitwise Xor",                OT_INFIX          },
     54        {       "?|?",    "|",    "_operator_bitor",             "Bitwise Or",                 OT_INFIX          },
     55        {       "?=?",    "=",    "_operator_assign",            "Assignment",                 OT_INFIXASSIGN    },
     56        {       "?\\=?",  "\\=",  "_operator_expassign",         "Exponentiation Assignment",  OT_INFIXASSIGN    },
     57        {       "?*=?",   "*=",   "_operator_multassign",        "Multiplication Assignment",  OT_INFIXASSIGN    },
     58        {       "?/=?",   "/=",   "_operator_divassign",         "Division Assignment",        OT_INFIXASSIGN    },
     59        {       "?%=?",   "%=",   "_operator_modassign",         "Modulo Assignment",          OT_INFIXASSIGN    },
     60        {       "?+=?",   "+=",   "_operator_addassign",         "Addition Assignment",        OT_INFIXASSIGN    },
     61        {       "?-=?",   "-=",   "_operator_subassign",         "Substrction Assignment",     OT_INFIXASSIGN    },
     62        {       "?<<=?",  "<<=",  "_operator_shiftleftassign",   "Shift Left Assignment",      OT_INFIXASSIGN    },
     63        {       "?>>=?",  ">>=",  "_operator_shiftrightassign",  "Shift Right Assignment",     OT_INFIXASSIGN    },
     64        {       "?&=?",   "&=",   "_operator_bitandassign",      "Bitwise And Assignment",     OT_INFIXASSIGN    },
     65        {       "?^=?",   "^=",   "_operator_bitxorassign",      "Bitwise Xor Assignment",     OT_INFIXASSIGN    },
     66        {       "?|=?",   "|=",   "_operator_bitorassign",       "Bitwise Or Assignment",      OT_INFIXASSIGN    },
     67}; // tableValues
    7268
    73         CodeGen::CodeGen() {
    74                 enum { numOps = sizeof( tableValues ) / sizeof( OperatorInfo ) };
    75                 for ( int i = 0; i < numOps; i += 1 ) {
    76                         table[ tableValues[i].inputName ] = tableValues[i];
    77                 } // for
     69enum { numOps = sizeof( tableValues ) / sizeof( OperatorInfo ) };
     70
     71const OperatorInfo * operatorLookup( const std::string & inputName ) {
     72        // Static information set up:
     73        static std::unordered_map<std::string, const OperatorInfo *> inputTable;
     74        if ( inputTable.empty() ) for ( const OperatorInfo & op : tableValues ) {
     75                inputTable[ op.inputName ] = &op;
    7876        }
    7977
    80         const OperatorInfo * operatorLookup( const string & funcName ) {
    81                 if ( funcName.find_first_of( "?^*+-!", 0, 1 ) == string::npos ) return nullptr; // prefilter
    82                 const OperatorInfo * ret = &CodeGen::table.find( funcName )->second; // must be in the table
    83                 assert( ret );
    84                 return ret;
     78        if ( inputName.find_first_of( "?^*+-!", 0, 1 ) == std::string::npos ) return nullptr; // prefilter
     79        const OperatorInfo * ret = inputTable.find( inputName )->second;
     80        // This can only happen if an invalid identifier name has been used.
     81        assert( ret );
     82        return ret;
     83}
     84
     85bool isOperator( const std::string & inputName ) {
     86        return operatorLookup( inputName ) != nullptr;
     87}
     88
     89std::string operatorFriendlyName( const std::string & inputName ) {
     90        const OperatorInfo * info = operatorLookup( inputName );
     91        if ( info ) return info->friendlyName;
     92        return "";
     93}
     94
     95// This is only used in the demangler, so it is smaller (and only maybe slow).
     96const OperatorInfo * operatorLookupByOutput( const std::string & outputName ) {
     97        if ( '_' != outputName[0] ) return nullptr;
     98        for ( const OperatorInfo & op : tableValues ) {
     99                if ( outputName == op.outputName ) {
     100                        return &op;
     101                }
    85102        }
     103        return nullptr;
     104}
    86105
    87         bool isOperator( const string & funcName ) {
    88                 return operatorLookup( funcName ) != nullptr;
    89         }
     106bool isConstructor( const std::string & inputName ) {
     107        const OperatorInfo * info = operatorLookup( inputName );
     108        if ( info ) return info->type == OT_CTOR;
     109        return false;
     110}
    90111
    91         string operatorFriendlyName( const string & funcName ) {
    92                 const OperatorInfo * info = operatorLookup( funcName );
    93                 if ( info ) return info->friendlyName;
    94                 return "";
    95         }
     112bool isDestructor( const std::string & inputName ) {
     113        const OperatorInfo * info = operatorLookup( inputName );
     114        if ( info ) return info->type == OT_DTOR;
     115        return false;
     116}
    96117
    97         bool isConstructor( const string & funcName ) {
    98                 const OperatorInfo * info = operatorLookup( funcName );
    99                 if ( info ) return info->type == OT_CTOR;
    100                 return false;
    101         }
     118bool isCtorDtor( const std::string & inputName ) {
     119        const OperatorInfo * info = operatorLookup( inputName );
     120        if ( info ) return info->type <= OT_CONSTRUCTOR;
     121        return false;
     122}
    102123
    103         bool isDestructor( const string & funcName ) {
    104                 const OperatorInfo * info = operatorLookup( funcName );
    105                 if ( info ) return info->type == OT_DTOR;
    106                 return false;
    107         }
     124bool isAssignment( const std::string & inputName ) {
     125        const OperatorInfo * info = operatorLookup( inputName );
     126        if ( info ) return info->type > OT_CONSTRUCTOR && info->type <= OT_ASSIGNMENT;
     127        return false;
     128}
    108129
    109         bool isCtorDtor( const string & funcName ) {
    110                 const OperatorInfo * info = operatorLookup( funcName );
    111                 if ( info ) return info->type <= OT_CONSTRUCTOR;
    112                 return false;
    113         }
     130bool isCtorDtorAssign( const std::string & inputName ) {
     131        const OperatorInfo * info = operatorLookup( inputName );
     132        if ( info ) return info->type <= OT_ASSIGNMENT;
     133        return false;
     134}
    114135
    115         bool isAssignment( const string & funcName ) {
    116                 const OperatorInfo * info = operatorLookup( funcName );
    117                 if ( info ) return info->type > OT_CONSTRUCTOR && info->type <= OT_ASSIGNMENT;
    118                 return false;
    119         }
    120 
    121         bool isCtorDtorAssign( const string & funcName ) {
    122                 const OperatorInfo * info = operatorLookup( funcName );
    123                 if ( info ) return info->type <= OT_ASSIGNMENT;
    124                 return false;
    125         }
    126 
    127         CodeGen codegen;                                                                        // initialize singleton package
    128136} // namespace CodeGen
    129137
  • src/CodeGen/OperatorTable.h

    r0030b508 rfc12f05  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 16 08:13:34 2020
    13 // Update Count     : 26
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov  3 14:53:00 2023
     13// Update Count     : 27
    1414//
    1515
     
    1717
    1818#include <string>
    19 #include <map>
    2019
    2120namespace CodeGen {
    22         enum OperatorType {
    23                 OT_CTOR,
    24                 OT_DTOR,
    25                 OT_CONSTRUCTOR = OT_DTOR,
    26                 OT_PREFIXASSIGN,
    27                 OT_POSTFIXASSIGN,
    28                 OT_INFIXASSIGN,
    29                 OT_ASSIGNMENT = OT_INFIXASSIGN,
    30                 OT_CALL,
    31                 OT_PREFIX,
    32                 OT_INFIX,
    33                 OT_POSTFIX,
    34                 OT_INDEX,
    35                 OT_LABELADDRESS,
    36                 OT_CONSTANT
    37         };
    3821
    39         struct OperatorInfo {
    40                 std::string inputName;
    41                 std::string symbol;
    42                 std::string outputName;
    43                 std::string friendlyName;
    44                 OperatorType type;
    45         };
     22enum OperatorType {
     23        OT_CTOR,
     24        OT_DTOR,
     25        OT_CONSTRUCTOR = OT_DTOR,
     26        OT_PREFIXASSIGN,
     27        OT_POSTFIXASSIGN,
     28        OT_INFIXASSIGN,
     29        OT_ASSIGNMENT = OT_INFIXASSIGN,
     30        OT_CALL,
     31        OT_PREFIX,
     32        OT_INFIX,
     33        OT_POSTFIX,
     34        OT_INDEX,
     35        OT_LABELADDRESS,
     36        OT_CONSTANT
     37};
    4638
    47         class CodeGen {
    48                 friend const OperatorInfo * operatorLookup( const std::string & funcName );
     39struct OperatorInfo {
     40        // The Cforall special function name.
     41        std::string inputName;
     42        // The string used when the operator is used as an operator.
     43        std::string symbol;
     44        // The base name used in the mangled name.
     45        std::string outputName;
     46        // Human-readable name of the operator.
     47        std::string friendlyName;
     48        // The type of operator shows how it is used as an operator.
     49        OperatorType type;
     50};
    4951
    50                 static const OperatorInfo tableValues[];
    51                 static std::map< std::string, OperatorInfo > table;
    52           public:
    53                 CodeGen();
    54         }; // CodeGen
     52// Look up the operator (by inputName), return nullptr if no such operator.
     53const OperatorInfo * operatorLookup( const std::string & inputName );
     54// Is there an operator with this name?
     55bool isOperator( const std::string & inputName );
     56// Get the friendlyName of the operator with the inputName
     57std::string operatorFriendlyName( const std::string & inputName );
     58// Get the OperatorInfo with the given outputName, if one exists.
     59const OperatorInfo * operatorLookupByOutput( const std::string & outputName );
    5560
    56         bool isOperator( const std::string & funcName );
    57         const OperatorInfo * operatorLookup( const std::string & funcName );
    58         std::string operatorFriendlyName( const std::string & funcName );
     61// Is the operator a constructor, destructor or any form of assignment.
     62// (Last two are "or" combinations of the first three.)
     63bool isConstructor( const std::string & );
     64bool isDestructor( const std::string & );
     65bool isAssignment( const std::string & );
     66bool isCtorDtor( const std::string & );
     67bool isCtorDtorAssign( const std::string & );
    5968
    60         bool isConstructor( const std::string & );
    61         bool isDestructor( const std::string & );
    62         bool isAssignment( const std::string & );
    63         bool isCtorDtor( const std::string & );
    64         bool isCtorDtorAssign( const std::string & );
    6569} // namespace CodeGen
    6670
  • src/CodeGen/module.mk

    r0030b508 rfc12f05  
    1616
    1717SRC_CODEGEN = \
    18         CodeGen/FixMain2.cc \
    19         CodeGen/FixMain.h \
     18        CodeGen/CodeGeneratorNew.cpp \
     19        CodeGen/CodeGeneratorNew.hpp \
     20        CodeGen/GenType.cc \
     21        CodeGen/GenType.h \
    2022        CodeGen/OperatorTable.cc \
    2123        CodeGen/OperatorTable.h
    2224
    2325SRC += $(SRC_CODEGEN) \
    24         CodeGen/CodeGenerator.cc \
    25         CodeGen/CodeGenerator.h \
    2626        CodeGen/Generate.cc \
    2727        CodeGen/Generate.h \
    2828        CodeGen/FixMain.cc \
     29        CodeGen/FixMain.h \
    2930        CodeGen/FixNames.cc \
    3031        CodeGen/FixNames.h \
    31         CodeGen/GenType.cc \
    32         CodeGen/GenType.h \
    3332        CodeGen/LinkOnce.cc \
    3433        CodeGen/LinkOnce.h \
Note: See TracChangeset for help on using the changeset viewer.