source: src/main.cc@ cd79053

Last change on this file since cd79053 was 37b3151, checked in by Andrew Beach <ajbeach@…>, 22 months ago

Rename the linkReferenceTypes pass and the file that contains it. BaseInstType used to be called ReferenceToType, so the reason for the pass being called that is no longer true.

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