source: src/main.cc @ eb7586e

Last change on this file since eb7586e was eb7586e, checked in by JiadaL <j82liang@…>, 2 months ago
  1. Change return value of typed Enum in null context: they now return the position. Therefore, printf with enumeration value will no longer be supported. 2. sout now will return the enumeration value. So sout | enumValue will print what we expect. 3. Provide enum.hfa, which contains traits that related to enum. 4. Implement functions declare in enum.hfa for enum types, so enum type fulfill the traits. Known defeat: error if we use the enum traits on enum types. They work but c compiler gives an warning
  • Property mode set to 100644
File size: 28.1 KB
RevLine 
[b87a5ed]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[71f4e4f]7// main.cc --
[b87a5ed]8//
[3e96559]9// Author           : Peter Buhr and Rob Schluntz
[b87a5ed]10// Created On       : Fri May 15 23:12:02 2015
[372b6d3]11// Last Modified By : Peter A. Buhr
[be3f163]12// Last Modified On : Wed Nov  1 21:12:58 2023
13// Update Count     : 690
[b87a5ed]14//
15
[bf2438c]16#include <cxxabi.h>                         // for __cxa_demangle
17#include <execinfo.h>                       // for backtrace, backtrace_symbols
18#include <getopt.h>                         // for no_argument, optind, geto...
[08fc48f]19#include <cassert>                          // for assertf
[bf2438c]20#include <cstdio>                           // for fopen, FILE, fclose, stdin
21#include <cstdlib>                          // for exit, free, abort, EXIT_F...
[bffcd66]22#include <csignal>                          // for signal, SIGABRT, SIGSEGV
[bf2438c]23#include <cstring>                          // for index
[be9288a]24#include <fstream>                          // for ofstream
[bf2438c]25#include <iostream>                         // for operator<<, basic_ostream
[62ce290]26#include <iomanip>
[bf2438c]27#include <iterator>                         // for back_inserter
28#include <list>                             // for list
[08fc48f]29#include <string>                           // for char_traits, operator<<
[e6955b1]30
[bccd70a]31#include "AST/Pass.hpp"                     // for pass_visitor_stats
[0b5e780]32#include "AST/Print.hpp"                    // for printAll
[bccd70a]33#include "AST/TranslationUnit.hpp"          // for TranslationUnit
[52f9804]34#include "AST/Util.hpp"                     // for checkInvariants
[7f38b67a]35#include "CompilationState.h"
[bf2438c]36#include "../config.h"                      // for CFA_LIBDIR
37#include "CodeGen/FixMain.h"                // for FixMain
38#include "CodeGen/FixNames.h"               // for fixNames
39#include "CodeGen/Generate.h"               // for generate
[aff7e86]40#include "CodeGen/LinkOnce.h"               // for translateLinkOnce
[f57faf6f]41#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
[55cbff8]42#include "Common/DeclStats.hpp"             // for printDeclStats
43#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
[09366b8]44#include "Common/Stats.h"                   // for Stats
[bf2438c]45#include "Common/utility.h"                 // for deleteAll, filter, printAll
[3dd8f42]46#include "Concurrency/Actors.hpp"           // for implementActors
[eb779d5]47#include "Concurrency/Corun.hpp"            // for implementCorun
[2cf3b87]48#include "Concurrency/Keywords.h"           // for implementMutex, implement...
[9f5ecf5]49#include "Concurrency/Waitfor.h"            // for generateWaitfor
[c86b08d]50#include "Concurrency/Waituntil.hpp"        // for generateWaitUntil
[0c730d9]51#include "ControlStruct/ExceptDecl.h"       // for translateExcept
[09366b8]52#include "ControlStruct/ExceptTranslate.h"  // for translateThrows, translat...
[b8ab91a]53#include "ControlStruct/FixLabels.hpp"      // for fixLabels
[a488783]54#include "ControlStruct/HoistControlDecls.hpp" //  hoistControlDecls
[bf2438c]55#include "GenPoly/Box.h"                    // for box
56#include "GenPoly/InstantiateGeneric.h"     // for instantiateGeneric
57#include "GenPoly/Lvalue.h"                 // for convertLvalue
58#include "GenPoly/Specialize.h"             // for convertSpecializations
59#include "InitTweak/FixInit.h"              // for fix
60#include "InitTweak/GenInit.h"              // for genInit
61#include "MakeLibCfa.h"                     // for makeLibCfa
[cbd1ba8]62#include "Parser/RunParser.hpp"             // for buildList, dumpParseTree,...
[1622af5]63#include "ResolvExpr/CandidatePrinter.hpp"  // for printCandidates
[d3652df]64#include "ResolvExpr/EraseWith.hpp"         // for eraseWith
[bf2438c]65#include "ResolvExpr/Resolver.h"            // for resolve
66#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
[a488783]67#include "Validate/Autogen.hpp"             // for autogenerateRoutines
[af746cc]68#include "Validate/ImplementEnumFunc.hpp"   // for implementEnumFunc
[298fe57]69#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
70#include "Validate/EliminateTypedef.hpp"    // for eliminateTypedef
[1931bb01]71#include "Validate/EnumAndPointerDecay.hpp" // for decayEnumsAndPointers
[ce36b55]72#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
[298fe57]73#include "Validate/FixQualifiedTypes.hpp"   // for fixQualifiedTypes
[1931bb01]74#include "Validate/FixReturnTypes.hpp"      // for fixReturnTypes
[9490621]75#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
[298fe57]76#include "Validate/GenericParameter.hpp"    // for fillGenericParameters, tr...
77#include "Validate/HoistStruct.hpp"         // for hoistStruct
[1931bb01]78#include "Validate/HoistTypeDecls.hpp"      // for hoistTypeDecls
[ce36b55]79#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
80#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
[37b3151]81#include "Validate/LinkInstanceTypes.hpp"   // for linkInstanceTypes
[1931bb01]82#include "Validate/ReplaceTypedef.hpp"      // for replaceTypedef
[4ec9513]83#include "Validate/ReturnCheck.hpp"         // for checkReturnStatements
[1931bb01]84#include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
[61e362f]85#include "Validate/ReplacePseudoFunc.hpp"   // for replacePseudoFunc
[a5f0529]86#include "Virtual/ExpandCasts.h"            // for expandCasts
[37b3151]87#include "Virtual/VirtualDtor.hpp"          // for implementVirtDtors
[51b7345]88
[2c38b15]89using namespace std;
90
[3e96559]91static void NewPass( const char * const name ) {
92        Stats::Heap::newPass( name );
[1cb7fab2]93        using namespace Stats::Counters;
[b8665e3]94        {
[f43146e4]95                static auto group = build<CounterGroup>( "Pass Visitor Template" );
[3e96559]96                auto pass = build<CounterGroup>( name, group );
[f43146e4]97                ast::pass_visitor_stats.depth = 0;
98                ast::pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass );
99                ast::pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass );
[b8665e3]100        }
[675716e]101}
102
[52f9804]103#define PASS( name, pass, unit, ... )       \
[ecaeac6e]104        if ( errorp ) { cerr << name << endl; } \
[675716e]105        NewPass(name);                          \
[4f97937]106        Stats::Time::StartBlock(name);          \
[52f9804]107        pass(unit,##__VA_ARGS__);               \
108        Stats::Time::StopBlock();               \
109        if ( invariant ) {                      \
[5b25c49]110                ast::checkInvariants(unit);         \
[52f9804]111        }
112
113#define DUMP( cond, unit )                  \
114        if ( cond ) {                           \
115                dump(unit);                         \
116                return EXIT_SUCCESS;                \
117        }
[0da3e2c]118
[ef22ad6]119static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
[dee1f89]120
[bffcd66]121static string PreludeDirector = "";
[4dcaed2]122
[77d601f]123static void parse_cmdline( int argc, char * argv[] );
[e499381]124static void dump( ast::TranslationUnit && transUnit, ostream & out = cout );
[e6955b1]125
[0afffee]126static void backtrace( int start ) {                                    // skip first N stack frames
[74330e7]127        enum { Frames = 50, };                                                          // maximum number of stack frames
[e6955b1]128        void * array[Frames];
[74330e7]129        size_t size = ::backtrace( array, Frames );
[0afffee]130        char ** messages = ::backtrace_symbols( array, size ); // does not demangle names
131
132        *index( messages[0], '(' ) = '\0';                                      // find executable name
133        cerr << "Stack back trace for: " << messages[0] << endl;
[e6955b1]134
[b542bfb]135        // skip last 2 stack frames after main
[74330e7]136        for ( unsigned int i = start; i < size - 2 && messages != nullptr; i += 1 ) {
[e6955b1]137                char * mangled_name = nullptr, * offset_begin = nullptr, * offset_end = nullptr;
[7006ba5]138
139                for ( char * p = messages[i]; *p; p += 1 ) {    // find parantheses and +offset
[0afffee]140                        if ( *p == '(' ) {
[46f6134]141                                mangled_name = p;
[0afffee]142                        } else if ( *p == '+' ) {
[e6955b1]143                                offset_begin = p;
[0afffee]144                        } else if ( *p == ')' ) {
[e6955b1]145                                offset_end = p;
146                                break;
147                        } // if
148                } // for
149
150                // if line contains symbol, attempt to demangle
[b542bfb]151                int frameNo = i - start;
[e6955b1]152                if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin ) {
[0afffee]153                        *mangled_name++ = '\0';                                         // delimit strings
[e6955b1]154                        *offset_begin++ = '\0';
155                        *offset_end++ = '\0';
156
[0afffee]157                        int status;
[e6955b1]158                        char * real_name = __cxxabiv1::__cxa_demangle( mangled_name, 0, 0, &status );
[0afffee]159                        // bug in __cxa_demangle for single-character lower-case non-mangled names
[e6955b1]160                        if ( status == 0 ) {                                            // demangling successful ?
[b542bfb]161                                cerr << "(" << frameNo << ") " << messages[i] << " : "
[e6955b1]162                                         << real_name << "+" << offset_begin << offset_end << endl;
163                        } else {                                                                        // otherwise, output mangled name
[b542bfb]164                                cerr << "(" << frameNo << ") " << messages[i] << " : "
[0afffee]165                                         << mangled_name << "(/*unknown*/)+" << offset_begin << offset_end << endl;
[e6955b1]166                        } // if
[0afffee]167
[e6955b1]168                        free( real_name );
169                } else {                                                                                // otherwise, print the whole line
[b542bfb]170                        cerr << "(" << frameNo << ") " << messages[i] << endl;
[e6955b1]171                } // if
172        } // for
[b542bfb]173
[e6955b1]174        free( messages );
[b542bfb]175} // backtrace
176
[bffcd66]177#define SIGPARMS int sig __attribute__(( unused )), siginfo_t * sfp __attribute__(( unused )), ucontext_t * cxt __attribute__(( unused ))
178
[1f68d5d]179static void _Signal(struct sigaction & act, int sig, int flags ) {
[dacd2c19]180        sigemptyset( &act.sa_mask );
[bffcd66]181        act.sa_flags = flags;
182
183        if ( sigaction( sig, &act, nullptr ) == -1 ) {
[77d601f]184            cerr << "*cfa-cpp compilation error* problem installing signal handler, error(" << errno << ") " << strerror( errno ) << endl;
[bffcd66]185            _exit( EXIT_FAILURE );
186        } // if
[1f68d5d]187}
188
189static void Signal( int sig, void (* handler)(SIGPARMS), int flags ) {
190        struct sigaction act;
191        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
192        _Signal(act, sig, flags);
193} // Signal
194
195static void Signal( int sig, void (* handler)(int), int flags ) {
196        struct sigaction act;
197        act.sa_handler = handler;
198        _Signal(act, sig, flags);
[bffcd66]199} // Signal
200
201static void sigSegvBusHandler( SIGPARMS ) {
202        if ( sfp->si_addr == nullptr ) {
203                cerr << "Null pointer (nullptr) dereference." << endl;
204        } else {
205                cerr << (sig == SIGSEGV ? "Segment fault" : "Bus error") << " at memory location " << sfp->si_addr << "." << endl
206                         << "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript." << endl;
207        } // if
[b542bfb]208        backtrace( 2 );                                                                         // skip first 2 stack frames
[3e96559]209        abort();                                                                                        // cause core dump for debugging
[e6955b1]210} // sigSegvBusHandler
[0da3e2c]211
[74330e7]212static void sigFpeHandler( SIGPARMS ) {
213        const char * msg;
214
215        switch ( sfp->si_code ) {
216          case FPE_INTDIV: case FPE_FLTDIV: msg = "divide by zero"; break;
217          case FPE_FLTOVF: msg = "overflow"; break;
218          case FPE_FLTUND: msg = "underflow"; break;
219          case FPE_FLTRES: msg = "inexact result"; break;
220          case FPE_FLTINV: msg = "invalid operation"; break;
221          default: msg = "unknown";
222        } // choose
223        cerr << "Computation error " << msg << " at location " << sfp->si_addr << endl
224                 << "Possible cause is constant-expression evaluation invalid." << endl;
225        backtrace( 2 );                                                                         // skip first 2 stack frames
226        abort();                                                                                        // cause core dump for debugging
227} // sigFpeHandler
228
[bffcd66]229static void sigAbortHandler( SIGPARMS ) {
[b542bfb]230        backtrace( 6 );                                                                         // skip first 6 stack frames
[1f68d5d]231        Signal( SIGABRT, SIG_DFL, SA_SIGINFO ); // reset default signal handler
[9be45a2]232        raise( SIGABRT );                                                                       // reraise SIGABRT
[b542bfb]233} // sigAbortHandler
234
[cbaee0d]235int main( int argc, char * argv[] ) {
[3b8e52c]236        FILE * input;                                                                           // use FILE rather than istream because yyin is FILE
[d08beee]237        ostream * output = & cout;
[64b3cda]238        ast::TranslationUnit transUnit;
[e6955b1]239
[bffcd66]240        Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO );
241        Signal( SIGBUS, sigSegvBusHandler, SA_SIGINFO );
[74330e7]242        Signal( SIGFPE, sigFpeHandler, SA_SIGINFO );
[bffcd66]243        Signal( SIGABRT, sigAbortHandler, SA_SIGINFO );
[b87a5ed]244
[bffcd66]245        // cout << "main" << endl;
[44bca7f]246        // for ( int i = 0; i < argc; i += 1 ) {
[bffcd66]247        //      cout << '\t' << argv[i] << endl;
[44bca7f]248        // } // for
249
[e0bd0f9]250        parse_cmdline( argc, argv );                                            // process command-line arguments
[b87a5ed]251
[ef22ad6]252        if ( waiting_for_gdb ) {
[bffcd66]253                cerr << "Waiting for gdb" << endl;
254                cerr << "run :" << endl;
255                cerr << "  gdb attach " << getpid() << endl;
[dee1f89]256                raise(SIGSTOP);
[ef22ad6]257        } // if
[dee1f89]258
[b87a5ed]259        try {
[81419b5]260                // choose to read the program from a file or stdin
[3b8e52c]261                if ( optind < argc ) {                                                  // any commands after the flags ? => input file name
[b87a5ed]262                        input = fopen( argv[ optind ], "r" );
[e0bd0f9]263                        assertf( input, "cannot open %s because %s\n", argv[ optind ], strerror( errno ) );
[b87a5ed]264                        optind += 1;
[3b8e52c]265                } else {                                                                                // no input file name
[b87a5ed]266                        input = stdin;
267                } // if
268
[79eaeb7]269                Stats::Time::StartGlobal();
[3c0d4cd]270                NewPass("Parse");
271                Stats::Time::StartBlock("Parse");
[675716e]272
[159c62e]273                // read in the builtins, extras, and the prelude
[de62360d]274                if ( ! nopreludep ) {                                                   // include gcc builtins
[faf8857]275                        // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here.
[807ce84]276
[37fe352]277                        assertf( !PreludeDirector.empty(), "Can't find prelude without option --prelude-dir must be used." );
[4dcaed2]278
[807ce84]279                        // Read to gcc builtins, if not generating the cfa library
[be3f163]280                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cfa").c_str(), "r" );
[6ce3ae9]281                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
[f2f595d7]282                        parse( gcc_builtins, ast::Linkage::Compiler );
[81419b5]283
[159c62e]284                        // read the extra prelude in, if not generating the cfa library
[be3f163]285                        FILE * extras = fopen( (PreludeDirector + "/extras.cfa").c_str(), "r" );
[3b8e52c]286                        assertf( extras, "cannot open extras.cf\n" );
[f2f595d7]287                        parse( extras, ast::Linkage::BuiltinC );
[81419b5]288                        if ( ! libcfap ) {
[faf8857]289                                // read the prelude in, if not generating the cfa library
[e523b07]290                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
291                                assertf( prelude, "cannot open prelude.cfa\n" );
[f2f595d7]292                                parse( prelude, ast::Linkage::Intrinsic );
[fa4805f]293
294                                // Read to cfa builtins, if not generating the cfa library
[be3f163]295                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cfa").c_str(), "r" );
[fa4805f]296                                assertf( builtins, "cannot open builtins.cf\n" );
[f2f595d7]297                                parse( builtins, ast::Linkage::BuiltinCFA );
[b87a5ed]298                        } // if
299                } // if
[81419b5]300
[f2f595d7]301                parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );
[71f4e4f]302
[64b3cda]303                transUnit = buildUnit();
[b87a5ed]304
[52f9804]305                DUMP( astp, std::move( transUnit ) );
[b87a5ed]306
[3c0d4cd]307                Stats::Time::StopBlock();
[036dd5f]308
[52f9804]309                PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit );
310
311                PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit );
312                DUMP( exdeclp, std::move( transUnit ) );
313                PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit );
314                PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit );
315                PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit );
316                PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit );
317
[37b3151]318                PASS( "Link Instance Types", Validate::linkInstanceTypes, transUnit );
[52f9804]319
[14c0f7b]320                PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit );
[52f9804]321                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit );
[59c8dff]322
[52f9804]323                PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
[2c38b15]324                PASS( "Hoist Struct", Validate::hoistStruct, transUnit );
[52f9804]325                PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit );
326                PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
[eb7586e]327                // Need to happen before fixing returns because implementEnumFunc has ReturnStmt
328               
329                PASS( "Generate Enum Attributes Functions", Validate::implementEnumFunc, transUnit );
[52f9804]330                PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit );
331                PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit );
332                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit );
[14c0f7b]333                PASS( "Fix Unique Ids", Validate::fixUniqueIds, transUnit );
[cf3da24]334                PASS( "Implement Corun", Concurrency::implementCorun, transUnit );
[52f9804]335                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit );
336
337                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit );
[eb7586e]338               
[52f9804]339                PASS( "Implement Actors", Concurrency::implementActors, transUnit );
340                PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit );
341                PASS( "Implement Mutex", Concurrency::implementMutex, transUnit );
342                PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit );
343                PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit );
344                PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit );
345                PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit );
346                PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit );
[09366b8]347
348                if ( symtabp ) {
349                        return EXIT_SUCCESS;
350                } // if
[ccbc65c]351
[09366b8]352                if ( expraltp ) {
353                        ResolvExpr::printCandidates( transUnit );
354                        return EXIT_SUCCESS;
355                } // if
[3606fe4]356
[52f9804]357                DUMP( validp, std::move( transUnit ) );
[6a896b0]358
[52f9804]359                PASS( "Translate Throws", ControlStruct::translateThrows, transUnit );
360                PASS( "Fix Labels", ControlStruct::fixLabels, transUnit );
[14c0f7b]361                PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit  );
[52f9804]362                PASS( "Fix Names", CodeGen::fixNames, transUnit );
363                PASS( "Gen Init", InitTweak::genInit, transUnit );
364                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit );
[ce36b55]365
[09366b8]366                if ( libcfap ) {
367                        // Generate the bodies of cfa library functions.
368                        LibCfa::makeLibCfa( transUnit );
369                } // if
[1622af5]370
[09366b8]371                if ( declstatsp ) {
372                        printDeclStats( transUnit );
373                        return EXIT_SUCCESS;
374                } // if
[1622af5]375
[52f9804]376                DUMP( bresolvep, std::move( transUnit ) );
[1622af5]377
[09366b8]378                if ( resolvprotop ) {
379                        dumpAsResolverProto( transUnit );
380                        return EXIT_SUCCESS;
381                } // if
[9f5a19fa]382
[52f9804]383                PASS( "Resolve", ResolvExpr::resolve, transUnit );
384                DUMP( exprp, std::move( transUnit ) );
[7b05de4]385                PASS( "Replace Pseudo Func", Validate::replacePseudoFunc, transUnit );
[af746cc]386                PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); // Here
[d3652df]387                PASS( "Erase With", ResolvExpr::eraseWith, transUnit );
[68fe946e]388
[09366b8]389                // fix ObjectDecl - replaces ConstructorInit nodes
[52f9804]390                DUMP( ctorinitp, std::move( transUnit ) );
[68fe946e]391
[09366b8]392                // Currently not working due to unresolved issues with UniqueExpr
[52f9804]393                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr, transUnit ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
[68fe946e]394
[52f9804]395                PASS( "Translate Tries", ControlStruct::translateTries, transUnit );
396                PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit );
[61efa42]397                PASS( "Fix Main Linkage", CodeGen::fixMainLinkage, transUnit, !nomainp );
[4615ac8]398
[09366b8]399                // Needs to happen before tuple types are expanded.
[52f9804]400                PASS( "Convert Specializations",  GenPoly::convertSpecializations, transUnit );
[81419b5]401
[52f9804]402                PASS( "Expand Tuples", Tuples::expandTuples, transUnit );
403                DUMP( tuplep, std::move( transUnit ) );
[626dbc10]404
[09366b8]405                // Must come after Translate Tries.
[52f9804]406                PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit );
[141b786]407
[52f9804]408                PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit );
409                DUMP( genericsp, std::move( transUnit ) );
[b4f8808]410
[52f9804]411                PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit );
[1ee0a4da]412                DUMP( bboxp, std::move( transUnit ) );
413                PASS( "Box", GenPoly::box, transUnit );
[3cbe320]414                PASS( "Link-Once", CodeGen::translateLinkOnce, transUnit );
[7fffb1b]415
[aff7e86]416                // Code has been lowered to C, now we can start generation.
417
[8941b6b]418                DUMP( bcodegenp, std::move( transUnit ) );
[8905f56]419
[13de47bc]420                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
421                        output = new ofstream( argv[ optind ] );
422                } // if
[0270824]423
[8941b6b]424                PASS( "Code Gen", CodeGen::generate, transUnit, *output, !genproto, prettycodegenp, true, linemarks, false );
[61efa42]425                CodeGen::fixMainInvoke( transUnit, *output, (PreludeDirector + "/bootloader.c").c_str() );
[8941b6b]426
[e6955b1]427                if ( output != &cout ) {
[b87a5ed]428                        delete output;
429                } // if
[77d601f]430        } catch ( SemanticErrorException & e ) {
[b87a5ed]431                if ( errorp ) {
[e6955b1]432                        cerr << "---AST at error:---" << endl;
[0b5e780]433                        dump( std::move( transUnit ), cerr );
[e6955b1]434                        cerr << endl << "---End of AST, begin error message:---\n" << endl;
[926af74]435                } // if
[d55d7a6]436                e.print();
[e6955b1]437                if ( output != &cout ) {
[b87a5ed]438                        delete output;
439                } // if
[3e96559]440                return EXIT_FAILURE;
[77d601f]441        } catch ( std::bad_alloc & ) {
442                cerr << "*cfa-cpp compilation error* std::bad_alloc" << endl;
443                backtrace( 1 );
444                abort();
[3e96559]445        } catch ( ... ) {
[bffcd66]446                exception_ptr eptr = current_exception();
[4990812]447                try {
448                        if (eptr) {
[bffcd66]449                                rethrow_exception(eptr);
[3e96559]450                        } else {
[77d601f]451                                cerr << "*cfa-cpp compilation error* exception uncaught and unknown" << endl;
[3e96559]452                        } // if
[77d601f]453                } catch( const exception & e ) {
454                        cerr << "*cfa-cpp compilation error* uncaught exception \"" << e.what() << "\"\n";
[3e96559]455                } // try
456                return EXIT_FAILURE;
457        } // try
[b87a5ed]458
[1cb7fab2]459        Stats::print();
[3e96559]460        return EXIT_SUCCESS;
[d9a0e76]461} // main
[51b7345]462
[0da3e2c]463
[372b6d3]464static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:";
[3e96559]465
[62ce290]466enum { PreludeDir = 128 };
[3e96559]467static struct option long_opts[] = {
[1a69a90]468        { "colors", required_argument, nullptr, 'c' },
469        { "gdb", no_argument, nullptr, 'g' },
[3e96559]470        { "help", no_argument, nullptr, 'h' },
[372b6d3]471        { "invariant", no_argument, nullptr, 'i' },
[3e96559]472        { "libcfa", no_argument, nullptr, 'l' },
[62ce290]473        { "linemarks", no_argument, nullptr, 'L' },
[372b6d3]474        { "no-main", no_argument, nullptr, 'm' },
[62ce290]475        { "no-linemarks", no_argument, nullptr, 'N' },
476        { "no-prelude", no_argument, nullptr, 'n' },
[3e96559]477        { "prototypes", no_argument, nullptr, 'p' },
[7215000]478        { "deterministic-out", no_argument, nullptr, 'd' },
[62ce290]479        { "print", required_argument, nullptr, 'P' },
480        { "prelude-dir", required_argument, nullptr, PreludeDir },
481        { "statistics", required_argument, nullptr, 'S' },
[3e96559]482        { "tree", no_argument, nullptr, 't' },
483        { "", no_argument, nullptr, 0 },                                        // -w
484        { "", no_argument, nullptr, 0 },                                        // -W
485        { "", no_argument, nullptr, 0 },                                        // -D
486        { nullptr, 0, nullptr, 0 }
487}; // long_opts
488
489static const char * description[] = {
[aa88cb9a]490        "diagnostic color: never, always, auto",                        // -c
[3e9de01]491        "wait for gdb to attach",                                                       // -g
[aa88cb9a]492        "print translator help message",                                        // -h
[372b6d3]493        "invariant checking during AST passes",                         // -i
[3e9de01]494        "generate libcfa.c",                                                            // -l
495        "generate line marks",                                                          // -L
496        "do not replace main",                                                          // -m
497        "do not generate line marks",                                           // -N
498        "do not read prelude",                                                          // -n
[aa88cb9a]499        "do not generate prelude prototypes => prelude not printed", // -p
[3e9de01]500        "only print deterministic output",                  // -d
501        "print",                                                                                        // -P
[62ce290]502        "<directory> prelude directory for debug/nodebug",      // no flag
[aa88cb9a]503        "<option-list> enable profiling information: counters, heap, time, all, none", // -S
[3e9de01]504        "building cfa standard lib",                                            // -t
505        "",                                                                                                     // -w
506        "",                                                                                                     // -W
507        "",                                                                                                     // -D
[3e96559]508}; // description
509
[0c0f548]510static_assert( sizeof( long_opts ) / sizeof( long_opts[0] ) - 1 == sizeof( description ) / sizeof( description[0] ), "Long opts and description must match" );
[62ce290]511
512static struct Printopts {
513        const char * name;
514        int & flag;
515        int val;
516        const char * descript;
517} printopts[] = {
[0e464f6]518        { "ascodegen", codegenp, true, "print AST as codegen rather than AST" },
519        { "asterr", errorp, true, "print AST on error" },
[12f671e]520        { "declstats", declstatsp, true, "print code property statistics" },
521        { "parse", yydebug, true, "print yacc (parsing) debug information" },
[62ce290]522        { "pretty", prettycodegenp, true, "prettyprint for ascodegen flag" },
523        { "rproto", resolvprotop, true, "resolver-proto instance" },
[0e464f6]524        { "rsteps", resolvep, true, "print resolver steps" },
[5f917740]525        // AST dumps
[0e464f6]526        { "ast", astp, true, "print AST after parsing" },
[5f917740]527        { "excpdecl", exdeclp, true, "print AST after translating exception decls" },
[0e464f6]528        { "symevt", symtabp, true, "print AST after symbol table events" },
[5f917740]529        { "expralt", expraltp, true, "print AST after expressions alternatives" },
530        { "valdecl", validp, true, "print AST after declaration validation pass" },
531        { "bresolver", bresolvep, true, "print AST before resolver step" },
532        { "expranly", exprp, true, "print AST after expression analysis" },
[0e464f6]533        { "ctordtor", ctorinitp, true, "print AST after ctor/dtor are replaced" },
534        { "tuple", tuplep, true, "print AST after tuple expansion" },
[5f917740]535        { "instgen", genericsp, true, "print AST after instantiate generics" },
536        { "bbox", bboxp, true, "print AST before box pass" },
[cdb4eaa]537        { "bcodegen", bcodegenp, true, "print AST before code generation" }
[62ce290]538};
539enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) };
540
[77d601f]541static void usage( char * argv[] ) {
[e0bd0f9]542    cout << "Usage: " << argv[0] << " [options] [input-file (default stdin)] [output-file (default stdout)], where options are:" << endl;
[3e96559]543        int i = 0, j = 1;                                                                       // j skips starting colon
544        for ( ; long_opts[i].name != 0 && optstring[j] != '\0'; i += 1, j += 1 ) {
545                if ( long_opts[i].name[0] != '\0' ) {                   // hidden option, internal usage only
[62ce290]546                        if ( strcmp( long_opts[i].name, "prelude-dir" ) != 0 ) { // flag
547                                cout << "  -" << optstring[j] << ",";
548                        } else {                                                                        // no flag
549                                j -= 1;                                                                 // compensate
550                                cout << "     ";
551                        } // if
552                        cout << " --" << left << setw(12) << long_opts[i].name << "  ";
553                        if ( strcmp( long_opts[i].name, "print" ) == 0 ) {
554                                cout << "one of: " << endl;
555                                for ( int i = 0; i < printoptsSize; i += 1 ) {
556                                        cout << setw(10) << " " << left << setw(10) << printopts[i].name << "  " << printopts[i].descript << endl;
557                                } // for
558                        } else {
559                                cout << description[i] << endl;
560                        } // if
[3e96559]561                } // if
[62ce290]562                if ( optstring[j + 1] == ':' ) j += 1;
[3e96559]563        } // for
564        if ( long_opts[i].name != 0 || optstring[j] != '\0' ) assertf( false, "internal error, mismatch of option flags and names\n" );
565    exit( EXIT_FAILURE );
566} // usage
567
[e0bd0f9]568static void parse_cmdline( int argc, char * argv[] ) {
[0da3e2c]569        opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
570
[c5e5109]571        bool Wsuppress = false, Werror = false;
[0da3e2c]572        int c;
[3e96559]573        while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) {
[0da3e2c]574                switch ( c ) {
[1a69a90]575                  case 'c':                                                                             // diagnostic colors
576                        if ( strcmp( optarg, "always" ) == 0 ) {
577                                ErrorHelpers::colors = ErrorHelpers::Colors::Always;
578                        } else if ( strcmp( optarg, "never" ) == 0 ) {
579                                ErrorHelpers::colors = ErrorHelpers::Colors::Never;
580                        } else if ( strcmp( optarg, "auto" ) == 0 ) {
581                                ErrorHelpers::colors = ErrorHelpers::Colors::Auto;
582                        } // if
583                        break;
[3e96559]584                  case 'h':                                                                             // help message
585                        usage( argv );                                                          // no return
[53d3ab4b]586                        break;
[372b6d3]587                  case 'i':                                                                             // invariant checking
588                        invariant = true;
589                        break;
[3e96559]590                  case 'l':                                                                             // generate libcfa.c
[0da3e2c]591                        libcfap = true;
592                        break;
[62ce290]593                  case 'L':                                                                             // generate line marks
[6de43b6]594                        linemarks = true;
[c850687]595                        break;
[3e96559]596                  case 'm':                                                                             // do not replace main
597                        nomainp = true;
[0da3e2c]598                        break;
[62ce290]599                  case 'N':                                                                             // do not generate line marks
[6de43b6]600                        linemarks = false;
[c59bde6]601                        break;
[62ce290]602                  case 'n':                                                                             // do not read prelude
[3e96559]603                        nopreludep = true;
[0da3e2c]604                        break;
[62ce290]605                  case 'p':                                                                             // generate prototypes for prelude functions
606                        genproto = true;
[0da3e2c]607                        break;
[7215000]608                  case 'd':                                     // don't print non-deterministic output
[a77257be]609                        deterministic_output = true;
610                        break;
[62ce290]611                  case 'P':                                                                             // print options
612                        for ( int i = 0;; i += 1 ) {
613                                if ( i == printoptsSize ) {
614                                        cout << "Unknown --print option " << optarg << endl;
615                                        goto Default;
616                                } // if
617                                if ( strcmp( optarg, printopts[i].name ) == 0 ) {
618                                        printopts[i].flag = printopts[i].val;
619                                        break;
620                                } // if
621                        } // for
[0da3e2c]622                        break;
[62ce290]623                  case PreludeDir:                                                              // prelude directory for debug/nodebug, hidden
624                        PreludeDirector = optarg;
[3b3491b]625                        break;
[3e96559]626                  case 'S':                                                                             // enable profiling information, argument comma separated list of names
627                        Stats::parse_params( optarg );
[ebcc940]628                        break;
[dee1f89]629                  case 't':                                                                             // building cfa stdlib
[0da3e2c]630                        treep = true;
631                        break;
[dee1f89]632                  case 'g':                                                                             // wait for gdb
633                        waiting_for_gdb = true;
634                        break;
[3e96559]635                  case 'w':                                                                             // suppress all warnings, hidden
[c5e5109]636                        Wsuppress = true;
[44bca7f]637                        break;
[3e96559]638                  case 'W':                                                                             // coordinate gcc -W with CFA, hidden
[44bca7f]639                        if ( strcmp( optarg, "all" ) == 0 ) {
[68e9ace]640                                SemanticWarning_EnableAll();
[44bca7f]641                        } else if ( strcmp( optarg, "error" ) == 0 ) {
642                                Werror = true;
643                        } else {
644                                char * warning = optarg;
645                                Severity s;
646                                if ( strncmp( optarg, "no-", 3 ) == 0 ) {
647                                        warning += 3;
648                                        s = Severity::Suppress;
649                                } else {
650                                        s = Severity::Warn;
651                                } // if
[68e9ace]652                                SemanticWarning_Set( warning, s );
[44bca7f]653                        } // if
654                        break;
[3e96559]655                  case 'D':                                                                             // ignore -Dxxx, forwarded by cpp, hidden
[0da3e2c]656                        break;
[3e96559]657                  case '?':                                                                             // unknown option
658                        if ( optopt ) {                                                         // short option ?
659                                cout << "Unknown option -" << (char)optopt << endl;
660                        } else {
661                                cout << "Unknown option " << argv[optind - 1] << endl;
662                        } // if
663                        goto Default;
664                  case ':':                                                                             // missing option
[ae47a23]665                        if ( optopt ) {                                                         // short option ?
[3e96559]666                                cout << "Missing option for -" << (char)optopt << endl;
[ae47a23]667                        } else {
[3e96559]668                                cout << "Missing option for " << argv[optind - 1] << endl;
[ae47a23]669                        } // if
[3e96559]670                        goto Default;
671                  Default:
672                  default:
673                        usage( argv );                                                          // no return
[0da3e2c]674                } // switch
675        } // while
[44bca7f]676
677        if ( Werror ) {
[68e9ace]678                SemanticWarning_WarningAsError();
[44bca7f]679        } // if
[c5e5109]680        if ( Wsuppress ) {
681                SemanticWarning_SuppressAll();
682        } // if
[44bca7f]683        // for ( const auto w : WarningFormats ) {
684        //      cout << w.name << ' ' << (int)w.severity << endl;
685        // } // for
[0da3e2c]686} // parse_cmdline
687
[0b5e780]688static bool notPrelude( ast::ptr<ast::Decl> & decl ) {
689        return !decl->linkage.is_builtin;
690}
[926af74]691
[0b5e780]692static void dump( ast::TranslationUnit && unit, std::ostream & out ) {
693        // May filter out all prelude declarations.
[62ce290]694        if ( genproto ) {
[0b5e780]695                std::list<ast::ptr<ast::Decl>> decls;
696                std::copy_if( unit.decls.begin(), unit.decls.end(),
697                        std::back_inserter( decls ), notPrelude );
698                decls.swap( unit.decls );
699        }
[1ab4ce2]700
[0b5e780]701        // May print as full dump or as code generation.
[e39241b]702        if ( codegenp ) {
[0b5e780]703                CodeGen::generate( unit, out, !genproto, prettycodegenp, false, false, false );
[e39241b]704        } else {
[0b5e780]705                ast::printAll( out, unit.decls );
706        }
[e499381]707}
708
[51b7345]709// Local Variables: //
[b87a5ed]710// tab-width: 4 //
711// mode: c++ //
712// compile-command: "make install" //
[51b7345]713// End:  //
Note: See TracBrowser for help on using the repository browser.