Changeset b038fe4
- Timestamp:
- May 9, 2019, 4:48:12 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 292d599
- Parents:
- 63364d8 (diff), 02af79b0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 22 added
- 41 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/FullBuild
r63364d8 rb038fe4 17 17 18 18 parallel ( 19 gcc_6_x64: { trigger_build( 'gcc-6', 'x64' , true) },20 gcc_6_x86: { trigger_build( 'gcc-6', 'x86' , true) },21 gcc_5_x64: { trigger_build( 'gcc-5', 'x64' , false) },22 gcc_5_x86: { trigger_build( 'gcc-5', 'x86' , false) },23 clang_x64: { trigger_build( 'clang', 'x64' , false) },24 clang_x86: { trigger_build( 'clang', 'x86' , false) },19 gcc_6_x64: { trigger_build( 'gcc-6', 'x64' ) }, 20 gcc_6_x86: { trigger_build( 'gcc-6', 'x86' ) }, 21 gcc_5_x64: { trigger_build( 'gcc-5', 'x64' ) }, 22 gcc_5_x86: { trigger_build( 'gcc-5', 'x86' ) }, 23 clang_x64: { trigger_build( 'clang', 'x64' ) }, 24 clang_x86: { trigger_build( 'clang', 'x86' ) }, 25 25 ) 26 26 } … … 56 56 //=========================================================================================================== 57 57 58 def trigger_build(String cc, String arch , Boolean publish) {58 def trigger_build(String cc, String arch) { 59 59 def result = build job: 'Cforall/master', \ 60 60 parameters: [ \ … … 76 76 [$class: 'BooleanParameterValue', \ 77 77 name: 'Publish', \ 78 value: publish], \78 value: true], \ 79 79 [$class: 'BooleanParameterValue', \ 80 80 name: 'Silent', \ -
Jenkinsfile
r63364d8 rb038fe4 170 170 build_stage('Publish') { 171 171 172 if( !Settings.RunBenchmark ) { echo 'No results to publish!!!' }172 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' } 173 173 174 174 def groupCompile = new PlotGroup('Compilation', 'seconds', true) … … 433 433 } 434 434 435 def do_plot(boolean silent, String file, PlotGroup group, String title) { 436 437 def series = silent ? [] : [[ 435 def do_plot(boolean new_data, String file, PlotGroup group, String title) { 436 437 if(new_data) { 438 echo "Publishing new data" 439 } 440 441 def series = new_data ? [] : [[ 438 442 file: "${file}.csv", 439 443 exclusionValues: '', -
doc/papers/concurrency/Paper.tex
r63364d8 rb038fe4 241 241 \corres{*Peter A. Buhr, Cheriton School of Computer Science, University of Waterloo, 200 University Avenue West, Waterloo, ON, N2L 3G1, Canada. \email{pabuhr{\char`\@}uwaterloo.ca}} 242 242 243 \fundingInfo{Natural Sciences and Engineering Research Council of Canada}243 % \fundingInfo{Natural Sciences and Engineering Research Council of Canada} 244 244 245 245 \abstract[Summary]{ 246 \CFA is a modern, polymorphic, non-object-oriented, backwards-compatible extension of the C programming language. 247 This paper discusses some advanced control-flow and concurrency/parallelism features in \CFA, along with the supporting runtime. 248 These features are created from scratch because they do not exist in ISO C, or are low-level and/or unimplemented, so C programmers continue to rely on library features, like C pthreads. 249 \CFA introduces language-level control-flow mechanisms, like coroutines, user-level threading, and monitors for mutual exclusion and synchronization. 250 A unique contribution of this work is allowing multiple monitors to be safely acquired \emph{simultaneously} (deadlock free), while integrating this capability with monitor synchronization mechanisms. 251 These features also integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers. 246 \CFA is a polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language. 247 This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime. 248 These features are created from scratch as ISO C has only low-level and/or unimplemented concurrency, so C programmers continue to rely on library features like C pthreads. 249 \CFA introduces modern language-level control-flow mechanisms, like coroutines, user-level threading, and monitors for mutual exclusion and synchronization. 250 Library extension for executors, futures, and actors are built on these basic mechanisms. 251 The runtime provides significant programmer simplification and safety by eliminating spurious wakeup and reducing monitor barging. 252 The runtime also ensures multiple monitors can be safely acquired \emph{simultaneously} (deadlock free), and this feature is fully integrated with all monitor synchronization mechanisms. 253 All language features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers. 252 254 Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming-languages. 253 255 }% … … 264 266 \section{Introduction} 265 267 266 This paper discusses the design of language-level control-flow and concurrency/parallelism extensions in \CFAand its runtime.268 This paper discusses the design philosophy and implementation of advanced language-level control-flow and concurrent/parallel features in \CFA~\cite{Moss18} and its runtime. 267 269 \CFA is a modern, polymorphic, non-object-oriented\footnote{ 268 270 \CFA has features often associated with object-oriented programming languages, such as constructors, destructors, virtuals and simple inheritance. 269 271 However, functions \emph{cannot} be nested in structures, so there is no lexical binding between a structure and set of functions (member/method) implemented by an implicit \lstinline@this@ (receiver) parameter.}, 270 backwards-compatible extension of the C programming language ~\cite{Moss18}.272 backwards-compatible extension of the C programming language. 271 273 Within the \CFA framework, new control-flow features are created from scratch. 272 274 ISO \Celeven defines only a subset of the \CFA extensions, where the overlapping features are concurrency~\cite[\S~7.26]{C11}. … … 275 277 no high-level language concurrency features are defined. 276 278 Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-8 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach. 277 Finally, while the \Celeven standard does not state a concurrent threading-model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}.279 Finally, while the \Celeven standard does not state a threading model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}. 278 280 279 281 In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages. … … 281 283 Kernel threading was chosen, largely because of its simplicity and fit with the simpler operating systems and hardware architectures at the time, which gave it a performance advantage~\cite{Drepper03}. 282 284 Libraries like pthreads were developed for C, and the Solaris operating-system switched from user (JDK 1.1~\cite{JDK1.1}) to kernel threads. 283 As a result, languages like Java, Scala~\cite{Scala}, Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, and C\#~\cite{Csharp} adopt edthe 1:1 kernel-threading model, with a variety of presentation mechanisms.285 As a result, languages like Java, Scala~\cite{Scala}, Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, and C\#~\cite{Csharp} adopt the 1:1 kernel-threading model, with a variety of presentation mechanisms. 284 286 From 2000 onwards, languages like Go~\cite{Go}, Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, D~\cite{D}, and \uC~\cite{uC++,uC++book} have championed the M:N user-threading model, and many user-threading libraries have appeared~\cite{Qthreads,MPC,BoostThreads}, including putting green threads back into Java~\cite{Quasar}. 285 287 The main argument for user-level threading is that they are lighter weight than kernel threads (locking and context switching do not cross the kernel boundary), so there is less restriction on programming styles that encourage large numbers of threads performing smaller work-units to facilitate load balancing by the runtime~\cite{Verch12}. … … 287 289 Finally, performant user-threading implementations (both time and space) are largely competitive with direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety. 288 290 289 A further effort over the past decade is the development of language memory-models to deal with the conflict between certain language features and compiler/hardware optimizations. 290 This issue can be rephrased as: some language features are pervasive (language and runtime) and cannot be safely added via a library to prevent invalidation by sequential optimizations~\cite{Buhr95a,Boehm05}. 291 The consequence is that a language must be cognizant of these features and provide sufficient tools to program around any safety issues. 292 For example, C created the @volatile@ qualifier to provide correct execution for @setjmp@/@logjmp@ (concurrency came later). 293 The common solution is to provide a handful of complex qualifiers and functions (e.g., @volatile@ and atomics) allowing programmers to write consistent/race-free programs, often in the sequentially-consistent memory-model~\cite{Boehm12}. 294 295 While having a sufficient memory-model allows sound libraries to be constructed, writing these libraries can quickly become awkward and error prone, and using these low-level libraries has the same issues. 296 Essentially, using low-level explicit locks is the concurrent equivalent of assembler programming. 297 Just as most assembler programming is replaced with high-level programming, explicit locks can be replaced with high-level concurrency in a programming language. 298 Then the goal is for the compiler to check for correct usage and follow any complex coding conventions implicitly. 299 The drawback is that language constructs may preclude certain specialized techniques, therefore introducing inefficiency or inhibiting concurrency. 300 For most concurrent programs, these drawbacks are insignificant in comparison to the speed of composition, and subsequent reliability and maintainability of the high-level concurrent program. 301 (The same is true for high-level programming versus assembler programming.) 302 Only very rarely should it be necessary to drop down to races and/or explicit locks to apply a specialized technique to achieve maximum speed or concurrency. 303 As stated, this observation applies to non-concurrent forms of complex control-flow, like exception handling and coroutines. 304 305 Adapting the programming language to these features also allows matching the control-flow model with the programming-language style, versus adopting one general (sound) library/paradigm. 291 A further effort over the past two decades is the development of language memory-models to deal with the conflict between language features and compiler/hardware optimizations, i.e., some language features are unsafe in the presence of aggressive sequential optimizations~\cite{Buhr95a,Boehm05}. 292 The consequence is that a language must provide sufficient tools to program around safety issues, as inline and library code is all sequential to the compiler. 293 One solution is low-level qualifiers and functions (e.g., @volatile@ and atomics) allowing \emph{programmers} to explicitly write safe (race-free~\cite{Boehm12}) programs. 294 A safer solution is high-level language constructs so the \emph{compiler} knows the optimization boundaries, and hence, provides implicit safety. 295 This problem is best know with respect to concurrency, but applies to other complex control-flow, like exceptions\footnote{ 296 \CFA exception handling will be presented in a separate paper. 297 The key feature that dovetails with this paper is non-local exceptions allowing exceptions to be raised across stacks, with synchronous exceptions raised among coroutines and asynchronous exceptions raised among threads, similar to that in \uC~\cite[\S~5]{uC++} 298 } and coroutines. 299 Finally, solutions in the language allows matching constructs with language paradigm, i.e., imperative and functional languages have different presentations of the same concept. 300 301 Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary. 302 Two concurrency violations of this philosophy are \emph{spurious wakeup} and \emph{barging}, i.e., random wakeup~\cite[\S~8]{Buhr05a} and signalling-as-hints~\cite[\S~8]{Buhr05a}, where one begats the other. 303 If you believe spurious wakeup is a foundational concurrency property, than unblocking (signalling) a thread is always a hint. 304 If you \emph{do not} believe spurious wakeup is foundational, than signalling-as-hints is a performance decision. 305 Most importantly, removing spurious wakeup and signals-as-hints makes concurrent programming significantly safer because it removes local non-determinism. 306 Clawing back performance where the local non-determinism is unimportant, should be an option not the default. 307 308 \begin{comment} 306 309 For example, it is possible to provide exceptions, coroutines, monitors, and tasks as specialized types in an object-oriented language, integrating these constructs to allow leveraging the type-system (static type-checking) and all other object-oriented capabilities~\cite{uC++}. 307 310 It is also possible to leverage call/return for blocking communication via new control structures, versus switching to alternative communication paradigms, like channels or message passing. … … 321 324 Hence, rewriting and retraining costs for these languages, even \CC, are prohibitive for companies with a large C software-base. 322 325 \CFA with its orthogonal feature-set, its high-performance runtime, and direct access to all existing C libraries circumvents these problems. 323 324 We present comparative examples so the reader can judge if the \CFA control-flow extensions are equivalent or better than those in or proposed for \Celeven, \CC and other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms. 325 The detailed contributions of this work are: 326 \end{comment} 327 328 \CFA embraces user-level threading, language extensions for advanced control-flow, and safety as the default. 329 We present comparative examples so the reader can judge if the \CFA control-flow extensions are better and safer than those in or proposed for \Celeven, \CC and other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms. 330 The main contributions of this work are: 326 331 \begin{itemize} 327 332 \item 328 allowing multiple monitors to be safely acquired \emph{simultaneously} (deadlock free), while seamlessly integrating this capability with all monitor synchronization mechanisms.333 expressive language-level coroutines and user-level threading, which respect the expectations of C programmers. 329 334 \item 330 all control-flow features respect the expectations of C programmers, with statically type-safe interfaces that integrate with the \CFA polymorphic type-system and other language features.335 monitor synchronization without barging. 331 336 \item 332 experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming-languages. 337 safely acquiring multiple monitors \emph{simultaneously} (deadlock free), while seamlessly integrating this capability with all monitor synchronization mechanisms. 338 \item 339 providing statically type-safe interfaces that integrate with the \CFA polymorphic type-system and other language features. 340 \item 341 library extensions for executors, futures, and actors built on the basic mechanisms. 342 \item 343 a runtime system with no spurious wakeup. 344 \item 345 experimental results showing comparable performance of the new features with similar mechanisms in other concurrent programming-languages. 333 346 \end{itemize} 334 347 -
doc/user/user.tex
r63364d8 rb038fe4 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sun Apr 14 11:02:34201914 %% Update Count : 34 4313 %% Last Modified On : Sun May 5 18:24:50 2019 14 %% Update Count : 3489 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 193 193 \end{center} 194 194 While the \CFA I/O looks similar to the \Index*[C++]{\CC{}} output style, there are important differences, such as automatic spacing between variables as in \Index*{Python} (see~\VRef{s:IOLibrary}). 195 195 196 196 197 \subsection{Background} … … 431 432 \end{cfa} 432 433 which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}. 434 435 The \CFA translator has multiple steps. 436 The following flags control how the tranlator works, the stages run, and printing within a stage. 437 The majority of these flags are used by \CFA developers, but some are occasionally useful to programmers. 438 \begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt] 439 \item 440 \Indexc{-h}\index{translator option!-h@{©-h©}}, \Indexc{--help}\index{translator option!--help@{©--help©}} \, print help message 441 \item 442 \Indexc{-l}\index{translator option!-l@{©-l©}}, \Indexc{--libcfa}\index{translator option!--libcfa@{©--libcfa©}} \, generate libcfa.c 443 \item 444 \Indexc{-L}\index{translator option!-L@{©-L©}}, \Indexc{--linemarks}\index{translator option!--linemarks@{©--linemarks©}} \, generate line marks 445 \item 446 \Indexc{-m}\index{translator option!-m@{©-m©}}, \Indexc{--no-main}\index{translator option!--no-main@{©--no-main©}} \, do not replace main 447 \item 448 \Indexc{-N}\index{translator option!-N@{©-N©}}, \Indexc{--no-linemarks}\index{translator option!--no-linemarks@{©--no-linemarks©}} \, do not generate line marks 449 \item 450 \Indexc{-n}\index{translator option!-n@{©-n©}}, \Indexc{--no-prelude}\index{translator option!--no-prelude@{©--no-prelude©}} \, do not read prelude 451 \item 452 \Indexc{-p}\index{translator option!-p@{©-p©}}, \Indexc{--prototypes}\index{translator option!--prototypes@{©--prototypes©}} \, generate prototypes for prelude functions 453 \item 454 \Indexc{-P}\index{translator option!-P@{©-P©}}, \Indexc{--print}\index{translator option!--print@{©--print©}} \, one of: 455 \begin{description}[topsep=0pt,itemsep=0pt,parsep=0pt] 456 \item 457 \Indexc{altexpr}\index{translator option!-P@{©-P©}!©altexpr©}\index{translator option!--print@{©-print©}!©altexpr©} \, alternatives for expressions 458 \item 459 \Indexc{ascodegen}\index{translator option!-P@{©-P©}!©ascodegen©}\index{translator option!--print@{©-print©}!©ascodegen©} \, as codegen rather than AST 460 \item 461 \Indexc{ast}\index{translator option!-P@{©-P©}!©ast©}\index{translator option!--print@{©-print©}!©ast©} \, AST after parsing 462 \item 463 \Indexc{astdecl}\index{translator option!-P@{©-P©}!©astdecl©}\index{translator option!--print@{©-print©}!©astdecl©} \, AST after declaration validation pass 464 \item 465 \Indexc{asterr}\index{translator option!-P@{©-P©}!©asterr©}\index{translator option!--print@{©-print©}!©asterr©} \, AST on error 466 \item 467 \Indexc{astexpr}\index{translator option!-P@{©-P©}!©astexpr©}\index{translator option!--print@{©-print©}!©altexpr©} \, AST after expression analysis 468 \item 469 \Indexc{astgen}\index{translator option!-P@{©-P©}!©astgen©}\index{translator option!--print@{©-print©}!©astgen©} \, AST after instantiate generics 470 \item 471 \Indexc{box}\index{translator option!-P@{©-P©}!©box©}\index{translator option!--print@{©-print©}!©box©} \, before box step 472 \item 473 \Indexc{ctordtor}\index{translator option!-P@{©-P©}!©ctordtor©}\index{translator option!--print@{©-print©}!©ctordtor©} \, after ctor/dtor are replaced 474 \item 475 \Indexc{codegen}\index{translator option!-P@{©-P©}!©codegen©}\index{translator option!--print@{©-print©}!©codegen©} \, before code generation 476 \item 477 \Indexc{declstats}\index{translator option!-P@{©-P©}!©declstats©}\index{translator option!--print@{©-print©}!©declstats©} \, code property statistics 478 \item 479 \Indexc{parse}\index{translator option!-P@{©-P©}!©parse©}\index{translator option!--print@{©-print©}!©parse©} \, yacc (parsing) debug information 480 \item 481 \Indexc{pretty}\index{translator option!-P@{©-P©}!©pretty©}\index{translator option!--print@{©-print©}!©pretty©} \, prettyprint for ascodegen flag 482 \item 483 \Indexc{resolver}\index{translator option!-P@{©-P©}!©resolver©}\index{translator option!--print@{©-print©}!©resolver©} \, before resolver step 484 \item 485 \Indexc{rproto}\index{translator option!-P@{©-P©}!©rproto©}\index{translator option!--print@{©-print©}!©rproto©} \, resolver-proto instance 486 \item 487 \Indexc{rsteps}\index{translator option!-P@{©-P©}!©rsteps©}\index{translator option!--print@{©-print©}!©rsteps©} \, resolver steps 488 \item 489 \Indexc{symevt}\index{translator option!-P@{©-P©}!©symevt©}\index{translator option!--print@{©-print©}!©symevt©} \, symbol table events 490 \item 491 \Indexc{tree}\index{translator option!-P@{©-P©}!©tree©}\index{translator option!--print@{©-print©}!©tree©} \, parse tree 492 \item 493 \Indexc{tuple}\index{translator option!-P@{©-P©}!©tuple©}\index{translator option!--print@{©-print©}!©tuple©} \, after tuple expansion 494 \end{description} 495 \item 496 \Indexc{--prelude-dir} <directory> \, prelude directory for debug/nodebug 497 \item 498 \Indexc{-S}\index{translator option!-S@{©-S©}!©counters,heap,time,all,none©}, \Indexc{--statistics}\index{translator option!--statistics@{©--statistics©}!©counters,heap,time,all,none©} <option-list> \, enable profiling information: 499 \begin{description}[topsep=0pt,itemsep=0pt,parsep=0pt] 500 \item 501 \Indexc{counters,heap,time,all,none} 502 \end{description} 503 \item 504 \Indexc{-t}\index{translator option!-t@{©-t©}}, \Indexc{--tree}\index{translator option!--tree@{©--tree©}} build in tree 505 \end{description} 433 506 434 507 -
libcfa/src/iostream.hfa
r63364d8 rb038fe4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Apr 20 12:04:07201913 // Update Count : 2 2612 // Last Modified On : Fri May 3 22:55:04 2019 13 // Update Count : 230 14 14 // 15 15 … … 48 48 void close( ostype & os ); 49 49 ostype & write( ostype &, const char *, size_t ); 50 int fmt( ostype &, const char format[], ... ) ;50 int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) )); 51 51 }; // ostream 52 52 … … 158 158 istype & read( istype &, char *, size_t ); 159 159 istype & ungetc( istype &, char ); 160 int fmt( istype &, const char format[], ... ) ;160 int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); 161 161 }; // istream 162 162 -
src/BasicTypes-gen.cc
r63364d8 rb038fe4 1 #include <algorithm> 1 2 #include <queue> 2 3 #include <iostream> … … 340 341 } // for 341 342 code << "\t}; // costMatrix" << endl; 343 344 // maximum conversion cost from int 345 code << "\tstatic const int maxIntCost = " << *max_element(costMatrix[SignedInt], costMatrix[SignedInt] + NUMBER_OF_BASIC_TYPES) << ";" << endl; 342 346 code << "\t"; // indentation for end marker 343 347 344 348 if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", ConversionCost ); 345 349 if ( (end = str.find( STARTMK, start + 1 )) == string::npos ) Abort( "start", ConversionCost ); -
src/CodeGen/CodeGenerator.cc
r63364d8 rb038fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat May 5 09:08:32 201813 // Update Count : 49 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 2 10:47:00 2019 13 // Update Count : 497 14 14 // 15 15 #include "CodeGenerator.h" … … 83 83 void CodeGenerator::updateLocation( CodeLocation const & to ) { 84 84 // skip if linemarks shouldn't appear or if codelocation is unset 85 if ( ! lineMarks || to.isUnset() ) return;85 if ( !options.lineMarks || to.isUnset() ) return; 86 86 87 87 if ( currentLocation.followedBy( to, 0 ) ) { … … 116 116 } 117 117 118 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks, bool printExprTypes ) : indent( CodeGenerator::tabsize ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ), printExprTypes( printExprTypes ), endl( *this ) {} 118 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks, bool printExprTypes ) : indent( CodeGenerator::tabsize ), output( os ), printLabels( *this ), options( pretty, genC, lineMarks, printExprTypes ), endl( *this ) {} 119 CodeGenerator::CodeGenerator( std::ostream & os, const Options &options ) : indent( CodeGenerator::tabsize ), output( os ), printLabels( *this ), options(options), endl( *this ) {} 119 120 120 121 string CodeGenerator::mangleName( DeclarationWithType * decl ) { 121 122 // GCC builtins should always be printed unmangled 122 if ( pretty || decl->linkage.is_gcc_builtin ) return decl->name;123 if ( options.pretty || decl->linkage.is_gcc_builtin ) return decl->name; 123 124 if ( decl->mangleName != "" ) { 124 125 // need to incorporate scope level in order to differentiate names for destructors … … 164 165 previsit( (BaseSyntaxNode *)node ); 165 166 GuardAction( [this, node](){ 166 if ( printExprTypes && node->result ) {167 output << " /* " << genType( node->result, "", pretty, genC) << " */ ";167 if ( options.printExprTypes && node->result ) { 168 output << " /* " << genType( node->result, "", options ) << " */ "; 168 169 } 169 170 } ); … … 173 174 void CodeGenerator::postvisit( FunctionDecl * functionDecl ) { 174 175 // deleted decls should never be used, so don't print them 175 if ( functionDecl->isDeleted && genC ) return;176 if ( functionDecl->isDeleted && options.genC ) return; 176 177 extension( functionDecl ); 177 178 genAttributes( functionDecl->get_attributes() ); … … 180 181 functionDecl->get_funcSpec().print( output ); 181 182 182 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty, genC ); 183 Options subOptions = options; 184 subOptions.anonymousUnused = functionDecl->has_body(); 185 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), subOptions ); 183 186 184 187 asmName( functionDecl ); … … 194 197 void CodeGenerator::postvisit( ObjectDecl * objectDecl ) { 195 198 // deleted decls should never be used, so don't print them 196 if ( objectDecl->isDeleted && genC ) return;197 if (objectDecl->get_name().empty() && genC ) {199 if ( objectDecl->isDeleted && options.genC ) return; 200 if (objectDecl->get_name().empty() && options.genC ) { 198 201 // only generate an anonymous name when generating C code, otherwise it clutters the output too much 199 202 static UniqueName name = { "__anonymous_object" }; 200 203 objectDecl->set_name( name.newName() ); 204 // Stops unused parameter warnings. 205 if ( options.anonymousUnused ) { 206 objectDecl->attributes.push_back( new Attribute( "unused" ) ); 207 } 201 208 } 202 209 … … 205 212 206 213 handleStorageClass( objectDecl ); 207 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty,genC );214 output << genType( objectDecl->get_type(), mangleName( objectDecl ), options.pretty, options.genC ); 208 215 209 216 asmName( objectDecl ); … … 224 231 225 232 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) { 226 if( ! aggDecl->parameters.empty() && ! genC ) {233 if( ! aggDecl->parameters.empty() && ! options.genC ) { 227 234 // assertf( ! genC, "Aggregate type parameters should not reach code generation." ); 228 235 output << "forall("; … … 294 301 295 302 void CodeGenerator::postvisit( TraitDecl * traitDecl ) { 296 assertf( ! genC, "TraitDecls should not reach code generation." );303 assertf( ! options.genC, "TraitDecls should not reach code generation." ); 297 304 extension( traitDecl ); 298 305 handleAggregate( traitDecl, "trait " ); … … 300 307 301 308 void CodeGenerator::postvisit( TypedefDecl * typeDecl ) { 302 assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );309 assertf( ! options.genC, "Typedefs are removed and substituted in earlier passes." ); 303 310 output << "typedef "; 304 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC) << endl;311 output << genType( typeDecl->get_base(), typeDecl->get_name(), options ) << endl; 305 312 } 306 313 307 314 void CodeGenerator::postvisit( TypeDecl * typeDecl ) { 308 assertf( ! genC, "TypeDecls should not reach code generation." );315 assertf( ! options.genC, "TypeDecls should not reach code generation." ); 309 316 output << typeDecl->genTypeString() << " " << typeDecl->name; 310 317 if ( typeDecl->sized ) { … … 371 378 372 379 void CodeGenerator::postvisit( ConstructorInit * init ){ 373 assertf( ! genC, "ConstructorInit nodes should not reach code generation." );380 assertf( ! options.genC, "ConstructorInit nodes should not reach code generation." ); 374 381 // pseudo-output for constructor/destructor pairs 375 382 output << "<ctorinit>{" << endl << ++indent << "ctor: "; … … 507 514 } else { 508 515 // no constructors with 0 or more than 2 parameters 509 assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );516 assertf( ! options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." ); 510 517 output << "("; 511 518 (*arg++)->accept( *visitor ); … … 604 611 // an lvalue cast, this has been taken out. 605 612 output << "("; 606 output << genType( castExpr->get_result(), "", pretty, genC);613 output << genType( castExpr->get_result(), "", options ); 607 614 output << ")"; 608 615 } // if … … 612 619 613 620 void CodeGenerator::postvisit( KeywordCastExpr * castExpr ) { 614 assertf( ! genC, "KeywordCast should not reach code generation." );621 assertf( ! options.genC, "KeywordCast should not reach code generation." ); 615 622 extension( castExpr ); 616 623 output << "((" << castExpr->targetString() << " &)"; … … 620 627 621 628 void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) { 622 assertf( ! genC, "VirtualCastExpr should not reach code generation." );629 assertf( ! options.genC, "VirtualCastExpr should not reach code generation." ); 623 630 extension( castExpr ); 624 631 output << "(virtual "; … … 628 635 629 636 void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) { 630 assertf( ! genC, "UntypedMemberExpr should not reach code generation." );637 assertf( ! options.genC, "UntypedMemberExpr should not reach code generation." ); 631 638 extension( memberExpr ); 632 639 memberExpr->get_aggregate()->accept( *visitor ); … … 661 668 output << "sizeof("; 662 669 if ( sizeofExpr->get_isType() ) { 663 output << genType( sizeofExpr->get_type(), "", pretty, genC);670 output << genType( sizeofExpr->get_type(), "", options ); 664 671 } else { 665 672 sizeofExpr->get_expr()->accept( *visitor ); … … 673 680 output << "__alignof__("; 674 681 if ( alignofExpr->get_isType() ) { 675 output << genType( alignofExpr->get_type(), "", pretty, genC);682 output << genType( alignofExpr->get_type(), "", options ); 676 683 } else { 677 684 alignofExpr->get_expr()->accept( *visitor ); … … 681 688 682 689 void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) { 683 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );690 assertf( ! options.genC, "UntypedOffsetofExpr should not reach code generation." ); 684 691 output << "offsetof("; 685 output << genType( offsetofExpr->get_type(), "", pretty, genC);692 output << genType( offsetofExpr->get_type(), "", options ); 686 693 output << ", " << offsetofExpr->get_member(); 687 694 output << ")"; … … 691 698 // use GCC builtin 692 699 output << "__builtin_offsetof("; 693 output << genType( offsetofExpr->get_type(), "", pretty, genC);700 output << genType( offsetofExpr->get_type(), "", options ); 694 701 output << ", " << mangleName( offsetofExpr->get_member() ); 695 702 output << ")"; … … 697 704 698 705 void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) { 699 assertf( ! genC, "OffsetPackExpr should not reach code generation." );700 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC) << ")";706 assertf( ! options.genC, "OffsetPackExpr should not reach code generation." ); 707 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", options ) << ")"; 701 708 } 702 709 … … 728 735 extension( commaExpr ); 729 736 output << "("; 730 if ( genC ) {737 if ( options.genC ) { 731 738 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings. 732 739 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) ); … … 739 746 740 747 void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) { 741 assertf( ! genC, "TupleAssignExpr should not reach code generation." );748 assertf( ! options.genC, "TupleAssignExpr should not reach code generation." ); 742 749 tupleExpr->stmtExpr->accept( *visitor ); 743 750 } 744 751 745 752 void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) { 746 assertf( ! genC, "UntypedTupleExpr should not reach code generation." );753 assertf( ! options.genC, "UntypedTupleExpr should not reach code generation." ); 747 754 extension( tupleExpr ); 748 755 output << "["; … … 752 759 753 760 void CodeGenerator::postvisit( TupleExpr * tupleExpr ) { 754 assertf( ! genC, "TupleExpr should not reach code generation." );761 assertf( ! options.genC, "TupleExpr should not reach code generation." ); 755 762 extension( tupleExpr ); 756 763 output << "["; … … 760 767 761 768 void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) { 762 assertf( ! genC, "TupleIndexExpr should not reach code generation." );769 assertf( ! options.genC, "TupleIndexExpr should not reach code generation." ); 763 770 extension( tupleExpr ); 764 771 tupleExpr->get_tuple()->accept( *visitor ); … … 767 774 768 775 void CodeGenerator::postvisit( TypeExpr * typeExpr ) { 769 // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;770 // assertf( ! genC, "TypeExpr should not reach code generation." );771 if ( ! genC ) {772 output << genType( typeExpr->get_type(), "", pretty, genC);776 // if ( options.genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl; 777 // assertf( ! options.genC, "TypeExpr should not reach code generation." ); 778 if ( ! options.genC ) { 779 output << genType( typeExpr->get_type(), "", options ); 773 780 } 774 781 } … … 788 795 void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) { 789 796 assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) ); 790 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC) << ")";797 output << "(" << genType( compLitExpr->get_result(), "", options ) << ")"; 791 798 compLitExpr->get_initializer()->accept( *visitor ); 792 799 } 793 800 794 801 void CodeGenerator::postvisit( UniqueExpr * unqExpr ) { 795 assertf( ! genC, "Unique expressions should not reach code generation." );802 assertf( ! options.genC, "Unique expressions should not reach code generation." ); 796 803 output << "unq<" << unqExpr->get_id() << ">{ "; 797 804 unqExpr->get_expr()->accept( *visitor ); … … 829 836 830 837 void CodeGenerator::postvisit( ConstructorExpr * expr ) { 831 assertf( ! genC, "Unique expressions should not reach code generation." );838 assertf( ! options.genC, "Unique expressions should not reach code generation." ); 832 839 expr->callExpr->accept( *visitor ); 833 840 } 834 841 835 842 void CodeGenerator::postvisit( DeletedExpr * expr ) { 836 assertf( ! genC, "Deleted expressions should not reach code generation." );843 assertf( ! options.genC, "Deleted expressions should not reach code generation." ); 837 844 expr->expr->accept( *visitor ); 838 845 } 839 846 840 847 void CodeGenerator::postvisit( DefaultArgExpr * arg ) { 841 assertf( ! genC, "Default argument expressions should not reach code generation." );848 assertf( ! options.genC, "Default argument expressions should not reach code generation." ); 842 849 arg->expr->accept( *visitor ); 843 850 } 844 851 845 852 void CodeGenerator::postvisit( GenericExpr * expr ) { 846 assertf( ! genC, "C11 _Generic expressions should not reach code generation." );853 assertf( ! options.genC, "C11 _Generic expressions should not reach code generation." ); 847 854 output << "_Generic("; 848 855 expr->control->accept( *visitor ); … … 854 861 output << "default: "; 855 862 } else { 856 output << genType( assoc.type, "", pretty, genC) << ": ";863 output << genType( assoc.type, "", options ) << ": "; 857 864 } 858 865 assoc.expr->accept( *visitor ); … … 889 896 void CodeGenerator::postvisit( ExprStmt * exprStmt ) { 890 897 assert( exprStmt ); 891 if ( genC ) {898 if ( options.genC ) { 892 899 // cast the top-level expression to void to reduce gcc warnings. 893 900 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) ); … … 999 1006 case BranchStmt::FallThrough: 1000 1007 case BranchStmt::FallThroughDefault: 1001 assertf( ! genC, "fallthru should not reach code generation." );1008 assertf( ! options.genC, "fallthru should not reach code generation." ); 1002 1009 output << "fallthru"; 1003 1010 break; 1004 1011 } // switch 1005 1012 // print branch target for labelled break/continue/fallthru in debug mode 1006 if ( ! genC && branchStmt->get_type() != BranchStmt::Goto ) {1013 if ( ! options.genC && branchStmt->get_type() != BranchStmt::Goto ) { 1007 1014 if ( ! branchStmt->get_target().empty() ) { 1008 1015 output << " " << branchStmt->get_target(); … … 1021 1028 1022 1029 void CodeGenerator::postvisit( ThrowStmt * throwStmt ) { 1023 assertf( ! genC, "Throw statements should not reach code generation." );1030 assertf( ! options.genC, "Throw statements should not reach code generation." ); 1024 1031 1025 1032 output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ? … … 1036 1043 } 1037 1044 void CodeGenerator::postvisit( CatchStmt * stmt ) { 1038 assertf( ! genC, "Catch statements should not reach code generation." );1045 assertf( ! options.genC, "Catch statements should not reach code generation." ); 1039 1046 1040 1047 output << ((stmt->get_kind() == CatchStmt::Terminate) ? … … 1053 1060 1054 1061 void CodeGenerator::postvisit( WaitForStmt * stmt ) { 1055 assertf( ! genC, "Waitfor statements should not reach code generation." );1062 assertf( ! options.genC, "Waitfor statements should not reach code generation." ); 1056 1063 1057 1064 bool first = true; … … 1099 1106 1100 1107 void CodeGenerator::postvisit( WithStmt * with ) { 1101 if ( ! genC ) {1108 if ( ! options.genC ) { 1102 1109 output << "with ( "; 1103 1110 genCommaList( with->exprs.begin(), with->exprs.end() ); … … 1165 1172 1166 1173 void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) { 1167 assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );1174 assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." ); 1168 1175 stmt->callStmt->accept( *visitor ); 1169 1176 } -
src/CodeGen/CodeGenerator.h
r63364d8 rb038fe4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Aug 18 15:40:00 201713 // Update Count : 5 612 // Last Modified On : Tue Apr 30 12:01:00 2019 13 // Update Count : 57 14 14 // 15 15 … … 20 20 #include <string> // for string 21 21 22 #include "CodeGen/Options.h" // for Options 22 23 #include "Common/Indenter.h" // for Indenter 23 24 #include "Common/PassVisitor.h" // for PassVisitor … … 31 32 32 33 CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false, bool printExprTypes = false ); 34 CodeGenerator( std::ostream &os, const Options &options ); 33 35 34 36 //*** Turn off visit_children for all nodes … … 144 146 std::ostream & output; 145 147 LabelPrinter printLabels; 146 bool pretty = false; // pretty print 147 bool genC = false; // true if output has to be C code 148 bool lineMarks = false; 149 bool printExprTypes = false; 148 Options options; 150 149 public: 151 150 LineEnder endl; -
src/CodeGen/GenType.cc
r63364d8 rb038fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Mar 17 09:02:28 201713 // Update Count : 2 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed May 1 15:24:00 2019 13 // Update Count : 23 14 14 // 15 15 #include "GenType.h" … … 28 28 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting { 29 29 std::string typeString; 30 GenType( const std::string &typeString, bool pretty, bool genC, bool lineMarks );30 GenType( const std::string &typeString, const Options &options ); 31 31 32 32 void previsit( BaseSyntaxNode * ); … … 57 57 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 58 58 59 bool pretty = false; // pretty print 60 bool genC = false; // generating C code? 61 bool lineMarks = false; // lineMarks on for CodeGenerator? 59 Options options; 62 60 }; 63 61 64 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {65 PassVisitor<GenType> gt( baseString, pretty, genC, lineMarks );62 std::string genType( Type *type, const std::string &baseString, const Options &options ) { 63 PassVisitor<GenType> gt( baseString, options ); 66 64 std::ostringstream os; 67 65 68 66 if ( ! type->get_attributes().empty() ) { 69 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );67 PassVisitor<CodeGenerator> cg( os, options ); 70 68 cg.pass.genAttributes( type->get_attributes() ); 71 69 } // if … … 75 73 } 76 74 77 std::string genPrettyType( Type * type, const std::string & baseString ) { 78 return genType( type, baseString, true, false ); 79 } 80 81 GenType::GenType( const std::string &typeString, bool pretty, bool genC, bool lineMarks ) : typeString( typeString ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ) {} 75 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) { 76 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) ); 77 } 78 79 std::string genPrettyType( Type * type, const std::string & baseString ) { 80 return genType( type, baseString, true, false ); 81 } 82 83 GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {} 82 84 83 85 // *** BaseSyntaxNode … … 133 135 } // if 134 136 if ( dimension != 0 ) { 135 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );137 PassVisitor<CodeGenerator> cg( os, options ); 136 138 dimension->accept( cg ); 137 139 } else if ( isVarLen ) { … … 167 169 void GenType::postvisit( ReferenceType * refType ) { 168 170 assert( refType->base != 0); 169 assertf( ! genC, "Reference types should not reach code generation." );171 assertf( ! options.genC, "Reference types should not reach code generation." ); 170 172 handleQualifiers( refType ); 171 173 typeString = "&" + typeString; … … 195 197 } // if 196 198 } else { 197 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );199 PassVisitor<CodeGenerator> cg( os, options ); 198 200 os << "(" ; 199 201 … … 215 217 216 218 // add forall 217 if( ! funcType->forall.empty() && ! genC ) {219 if( ! funcType->forall.empty() && ! options.genC ) { 218 220 // assertf( ! genC, "Aggregate type parameters should not reach code generation." ); 219 221 std::ostringstream os; 220 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );222 PassVisitor<CodeGenerator> cg( os, options ); 221 223 os << "forall("; 222 224 cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() ); … … 229 231 if ( ! refType->parameters.empty() ) { 230 232 std::ostringstream os; 231 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );233 PassVisitor<CodeGenerator> cg( os, options ); 232 234 os << "("; 233 235 cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() ); … … 240 242 void GenType::postvisit( StructInstType * structInst ) { 241 243 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString; 242 if ( genC ) typeString = "struct " + typeString;244 if ( options.genC ) typeString = "struct " + typeString; 243 245 handleQualifiers( structInst ); 244 246 } … … 246 248 void GenType::postvisit( UnionInstType * unionInst ) { 247 249 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString; 248 if ( genC ) typeString = "union " + typeString;250 if ( options.genC ) typeString = "union " + typeString; 249 251 handleQualifiers( unionInst ); 250 252 } … … 252 254 void GenType::postvisit( EnumInstType * enumInst ) { 253 255 typeString = enumInst->name + " " + typeString; 254 if ( genC ) typeString = "enum " + typeString;256 if ( options.genC ) typeString = "enum " + typeString; 255 257 handleQualifiers( enumInst ); 256 258 } … … 262 264 263 265 void GenType::postvisit( TupleType * tupleType ) { 264 assertf( ! genC, "Tuple types should not reach code generation." );266 assertf( ! options.genC, "Tuple types should not reach code generation." ); 265 267 unsigned int i = 0; 266 268 std::ostringstream os; … … 268 270 for ( Type * t : *tupleType ) { 269 271 i++; 270 os << genType( t, "", pretty, genC, lineMarks ) << (i == tupleType->size() ? "" : ", ");272 os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", "); 271 273 } 272 274 os << "] "; … … 281 283 void GenType::postvisit( ZeroType * zeroType ) { 282 284 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 283 typeString = ( pretty ? "zero_t " : "long int ") + typeString;285 typeString = (options.pretty ? "zero_t " : "long int ") + typeString; 284 286 handleQualifiers( zeroType ); 285 287 } … … 287 289 void GenType::postvisit( OneType * oneType ) { 288 290 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 289 typeString = ( pretty ? "one_t " : "long int ") + typeString;291 typeString = (options.pretty ? "one_t " : "long int ") + typeString; 290 292 handleQualifiers( oneType ); 291 293 } 292 294 293 295 void GenType::postvisit( GlobalScopeType * globalType ) { 294 assertf( ! genC, "Global scope type should not reach code generation." );296 assertf( ! options.genC, "Global scope type should not reach code generation." ); 295 297 handleQualifiers( globalType ); 296 298 } 297 299 298 300 void GenType::postvisit( TraitInstType * inst ) { 299 assertf( ! genC, "Trait types should not reach code generation." );301 assertf( ! options.genC, "Trait types should not reach code generation." ); 300 302 typeString = inst->name + " " + typeString; 301 303 handleQualifiers( inst ); … … 304 306 void GenType::postvisit( TypeofType * typeof ) { 305 307 std::ostringstream os; 306 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );308 PassVisitor<CodeGenerator> cg( os, options ); 307 309 os << "typeof("; 308 310 typeof->expr->accept( cg ); … … 313 315 314 316 void GenType::postvisit( QualifiedType * qualType ) { 315 assertf( ! genC, "Qualified types should not reach code generation." );316 std::ostringstream os; 317 os << genType( qualType->parent, "", pretty, genC, lineMarks ) << "." << genType( qualType->child, "", pretty, genC, lineMarks ) << typeString;317 assertf( ! options.genC, "Qualified types should not reach code generation." ); 318 std::ostringstream os; 319 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString; 318 320 typeString = os.str(); 319 321 handleQualifiers( qualType ); … … 333 335 typeString = "_Atomic " + typeString; 334 336 } // if 335 if ( type->get_lvalue() && ! genC ) {337 if ( type->get_lvalue() && ! options.genC ) { 336 338 // when not generating C code, print lvalue for debugging. 337 339 typeString = "lvalue " + typeString; -
src/CodeGen/GenType.h
r63364d8 rb038fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 21 22:17:23 201713 // Update Count : 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 30 11:47:00 2019 13 // Update Count : 3 14 14 // 15 15 … … 18 18 #include <string> // for string 19 19 20 #include "CodeGen/Options.h" // for Options 21 20 22 class Type; 21 23 22 24 namespace CodeGen { 25 std::string genType( Type *type, const std::string &baseString, const Options &options ); 23 26 std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false ); 24 27 std::string genPrettyType( Type * type, const std::string & baseString ); -
src/Common/Assert.cc
r63364d8 rb038fe4 39 39 } 40 40 41 void abort(const char *fmt, ... ) noexcept __attribute__((noreturn, format(printf, 1, 2))); 42 void abort(const char *fmt, ... ) noexcept { 43 va_list args; 44 va_start( args, fmt ); 45 vfprintf( stderr, fmt, args ); 46 va_end( args ); 47 fprintf( stderr, "\n" ); 48 abort(); 49 } 50 41 51 // Local Variables: // 42 52 // tab-width: 4 // -
src/Common/PassVisitor.h
r63364d8 rb038fe4 4 4 5 5 #include <stack> 6 #include <type_traits> 6 7 7 8 #include "Common/Stats.h" … … 301 302 302 303 303 TypeSubstitution ** get_env_ptr () { return env_impl( pass, 0); }304 auto get_env_ptr () -> decltype(env_impl( pass, 0)) { return env_impl( pass, 0); } 304 305 std::list< Statement* > * get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); } 305 306 std::list< Statement* > * get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); } … … 348 349 }; 349 350 351 class WithConstTypeSubstitution { 352 protected: 353 WithConstTypeSubstitution() = default; 354 ~WithConstTypeSubstitution() = default; 355 356 public: 357 const TypeSubstitution * env = nullptr; 358 }; 359 350 360 class WithStmtsToAdd { 351 361 protected: -
src/Common/PassVisitor.impl.h
r63364d8 rb038fe4 20 20 21 21 #define MUTATE_END( type, node ) \ 22 return call_postmutate< type * >( node ); \ 22 auto __return = call_postmutate< type * >( node ); \ 23 assert( __return ); \ 24 return __return; 23 25 24 26 … … 253 255 254 256 // don't want statements from outer CompoundStmts to be added to this CompoundStmt 255 ValueGuardPtr< TypeSubstitution * > oldEnv ( get_env_ptr() );257 ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type > oldEnv( get_env_ptr() ); 256 258 ValueGuardPtr< DeclList_t > oldBeforeDecls( get_beforeDecls() ); 257 259 ValueGuardPtr< DeclList_t > oldAfterDecls ( get_afterDecls () ); … … 1995 1997 1996 1998 // don't want statements from outer CompoundStmts to be added to this StmtExpr 1997 ValueGuardPtr< TypeSubstitution * > oldEnv( get_env_ptr() );1999 ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type > oldEnv( get_env_ptr() ); 1998 2000 ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() ); 1999 2001 ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () ); … … 2012 2014 2013 2015 // don't want statements from outer CompoundStmts to be added to this StmtExpr 2014 ValueGuardPtr< TypeSubstitution * > oldEnv( get_env_ptr() );2016 ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type > oldEnv( get_env_ptr() ); 2015 2017 ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() ); 2016 2018 ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () ); -
src/Common/PassVisitor.proto.h
r63364d8 rb038fe4 165 165 static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;} \ 166 166 167 FIELD_PTR( TypeSubstitution *, env )167 FIELD_PTR( const TypeSubstitution *, env ) 168 168 FIELD_PTR( std::list< Statement* >, stmtsToAddBefore ) 169 169 FIELD_PTR( std::list< Statement* >, stmtsToAddAfter ) … … 174 174 FIELD_PTR( PassVisitor<pass_type> * const, visitor ) 175 175 176 #undef FIELD_PTR 177 176 178 //--------------------------------------------------------- 177 179 // Indexer -
src/CompilationState.cc
r63364d8 rb038fe4 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Ju1 30 10:46:25 201813 // Update Count : 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri May 3 13:45:23 2019 13 // Update Count : 4 14 14 // 15 15 16 bool 16 int 17 17 astp = false, 18 18 bresolvep = false, … … 26 26 libcfap = false, 27 27 nopreludep = false, 28 noprotop= false,28 genproto = false, 29 29 nomainp = false, 30 30 parsep = false, -
src/CompilationState.h
r63364d8 rb038fe4 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Ju1 30 10:46:25 201813 // Update Count : 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri May 3 13:43:21 2019 13 // Update Count : 4 14 14 // 15 15 16 16 extern int yydebug; // set for -g flag (Grammar) 17 extern bool17 extern int 18 18 astp, 19 19 bresolvep, … … 27 27 libcfap, 28 28 nopreludep, 29 noprotop,29 genproto, 30 30 nomainp, 31 31 parsep, -
src/ControlStruct/ExceptTranslate.cc
r63364d8 rb038fe4 617 617 return create_terminate_rethrow( throwStmt ); 618 618 } else { 619 a ssertf(false,"Invalid throw in %s at %i\n",619 abort("Invalid throw in %s at %i\n", 620 620 throwStmt->location.filename.c_str(), 621 621 throwStmt->location.first_line); 622 return nullptr;623 622 } 624 623 } else { … … 628 627 return create_resume_rethrow( throwStmt ); 629 628 } else { 630 a ssertf(false,"Invalid throwResume in %s at %i\n",629 abort("Invalid throwResume in %s at %i\n", 631 630 throwStmt->location.filename.c_str(), 632 631 throwStmt->location.first_line); 633 return nullptr;634 632 } 635 633 } -
src/GenPoly/Box.cc
r63364d8 rb038fe4 76 76 77 77 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call 78 class Pass1 final : public BoxPass, public With TypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {78 class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting { 79 79 public: 80 80 Pass1(); … … 150 150 /// * Calculates polymorphic offsetof expressions from offset array 151 151 /// * Inserts dynamic calculation of polymorphic type layouts where needed 152 class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public With TypeSubstitution {152 class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithConstTypeSubstitution { 153 153 public: 154 154 PolyGenericCalculator(); … … 1764 1764 1765 1765 Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) { 1766 Type *ty = sizeofExpr->get_isType() ? 1766 Type *ty = sizeofExpr->get_isType() ? 1767 1767 sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result(); 1768 1768 1769 1769 Expression * gen = genSizeof( ty ); 1770 1770 if ( gen ) { -
src/GenPoly/GenPoly.cc
r63364d8 rb038fe4 440 440 } 441 441 442 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {442 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) { 443 443 // is parameter is not polymorphic, don't need to box 444 444 if ( ! isPolyType( param, exprTyVars ) ) return false; … … 450 450 } 451 451 452 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {452 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) { 453 453 FunctionType * function = getFunctionType( appExpr->function->result ); 454 454 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() ); -
src/GenPoly/GenPoly.h
r63364d8 rb038fe4 81 81 82 82 /// true if arg requires boxing given exprTyVars 83 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );83 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ); 84 84 85 85 /// true if arg requires boxing in the call to appExpr 86 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );86 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ); 87 87 88 88 /// Adds the type variable `tyVar` to `tyVarMap` -
src/GenPoly/InstantiateGeneric.cc
r63364d8 rb038fe4 168 168 169 169 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately 170 struct GenericInstantiator final : public With TypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {170 struct GenericInstantiator final : public WithConstTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards { 171 171 /// Map of (generic type, parameter list) pairs to concrete type instantiations 172 172 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; -
src/GenPoly/Specialize.cc
r63364d8 rb038fe4 42 42 43 43 namespace GenPoly { 44 struct Specialize final : public With TypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {44 struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> { 45 45 Expression * postmutate( ApplicationExpr *applicationExpr ); 46 46 Expression * postmutate( CastExpr *castExpr ); … … 54 54 55 55 /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type. 56 bool needsPolySpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {56 bool needsPolySpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) { 57 57 if ( env ) { 58 58 using namespace ResolvExpr; … … 145 145 } 146 146 147 bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {147 bool needsSpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) { 148 148 return needsPolySpecialization( formalType, actualType, env ) || needsTupleSpecialization( formalType, actualType ); 149 149 } -
src/InitTweak/FixInit.cc
r63364d8 rb038fe4 72 72 }; 73 73 74 struct InsertImplicitCalls : public With TypeSubstitution {74 struct InsertImplicitCalls : public WithConstTypeSubstitution { 75 75 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which 76 76 /// function calls need their parameters to be copy constructed … … 187 187 }; 188 188 189 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public With TypeSubstitution {189 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithConstTypeSubstitution { 190 190 public: 191 191 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} -
src/ResolvExpr/ConversionCost.cc
r63364d8 rb038fe4 10 10 // Created On : Sun May 17 07:06:19 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 26 16:33:04201913 // Update Count : 2 412 // Last Modified On : Mon May 6 14:18:22 2019 13 // Update Count : 25 14 14 // 15 15 … … 249 249 /*_FLDXC*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, }, 250 250 }; // costMatrix 251 static const int maxIntCost = 15; 251 252 // GENERATED END 252 253 static_assert( … … 461 462 } // if 462 463 } else if ( dynamic_cast< PointerType* >( dest ) ) { 463 cost = Cost::safe; 464 cost = Cost::zero; 465 cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation 464 466 } // if 465 467 } -
src/ResolvExpr/RenameVars.cc
r63364d8 rb038fe4 10 10 // Created On : Sun May 17 12:05:18 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:36:32 201613 // Update Count : 512 // Last Modified On : Tue Apr 30 17:07:57 2019 13 // Update Count : 7 14 14 // 15 15 … … 39 39 private: 40 40 int level, resetCount; 41 std::list< std:: map< std::string, std::string > > mapStack;41 std::list< std::unordered_map< std::string, std::string > > mapStack; 42 42 }; 43 43 … … 55 55 namespace { 56 56 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 57 mapStack.push_front( std:: map< std::string, std::string >() );57 mapStack.push_front( std::unordered_map< std::string, std::string >() ); 58 58 } 59 59 … … 65 65 void RenameVars::previsit( TypeInstType * instType ) { 66 66 previsit( (Type *)instType ); 67 std:: map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );67 std::unordered_map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name ); 68 68 if ( i != mapStack.front().end() ) { 69 69 instType->name = i->second; -
src/ResolvExpr/TypeEnvironment.h
r63364d8 rb038fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:24:58 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Mon Jun 18 11:58:00 201813 // Update Count : 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 30 23:04:10 2019 13 // Update Count : 9 14 14 // 15 15 … … 18 18 #include <iostream> // for ostream 19 19 #include <list> // for list, list<>::iterator, list<>... 20 #include <map> // for map, map<>::value_compare 21 #include <set> // for set 20 #include <map> // for map, map<>::value_compare 21 #include <unordered_map> 22 #include <set> // for set 22 23 #include <string> // for string 23 24 #include <utility> // for move, swap … … 64 65 AssertionSetValue() : isUsed(false), resnSlot(0) {} 65 66 }; 66 typedef std::map< DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;67 typedef std:: map< std::string, TypeDecl::Data > OpenVarSet;67 typedef std::map< DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet; 68 typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet; 68 69 69 70 /// merges one set of open vars into another -
src/SynTree/Declaration.h
r63364d8 rb038fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun Sep 3 19:24:06 201713 // Update Count : 13 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 2 10:47:00 2019 13 // Update Count : 135 14 14 // 15 15 … … 19 19 #include <iosfwd> // for ostream 20 20 #include <list> // for list 21 #include <unordered_map> // for unordered_map 21 22 #include <string> // for string, operator+, allocator, to_string 22 23 … … 166 167 CompoundStmt *get_statements() const { return statements; } 167 168 void set_statements( CompoundStmt *newValue ) { statements = newValue; } 169 bool has_body() const { return NULL != statements; } 168 170 169 171 static FunctionDecl * newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements ); … … 334 336 virtual Declaration *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 335 337 private: 336 std:: map< std::string, long long int > enumValues;338 std::unordered_map< std::string, long long int > enumValues; 337 339 virtual std::string typeString() const override; 338 340 }; -
src/SynTree/TypeSubstitution.cc
r63364d8 rb038fe4 108 108 namespace { 109 109 struct EnvTrimmer { 110 TypeSubstitution * env, * newEnv; 111 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 110 const TypeSubstitution * env; 111 TypeSubstitution * newEnv; 112 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 112 113 void previsit( TypeDecl * tyDecl ) { 113 114 // transfer known bindings for seen type variables … … 120 121 121 122 /// reduce environment to just the parts that are referenced in a given expression 122 TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) {123 TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, const TypeSubstitution * env ) { 123 124 if ( env ) { 124 125 TypeSubstitution * newEnv = new TypeSubstitution(); -
src/SynTree/TypeSubstitution.h
r63364d8 rb038fe4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:52:24 201713 // Update Count : 312 // Last Modified On : Tue Apr 30 22:52:47 2019 13 // Update Count : 9 14 14 // 15 15 … … 19 19 #include <iosfwd> // for ostream 20 20 #include <list> // for list<>::iterator, _List_iterator 21 #include < map> // for _Rb_tree_iterator, map, map<>::val...22 #include < set> // for set21 #include <unordered_map> 22 #include <unordered_set> 23 23 #include <string> // for string, operator!= 24 24 #include <utility> // for pair … … 39 39 TypeSubstitution &operator=( const TypeSubstitution &other ); 40 40 41 template< typename SynTreeClass > int apply( SynTreeClass *&input ) ;42 template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) ;41 template< typename SynTreeClass > int apply( SynTreeClass *&input ) const; 42 template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const; 43 43 44 44 void add( std::string formalType, Type *actualType ); … … 56 56 57 57 /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr 58 static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );58 static TypeSubstitution * newFromExpr( Expression * expr, const TypeSubstitution * env ); 59 59 60 60 void normalize(); … … 78 78 friend class PassVisitor; 79 79 80 typedef std:: map< std::string, Type* > TypeEnvType;81 typedef std:: map< std::string, Expression* > VarEnvType;80 typedef std::unordered_map< std::string, Type * > TypeEnvType; 81 typedef std::unordered_map< std::string, Expression * > VarEnvType; 82 82 TypeEnvType typeEnv; 83 83 VarEnvType varEnv; … … 98 98 ActualIterator actualIt = actualBegin; 99 99 for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) { 100 if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) {101 if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) {100 if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) { 101 if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) { 102 102 if ( formal->get_name() != "" ) { 103 103 TypeEnvType::iterator i = typeEnv.find( formal->get_name() ); … … 130 130 // definitition must happen after PassVisitor is included so that WithGuards can be used 131 131 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> { 132 Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}132 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 133 133 134 134 Type * postmutate( TypeInstType * aggregateUseType ); … … 143 143 void premutate( UnionInstType * aggregateUseType ); 144 144 145 TypeSubstitution & sub;145 const TypeSubstitution & sub; 146 146 int subCount = 0; 147 147 bool freeOnly; 148 typedef std:: set< std::string > BoundVarsType;148 typedef std::unordered_set< std::string > BoundVarsType; 149 149 BoundVarsType boundVars; 150 150 }; 151 151 152 152 template< typename SynTreeClass > 153 int TypeSubstitution::apply( SynTreeClass *&input ) {153 int TypeSubstitution::apply( SynTreeClass *&input ) const { 154 154 assert( input ); 155 155 PassVisitor<Substituter> sub( *this, false ); … … 163 163 164 164 template< typename SynTreeClass > 165 int TypeSubstitution::applyFree( SynTreeClass *&input ) {165 int TypeSubstitution::applyFree( SynTreeClass *&input ) const { 166 166 assert( input ); 167 167 PassVisitor<Substituter> sub( *this, true ); -
src/Tuples/TupleExpansion.cc
r63364d8 rb038fe4 58 58 }; 59 59 60 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public With TypeSubstitution {60 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution { 61 61 Type * postmutate( TupleType * tupleType ); 62 62 -
src/include/cassert
r63364d8 rb038fe4 45 45 } 46 46 47 extern void abort(const char *fmt, ... ) noexcept __attribute__((noreturn, format(printf, 1, 2))); 47 48 // Local Variables: // 48 49 // tab-width: 4 // -
src/main.cc
r63364d8 rb038fe4 7 7 // main.cc -- 8 8 // 9 // Author : Richard C. Bilson9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 16 09:14:04201913 // Update Count : 5 0012 // Last Modified On : Fri May 3 16:10:52 2019 13 // Update Count : 599 14 14 // 15 15 … … 24 24 #include <fstream> // for ofstream 25 25 #include <iostream> // for operator<<, basic_ostream 26 #include <iomanip> 26 27 #include <iterator> // for back_inserter 27 28 #include <list> // for list … … 39 40 #include "Common/Stats.h" 40 41 #include "Common/PassVisitor.h" 42 // #include "AST/Pass.hpp" 41 43 #include "Common/SemanticError.h" // for SemanticError 42 44 #include "Common/UnimplementedError.h" // for UnimplementedError … … 65 67 using namespace std; 66 68 67 void NewPass(const char * const name) {68 Stats::Heap::newPass( name);69 static void NewPass( const char * const name ) { 70 Stats::Heap::newPass( name ); 69 71 using namespace Stats::Counters; 70 71 72 { 72 static auto group = build<CounterGroup>( "Pass Visitor");73 auto pass = build<CounterGroup>( name, group);73 static auto group = build<CounterGroup>( "Pass Visitor" ); 74 auto pass = build<CounterGroup>( name, group ); 74 75 pass_visitor_stats.depth = 0; 75 pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass);76 pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass);76 pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass ); 77 pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass ); 77 78 } 78 79 79 { 80 static auto group = build<CounterGroup>( "Syntax Node");81 auto pass = build<CounterGroup>( name, group);82 BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass);80 static auto group = build<CounterGroup>( "Syntax Node" ); 81 auto pass = build<CounterGroup>( name, group ); 82 BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass ); 83 83 } 84 84 } 85 85 86 #define PASS( name, pass) \86 #define PASS( name, pass ) \ 87 87 if ( errorp ) { cerr << name << endl; } \ 88 88 NewPass(name); \ … … 95 95 DeclarationNode * parseTree = nullptr; // program parse tree 96 96 97 st d::string PreludeDirector = "";97 static std::string PreludeDirector = ""; 98 98 99 99 static void parse_cmdline( int argc, char *argv[], const char *& filename ); … … 151 151 } // backtrace 152 152 153 void sigSegvBusHandler( int sig_num ) {153 static void sigSegvBusHandler( int sig_num ) { 154 154 cerr << "*CFA runtime error* program cfa-cpp terminated with " 155 155 << (sig_num == SIGSEGV ? "segment fault" : "bus error") … … 157 157 backtrace( 2 ); // skip first 2 stack frames 158 158 //_exit( EXIT_FAILURE ); 159 abort(); 159 abort(); // cause core dump for debugging 160 160 } // sigSegvBusHandler 161 161 162 void sigAbortHandler( __attribute__((unused)) int sig_num ) {162 static void sigAbortHandler( __attribute__((unused)) int sig_num ) { 163 163 backtrace( 6 ); // skip first 6 stack frames 164 164 signal( SIGABRT, SIG_DFL); // reset default signal handler … … 240 240 parseTree->printList( cout ); 241 241 delete parseTree; 242 return 0;242 return EXIT_SUCCESS; 243 243 } // if 244 244 … … 249 249 if ( astp ) { 250 250 dump( translationUnit ); 251 return 0;251 return EXIT_SUCCESS; 252 252 } // if 253 253 … … 262 262 if ( symtabp ) { 263 263 deleteAll( translationUnit ); 264 return 0;264 return EXIT_SUCCESS; 265 265 } // if 266 266 … … 268 268 PassVisitor<ResolvExpr::AlternativePrinter> printer( cout ); 269 269 acceptAll( translationUnit, printer ); 270 return 0;270 return EXIT_SUCCESS; 271 271 } // if 272 272 273 273 if ( validp ) { 274 274 dump( translationUnit ); 275 return 0;275 return EXIT_SUCCESS; 276 276 } // if 277 277 … … 288 288 CodeTools::printDeclStats( translationUnit ); 289 289 deleteAll( translationUnit ); 290 return 0;291 } 290 return EXIT_SUCCESS; 291 } // if 292 292 293 293 if ( bresolvep ) { 294 294 dump( translationUnit ); 295 return 0;295 return EXIT_SUCCESS; 296 296 } // if 297 297 … … 300 300 if ( resolvprotop ) { 301 301 CodeTools::dumpAsResolvProto( translationUnit ); 302 return 0;303 } 302 return EXIT_SUCCESS; 303 } // if 304 304 305 305 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 306 306 if ( exprp ) { 307 307 dump( translationUnit ); 308 return 0;308 return EXIT_SUCCESS; 309 309 } // if 310 310 … … 313 313 if ( ctorinitp ) { 314 314 dump ( translationUnit ); 315 return 0;315 return EXIT_SUCCESS; 316 316 } // if 317 317 … … 328 328 if ( tuplep ) { 329 329 dump( translationUnit ); 330 return 0;331 } 330 return EXIT_SUCCESS; 331 } // if 332 332 333 333 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM … … 336 336 if ( genericsp ) { 337 337 dump( translationUnit ); 338 return 0;339 } 338 return EXIT_SUCCESS; 339 } // if 340 340 PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) ); 341 341 … … 343 343 if ( bboxp ) { 344 344 dump( translationUnit ); 345 return 0;345 return EXIT_SUCCESS; 346 346 } // if 347 347 PASS( "Box", GenPoly::box( translationUnit ) ); … … 349 349 if ( bcodegenp ) { 350 350 dump( translationUnit ); 351 return 0;352 } 351 return EXIT_SUCCESS; 352 } // if 353 353 354 354 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 357 357 358 358 CodeTools::fillLocations( translationUnit ); 359 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true, linemarks ) );359 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) ); 360 360 361 361 CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() ); … … 373 373 delete output; 374 374 } // if 375 return 1;375 return EXIT_FAILURE; 376 376 } catch ( UnimplementedError &e ) { 377 377 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl; … … 379 379 delete output; 380 380 } // if 381 return 1;381 return EXIT_FAILURE; 382 382 } catch ( CompilerError &e ) { 383 383 cerr << "Compiler Error: " << e.get_what() << endl; … … 386 386 delete output; 387 387 } // if 388 return 1;389 } catch (...) {388 return EXIT_FAILURE; 389 } catch ( ... ) { 390 390 std::exception_ptr eptr = std::current_exception(); 391 391 try { 392 392 if (eptr) { 393 393 std::rethrow_exception(eptr); 394 } 395 else { 396 std::cerr << "Exception Uncaught and Unkown" << std::endl; 397 } 394 } else { 395 std::cerr << "Exception Uncaught and Unknown" << std::endl; 396 } // if 398 397 } catch(const std::exception& e) { 399 398 std::cerr << "Uncaught Exception \"" << e.what() << "\"\n"; 400 } 401 return 1;402 } // try399 } // try 400 return EXIT_FAILURE; 401 } // try 403 402 404 403 deleteAll( translationUnit ); 405 404 Stats::print(); 406 407 return 0; 405 return EXIT_SUCCESS; 408 406 } // main 409 407 410 void parse_cmdline( int argc, char * argv[], const char *& filename ) { 411 enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, ResolvProto, Stats, Symbol, Tree, TupleExpansion, Validate}; 412 413 static struct option long_opts[] = { 414 { "ast", no_argument, 0, Ast }, 415 { "before-box", no_argument, 0, Bbox }, 416 { "before-resolver", no_argument, 0, Bresolver }, 417 { "ctorinitfix", no_argument, 0, CtorInitFix }, 418 { "decl-stats", no_argument, 0, DeclStats }, 419 { "expr", no_argument, 0, Expr }, 420 { "expralt", no_argument, 0, ExprAlt }, 421 { "grammar", no_argument, 0, Grammar }, 422 { "libcfa", no_argument, 0, LibCFA }, 423 { "line-marks", no_argument, 0, Linemarks }, 424 { "no-line-marks", no_argument, 0, Nolinemarks }, 425 { "no-preamble", no_argument, 0, Nopreamble }, 426 { "parse", no_argument, 0, Parse }, 427 { "prelude-dir", required_argument, 0, PreludeDir }, 428 { "no-prototypes", no_argument, 0, Prototypes }, 429 { "resolver", no_argument, 0, Resolver }, 430 { "resolv-proto", no_argument, 0, ResolvProto }, 431 { "stats", required_argument, 0, Stats }, 432 { "symbol", no_argument, 0, Symbol }, 433 { "tree", no_argument, 0, Tree }, 434 { "tuple-expansion", no_argument, 0, TupleExpansion }, 435 { "validate", no_argument, 0, Validate }, 436 { 0, 0, 0, 0 } 437 }; // long_opts 438 int long_index; 439 408 409 static const char optstring[] = ":hlLmNn:pP:S:twW:D:F:"; 410 411 enum { PreludeDir = 128 }; 412 static struct option long_opts[] = { 413 { "help", no_argument, nullptr, 'h' }, 414 { "libcfa", no_argument, nullptr, 'l' }, 415 { "linemarks", no_argument, nullptr, 'L' }, 416 { "no-main", no_argument, 0, 'm' }, 417 { "no-linemarks", no_argument, nullptr, 'N' }, 418 { "no-prelude", no_argument, nullptr, 'n' }, 419 { "prototypes", no_argument, nullptr, 'p' }, 420 { "print", required_argument, nullptr, 'P' }, 421 { "prelude-dir", required_argument, nullptr, PreludeDir }, 422 { "statistics", required_argument, nullptr, 'S' }, 423 { "tree", no_argument, nullptr, 't' }, 424 { "", no_argument, nullptr, 0 }, // -w 425 { "", no_argument, nullptr, 0 }, // -W 426 { "", no_argument, nullptr, 0 }, // -D 427 { "", no_argument, nullptr, 0 }, // -F 428 { nullptr, 0, nullptr, 0 } 429 }; // long_opts 430 431 static const char * description[] = { 432 "print help message", // -h 433 "generate libcfa.c", // -l 434 "generate line marks", // -L 435 "do not replace main", // -m 436 "do not generate line marks", // -N 437 "do not read prelude", // -n 438 "generate prototypes for prelude functions", // -p 439 "print", // -P 440 "<directory> prelude directory for debug/nodebug", // no flag 441 "<option-list> enable profiling information:\n counters,heap,time,all,none", // -S 442 "build in tree", // -t 443 "", // -w 444 "", // -W 445 "", // -D 446 "", // -F 447 }; // description 448 449 static_assert( sizeof( long_opts ) / sizeof( long_opts[0] ) - 1 == sizeof( description ) / sizeof( description[0] ), "Long opts and description must match" ); 450 451 static struct Printopts { 452 const char * name; 453 int & flag; 454 int val; 455 const char * descript; 456 } printopts[] = { 457 { "altexpr", expraltp, true, "alternatives for expressions" }, 458 { "ascodegen", codegenp, true, "as codegen rather than AST" }, 459 { "ast", astp, true, "AST after parsing" }, 460 { "astdecl", validp, true, "AST after declaration validation pass" }, 461 { "asterr", errorp, true, "AST on error" }, 462 { "astexpr", exprp, true, "AST after expression analysis" }, 463 { "astgen", genericsp, true, "AST after instantiate generics" }, 464 { "box", bboxp, true, "before box step" }, 465 { "ctordtor", ctorinitp, true, "after ctor/dtor are replaced" }, 466 { "codegen", bcodegenp, true, "before code generation" }, 467 { "declstats", declstatsp, true, "code property statistics" }, 468 { "parse", yydebug, true, "yacc (parsing) debug information" }, 469 { "pretty", prettycodegenp, true, "prettyprint for ascodegen flag" }, 470 { "resolver", bresolvep, true, "before resolver step" }, 471 { "rproto", resolvprotop, true, "resolver-proto instance" }, 472 { "rsteps", resolvep, true, "resolver steps" }, 473 { "symevt", symtabp, true, "symbol table events" }, 474 { "tree", parsep, true, "parse tree" }, 475 { "tuple", tuplep, true, "after tuple expansion" }, 476 }; 477 enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) }; 478 479 static void usage( char *argv[] ) { 480 cout << "Usage: " << argv[0] << " options are:" << endl; 481 int i = 0, j = 1; // j skips starting colon 482 for ( ; long_opts[i].name != 0 && optstring[j] != '\0'; i += 1, j += 1 ) { 483 if ( long_opts[i].name[0] != '\0' ) { // hidden option, internal usage only 484 if ( strcmp( long_opts[i].name, "prelude-dir" ) != 0 ) { // flag 485 cout << " -" << optstring[j] << ","; 486 } else { // no flag 487 j -= 1; // compensate 488 cout << " "; 489 } // if 490 cout << " --" << left << setw(12) << long_opts[i].name << " "; 491 if ( strcmp( long_opts[i].name, "print" ) == 0 ) { 492 cout << "one of: " << endl; 493 for ( int i = 0; i < printoptsSize; i += 1 ) { 494 cout << setw(10) << " " << left << setw(10) << printopts[i].name << " " << printopts[i].descript << endl; 495 } // for 496 } else { 497 cout << description[i] << endl; 498 } // if 499 } // if 500 if ( optstring[j + 1] == ':' ) j += 1; 501 } // for 502 if ( long_opts[i].name != 0 || optstring[j] != '\0' ) assertf( false, "internal error, mismatch of option flags and names\n" ); 503 exit( EXIT_FAILURE ); 504 } // usage 505 506 static void parse_cmdline( int argc, char * argv[], const char *& filename ) { 440 507 opterr = 0; // (global) prevent getopt from printing error messages 441 508 442 509 bool Wsuppress = false, Werror = false; 443 510 int c; 444 while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrRstTvwW:yzZD:F:", long_opts, &long_index)) != -1 ) {511 while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) { 445 512 switch ( c ) { 446 case Ast: 447 case 'a': // dump AST 448 astp = true; 449 break; 450 case Bresolver: 451 case 'b': // print before resolver steps 452 bresolvep = true; 453 break; 454 case 'B': // print before box steps 455 bboxp = true; 456 break; 457 case CtorInitFix: 458 case 'c': // print after constructors and destructors are replaced 459 ctorinitp = true; 460 break; 461 case 'C': // print before code generation 462 bcodegenp = true; 463 break; 464 case DeclStats: 465 case 'd': 466 declstatsp = true; 467 break; 468 case Expr: 469 case 'e': // dump AST after expression analysis 470 exprp = true; 471 break; 472 case ExprAlt: 473 case 'f': // print alternatives for expressions 474 expraltp = true; 475 break; 476 case Grammar: 477 case 'g': // bison debugging info (grammar rules) 478 yydebug = true; 479 break; 480 case 'G': // dump AST after instantiate generics 481 genericsp = true; 482 break; 483 case LibCFA: 484 case 'l': // generate libcfa.c 513 case 'h': // help message 514 usage( argv ); // no return 515 break; 516 case 'l': // generate libcfa.c 485 517 libcfap = true; 486 518 break; 487 case Linemarks: 488 case 'L': // print lines marks 519 case 'L': // generate line marks 489 520 linemarks = true; 490 521 break; 491 case Nopreamble: 492 case 'n': // do not read preamble 522 case 'm': // do not replace main 523 nomainp = true; 524 break; 525 case 'N': // do not generate line marks 526 linemarks = false; 527 break; 528 case 'n': // do not read prelude 493 529 nopreludep = true; 494 530 break; 495 case Nolinemarks: 496 case 'N': // suppress line marks 497 linemarks = false; 498 break; 499 case Prototypes: 500 case 'p': // generate prototypes for preamble functions 501 noprotop = true; 502 break; 503 case PreludeDir: 504 PreludeDirector = optarg; 505 break; 506 case 'm': // don't replace the main 507 nomainp = true; 508 break; 509 case Parse: 510 case 'q': // dump parse tree 511 parsep = true; 512 break; 513 case Resolver: 514 case 'r': // print resolver steps 515 resolvep = true; 516 break; 517 case 'R': // dump resolv-proto instance 518 resolvprotop = true; 519 break; 520 case Stats: 521 Stats::parse_params(optarg); 522 break; 523 case Symbol: 524 case 's': // print symbol table events 525 symtabp = true; 526 break; 527 case Tree: 528 case 't': // build in tree 531 case 'p': // generate prototypes for prelude functions 532 genproto = true; 533 break; 534 case 'P': // print options 535 for ( int i = 0;; i += 1 ) { 536 if ( i == printoptsSize ) { 537 cout << "Unknown --print option " << optarg << endl; 538 goto Default; 539 } // if 540 if ( strcmp( optarg, printopts[i].name ) == 0 ) { 541 printopts[i].flag = printopts[i].val; 542 break; 543 } // if 544 } // for 545 break; 546 case PreludeDir: // prelude directory for debug/nodebug, hidden 547 PreludeDirector = optarg; 548 break; 549 case 'S': // enable profiling information, argument comma separated list of names 550 Stats::parse_params( optarg ); 551 break; 552 case 't': // build in tree 529 553 treep = true; 530 554 break; 531 case TupleExpansion: 532 case 'T': // print after tuple expansion 533 tuplep = true; 534 break; 535 case 'v': // dump AST after decl validation pass 536 validp = true; 537 break; 538 case 'w': 555 case 'w': // suppress all warnings, hidden 539 556 Wsuppress = true; 540 557 break; 541 case 'W':558 case 'W': // coordinate gcc -W with CFA, hidden 542 559 if ( strcmp( optarg, "all" ) == 0 ) { 543 560 SemanticWarning_EnableAll(); … … 556 573 } // if 557 574 break; 558 case 'y': // dump AST on error 559 errorp = true; 560 break; 561 case 'z': // dump as codegen rather than AST 562 codegenp = true; 563 break; 564 case 'Z': // prettyprint during codegen (i.e. print unmangled names, etc.) 565 prettycodegenp = true; 566 break; 567 case 'D': // ignore -Dxxx 568 break; 569 case 'F': // source file-name without suffix 575 case 'D': // ignore -Dxxx, forwarded by cpp, hidden 576 break; 577 case 'F': // source file-name without suffix, hidden 570 578 filename = optarg; 571 579 break; 572 case '?':580 case '?': // unknown option 573 581 if ( optopt ) { // short option ? 574 assertf( false, "Unknown option: -%c\n", (char)optopt );582 cout << "Unknown option -" << (char)optopt << endl; 575 583 } else { 576 assertf( false, "Unknown option: %s\n", argv[optind - 1] ); 577 } // if 578 #if defined(__GNUC__) && __GNUC__ >= 7 579 __attribute__((fallthrough)); 580 #endif 581 default: 582 abort(); 584 cout << "Unknown option " << argv[optind - 1] << endl; 585 } // if 586 goto Default; 587 case ':': // missing option 588 if ( optopt ) { // short option ? 589 cout << "Missing option for -" << (char)optopt << endl; 590 } else { 591 cout << "Missing option for " << argv[optind - 1] << endl; 592 } // if 593 goto Default; 594 Default: 595 default: 596 usage( argv ); // no return 583 597 } // switch 584 598 } // while … … 618 632 list< Declaration * > decls; 619 633 620 if ( noprotop) {634 if ( genproto ) { 621 635 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude ); 622 636 } else { … … 626 640 // depending on commandline options, either generate code or dump the AST 627 641 if ( codegenp ) { 628 CodeGen::generate( decls, out, ! noprotop, prettycodegenp );642 CodeGen::generate( decls, out, ! genproto, prettycodegenp ); 629 643 } else { 630 644 printAll( decls, out ); 631 } 645 } // if 632 646 deleteAll( translationUnit ); 633 647 } // dump -
tests/.expect/KRfunctions.x64.txt
r63364d8 rb038fe4 44 44 __attribute__ ((unused)) signed int _X10_retval_f5i_1; 45 45 } 46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))( signed int __anonymous_object0){46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(__attribute__ ((unused)) signed int __anonymous_object0){ 47 47 __attribute__ ((unused)) signed int (*_X10_retval_f6Fi_i__1)(signed int __anonymous_object1); 48 48 } -
tests/.expect/KRfunctions.x86.txt
r63364d8 rb038fe4 44 44 __attribute__ ((unused)) signed int _X10_retval_f5i_1; 45 45 } 46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))( signed int __anonymous_object0){46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(__attribute__ ((unused)) signed int __anonymous_object0){ 47 47 __attribute__ ((unused)) signed int (*_X10_retval_f6Fi_i__1)(signed int __anonymous_object1); 48 48 } -
tests/.expect/attributes.x64.txt
r63364d8 rb038fe4 271 271 } 272 272 __attribute__ ((unused,used,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object1); 273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())( signed int __anonymous_object2){273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(__attribute__ ((unused)) signed int __anonymous_object2){ 274 274 __attribute__ ((unused)) signed int (*_X10_retval_f4Fi_i__1)(signed int __anonymous_object3); 275 275 } -
tests/.expect/attributes.x86.txt
r63364d8 rb038fe4 271 271 } 272 272 __attribute__ ((unused,used,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object1); 273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())( signed int __anonymous_object2){273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(__attribute__ ((unused)) signed int __anonymous_object2){ 274 274 __attribute__ ((unused)) signed int (*_X10_retval_f4Fi_i__1)(signed int __anonymous_object3); 275 275 } -
tests/.expect/declarationSpecifier.x64.txt
r63364d8 rb038fe4 691 691 ((void)(_X12_retval_maini_1=0) /* ?{} */); 692 692 return _X12_retval_maini_1; 693 ((void)(_X12_retval_maini_1=0) /* ?{} */);694 return _X12_retval_maini_1;695 693 } 696 694 static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return _X4mainFi_iPPKc__1((signed int )argc, (const char **)argv); } -
tests/.expect/declarationSpecifier.x86.txt
r63364d8 rb038fe4 691 691 ((void)(_X12_retval_maini_1=0) /* ?{} */); 692 692 return _X12_retval_maini_1; 693 ((void)(_X12_retval_maini_1=0) /* ?{} */);694 return _X12_retval_maini_1;695 693 } 696 694 static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return _X4mainFi_iPPKc__1((signed int )argc, (const char **)argv); } -
tests/.expect/functions.x64.txt
r63364d8 rb038fe4 1 1 void _X1hFv___1(void){ 2 2 } 3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1( signed int (*__anonymous_object0)(void), signed int (*__anonymous_object1)(signed int __anonymous_object2), signed int (*__anonymous_object3)(void),signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(__attribute__ ((unused)) signed int (*__anonymous_object0)(void), __attribute__ ((unused)) signed int (*__anonymous_object1)(signed int __anonymous_object2), __attribute__ ((unused)) signed int (*__anonymous_object3)(void), __attribute__ ((unused)) signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){ 4 4 __attribute__ ((unused)) signed int _X9_retval_fi_1; 5 5 ((void)(*_X1gFv___1)()); … … 90 90 __attribute__ ((unused)) signed int _X9_retval_fi_1; 91 91 } 92 signed int _X1fFi_i__1( signed int __anonymous_object7){92 signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object7){ 93 93 __attribute__ ((unused)) signed int _X9_retval_fi_1; 94 94 } … … 121 121 __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = { }; 122 122 } 123 struct _conc__tuple2_0 _X1fFT2ii_ii__1( signed int __anonymous_object9, signed int _X1xi_1){123 struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object9, signed int _X1xi_1){ 124 124 __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = { }; 125 125 } … … 158 158 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 159 159 } 160 struct _conc__tuple3_1 _X1fFT3iii_iii__1( signed int __anonymous_object12, signed int _X1xi_1,signed int __anonymous_object13){160 struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object12, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object13){ 161 161 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 162 162 } … … 171 171 __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = { }; 172 172 } 173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1( signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){ 174 174 __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = { }; 175 175 } … … 181 181 const double _X3fooFd___1(void); 182 182 const double _X3fooFd_i__1(signed int __anonymous_object19); 183 const double _X3fooFd_d__1( double __anonymous_object20){183 const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object20){ 184 184 __attribute__ ((unused)) const double _X11_retval_fooKd_1; 185 185 ((void)((*((double *)(&_X11_retval_fooKd_1)))=3.0) /* ?{} */); … … 212 212 ((void)((*_X4_dstS1S_1)._X1ii_1=_X1ii_1) /* ?{} */); 213 213 } 214 struct S _X3rtnFS1S_i__1( signed int __anonymous_object21){214 struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object21){ 215 215 __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1; 216 216 } 217 signed int _X1fFi_Fi_ii_Fi_i___1( signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1),signed int (*__anonymous_object24)(signed int __anonymous_object25)){217 signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), __attribute__ ((unused)) signed int (*__anonymous_object24)(signed int __anonymous_object25)){ 218 218 __attribute__ ((unused)) signed int _X9_retval_fi_1; 219 219 signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned long int )10)])[][((unsigned long int )3)]; … … 241 241 } 242 242 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object27)(), signed int *(*__anonymous_object28)(), signed int **(*__anonymous_object29)(), signed int *const *(*__anonymous_object30)(), signed int *const *const (*__anonymous_object31)(), signed int *__anonymous_object32, signed int __anonymous_object33[((unsigned long int )10)], signed int **__anonymous_object34, signed int *__anonymous_object35[((unsigned long int )10)], signed int ***__anonymous_object36, signed int **__anonymous_object37[((unsigned long int )10)], signed int *const **__anonymous_object38, signed int *const *__anonymous_object39[((unsigned long int )10)], signed int *const *const *__anonymous_object40, signed int *const *const __anonymous_object41[((unsigned long int )10)]); 243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1( signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[((unsigned long int )10)], signed int **__anonymous_object49, signed int *__anonymous_object50[((unsigned long int )10)], signed int ***__anonymous_object51, signed int **__anonymous_object52[((unsigned long int )10)], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[((unsigned long int )10)], signed int *const *const *__anonymous_object55,signed int *const *const __anonymous_object56[((unsigned long int )10)]){243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object42)(), __attribute__ ((unused)) signed int *(*__anonymous_object43)(), __attribute__ ((unused)) signed int **(*__anonymous_object44)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object45)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object46)(), __attribute__ ((unused)) signed int *__anonymous_object47, __attribute__ ((unused)) signed int __anonymous_object48[((unsigned long int )10)], __attribute__ ((unused)) signed int **__anonymous_object49, __attribute__ ((unused)) signed int *__anonymous_object50[((unsigned long int )10)], __attribute__ ((unused)) signed int ***__anonymous_object51, __attribute__ ((unused)) signed int **__anonymous_object52[((unsigned long int )10)], __attribute__ ((unused)) signed int *const **__anonymous_object53, __attribute__ ((unused)) signed int *const *__anonymous_object54[((unsigned long int )10)], __attribute__ ((unused)) signed int *const *const *__anonymous_object55, __attribute__ ((unused)) signed int *const *const __anonymous_object56[((unsigned long int )10)]){ 244 244 __attribute__ ((unused)) signed int _X9_retval_fi_1; 245 245 } -
tests/.expect/functions.x86.txt
r63364d8 rb038fe4 1 1 void _X1hFv___1(void){ 2 2 } 3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1( signed int (*__anonymous_object0)(void), signed int (*__anonymous_object1)(signed int __anonymous_object2), signed int (*__anonymous_object3)(void),signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(__attribute__ ((unused)) signed int (*__anonymous_object0)(void), __attribute__ ((unused)) signed int (*__anonymous_object1)(signed int __anonymous_object2), __attribute__ ((unused)) signed int (*__anonymous_object3)(void), __attribute__ ((unused)) signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){ 4 4 __attribute__ ((unused)) signed int _X9_retval_fi_1; 5 5 ((void)(*_X1gFv___1)()); … … 90 90 __attribute__ ((unused)) signed int _X9_retval_fi_1; 91 91 } 92 signed int _X1fFi_i__1( signed int __anonymous_object7){92 signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object7){ 93 93 __attribute__ ((unused)) signed int _X9_retval_fi_1; 94 94 } … … 121 121 __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = { }; 122 122 } 123 struct _conc__tuple2_0 _X1fFT2ii_ii__1( signed int __anonymous_object9, signed int _X1xi_1){123 struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object9, signed int _X1xi_1){ 124 124 __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = { }; 125 125 } … … 158 158 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 159 159 } 160 struct _conc__tuple3_1 _X1fFT3iii_iii__1( signed int __anonymous_object12, signed int _X1xi_1,signed int __anonymous_object13){160 struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object12, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object13){ 161 161 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 162 162 } … … 171 171 __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = { }; 172 172 } 173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1( signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){ 174 174 __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = { }; 175 175 } … … 181 181 const double _X3fooFd___1(void); 182 182 const double _X3fooFd_i__1(signed int __anonymous_object19); 183 const double _X3fooFd_d__1( double __anonymous_object20){183 const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object20){ 184 184 __attribute__ ((unused)) const double _X11_retval_fooKd_1; 185 185 ((void)((*((double *)(&_X11_retval_fooKd_1)))=3.0) /* ?{} */); … … 212 212 ((void)((*_X4_dstS1S_1)._X1ii_1=_X1ii_1) /* ?{} */); 213 213 } 214 struct S _X3rtnFS1S_i__1( signed int __anonymous_object21){214 struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object21){ 215 215 __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1; 216 216 } 217 signed int _X1fFi_Fi_ii_Fi_i___1( signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1),signed int (*__anonymous_object24)(signed int __anonymous_object25)){217 signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), __attribute__ ((unused)) signed int (*__anonymous_object24)(signed int __anonymous_object25)){ 218 218 __attribute__ ((unused)) signed int _X9_retval_fi_1; 219 219 signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned int )10)])[][((unsigned int )3)]; … … 241 241 } 242 242 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object27)(), signed int *(*__anonymous_object28)(), signed int **(*__anonymous_object29)(), signed int *const *(*__anonymous_object30)(), signed int *const *const (*__anonymous_object31)(), signed int *__anonymous_object32, signed int __anonymous_object33[((unsigned int )10)], signed int **__anonymous_object34, signed int *__anonymous_object35[((unsigned int )10)], signed int ***__anonymous_object36, signed int **__anonymous_object37[((unsigned int )10)], signed int *const **__anonymous_object38, signed int *const *__anonymous_object39[((unsigned int )10)], signed int *const *const *__anonymous_object40, signed int *const *const __anonymous_object41[((unsigned int )10)]); 243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1( signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[((unsigned int )10)], signed int **__anonymous_object49, signed int *__anonymous_object50[((unsigned int )10)], signed int ***__anonymous_object51, signed int **__anonymous_object52[((unsigned int )10)], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[((unsigned int )10)], signed int *const *const *__anonymous_object55,signed int *const *const __anonymous_object56[((unsigned int )10)]){243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object42)(), __attribute__ ((unused)) signed int *(*__anonymous_object43)(), __attribute__ ((unused)) signed int **(*__anonymous_object44)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object45)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object46)(), __attribute__ ((unused)) signed int *__anonymous_object47, __attribute__ ((unused)) signed int __anonymous_object48[((unsigned int )10)], __attribute__ ((unused)) signed int **__anonymous_object49, __attribute__ ((unused)) signed int *__anonymous_object50[((unsigned int )10)], __attribute__ ((unused)) signed int ***__anonymous_object51, __attribute__ ((unused)) signed int **__anonymous_object52[((unsigned int )10)], __attribute__ ((unused)) signed int *const **__anonymous_object53, __attribute__ ((unused)) signed int *const *__anonymous_object54[((unsigned int )10)], __attribute__ ((unused)) signed int *const *const *__anonymous_object55, __attribute__ ((unused)) signed int *const *const __anonymous_object56[((unsigned int )10)]){ 244 244 __attribute__ ((unused)) signed int _X9_retval_fi_1; 245 245 } -
tests/declarationSpecifier.cfa
r63364d8 rb038fe4 10 10 // Created On : Wed Aug 17 08:21:04 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 17:52:59 201813 // Update Count : 312 // Last Modified On : Tue Apr 30 18:20:36 2019 13 // Update Count : 4 14 14 // 15 15 … … 89 89 90 90 //Dummy main 91 int main(int argc, char const *argv[]) 92 { 93 return 0; 94 } 91 int main( int argc, char const * argv[] ) {} 95 92 96 93 // Local Variables: //
Note: See TracChangeset
for help on using the changeset viewer.