Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/FixMain.cc

    r61efa42 r9939dc3  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixMain.cc -- Tools to change a Cforall main into a C main.
     7// FixMain.cc --
    88//
    99// Author           : Thierry Delisle
     
    1313// Update Count     : 0
    1414//
     15
    1516
    1617#include "FixMain.h"
     
    2223
    2324#include "AST/Decl.hpp"
    24 #include "AST/Pass.hpp"
    2525#include "AST/Type.hpp"
    26 #include "AST/Vector.hpp"
     26#include "Common/PassVisitor.h"
    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
    2931#include "SymTab/Mangler.h"
    3032
     
    3335namespace {
    3436
    35 struct FindMainCore final {
    36         ast::FunctionDecl const * main_declaration = nullptr;
     37struct FindMainCore {
     38        FunctionDecl * main_signature = nullptr;
    3739
    38         void previsit( ast::FunctionDecl const * decl ) {
    39                 if ( isMain( decl ) ) {
    40                         if ( main_declaration ) {
     40        void previsit( FunctionDecl * decl ) {
     41                if ( FixMain::isMain( decl ) ) {
     42                        if ( main_signature ) {
    4143                                SemanticError( decl, "Multiple definition of main routine\n" );
    4244                        }
    43                         main_declaration = decl;
     45                        main_signature = decl;
    4446                }
    4547        }
    4648};
    4749
    48 std::string genTypeAt( const ast::vector<ast::Type> & types, size_t at ) {
    49         return genType( types[at], "", Options( false, false, false, false ) );
    5050}
    5151
    52 ast::ObjectDecl * makeIntObj(){
    53         return new ast::ObjectDecl( CodeLocation(), "",
    54                 new ast::BasicType( ast::BasicType::SignedInt ) );
     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
     83namespace {
     84
     85ObjectDecl * signedIntObj() {
     86        return new ObjectDecl(
     87                "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
     88                new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr );
    5589}
    5690
    57 ast::ObjectDecl * makeCharStarStarObj() {
    58         return new ast::ObjectDecl( CodeLocation(), "",
    59                 new ast::PointerType(
    60                         new ast::PointerType(
    61                                 new ast::BasicType( ast::BasicType::Char ) ) ) );
     91ObjectDecl * 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 );
    6298}
    6399
    64 std::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() );
     100std::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() );
    81105}
    82106
    83 std::string getMangledNameOf0ParameterMain() {
    84         return getMangledNameOfMain( {}, ast::VariableArgs );
     107std::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 );
    85111}
    86112
    87 std::string getMangledNameOf2ParameterMain() {
    88         return getMangledNameOfMain( {
    89                 makeIntObj(),
    90                 makeCharStarStarObj(),
    91         }, ast::FixedArgs );
     113std::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 );
    92119}
    93120
     
    95122        // This breaks if you move it out of the function.
    96123        static const std::string mangled_mains[] = {
    97                 getMangledNameOf0ParameterMain(),
    98                 getMangledNameOf2ParameterMain(),
    99                 //getMangledNameOf3ParameterMain(),
     124                mangled_0_argument_main(),
     125                mangled_2_argument_main(),
     126                //mangled_3_argument_main(),
    100127        };
    101128
     
    106133}
    107134
    108 struct 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 
    118135} // namespace
    119136
    120 bool isMain( const ast::FunctionDecl * decl ) {
     137bool 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
     144bool FixMain::isMain( const ast::FunctionDecl * decl ) {
    121145        if ( std::string("main") != decl->name ) {
    122146                return false;
     
    125149}
    126150
    127 void 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 
    134 void 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
     151};
Note: See TracChangeset for help on using the changeset viewer.