Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/FixMain.cc

    r9939dc3 r61efa42  
    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
Note: See TracChangeset for help on using the changeset viewer.