source: src/main.cc@ 69dd8e6

Last change on this file since 69dd8e6 was eb7586e, checked in by JiadaL <j82liang@…>, 17 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
[51b73452]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
[51b73452]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;
[3b3491b6]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
[51b73452]709// Local Variables: //
[b87a5ed]710// tab-width: 4 //
711// mode: c++ //
712// compile-command: "make install" //
[51b73452]713// End: //
Note: See TracBrowser for help on using the repository browser.