Changeset 054514d
- Timestamp:
- May 29, 2018, 3:26:31 PM (6 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, with_gc
- Children:
- 3530f39a
- Parents:
- 96812c0 (diff), da60c631 (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:
-
- 8 added
- 52 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/TestRegen
r96812c0 r054514d 33 33 email() 34 34 } 35 } 35 } 36 36 catch (Exception caughtError) { 37 37 email_error() … … 65 65 66 66 def install_dir = pwd tmp: true 67 67 68 68 //Configure the conpilation (Output is not relevant) 69 69 //Use the current directory as the installation target so nothing … … 101 101 def email_subject = "[cforall dashboard][TEST REGEN# ${env.BUILD_NUMBER}] - Result" 102 102 def email_body = """This is an automated email from the Jenkins build machine. It was 103 generated http ://plg2:8082/dashboard.103 generated https://cforall.uwaterloo.ca:8082/dashboard.html. 104 104 105 105 Please apply the required changes using the following method : … … 118 118 def email_subject = "[cforall dashboard][TEST REGEN# ${env.BUILD_NUMBER}] - FAILURE" 119 119 def email_body = """This is an automated email from the Jenkins build machine. It was 120 generated http ://plg2:8082/dashboard.120 generated https://cforall.uwaterloo.ca:8082/dashboard.html. 121 121 122 122 Test generation encoutered an error please see attached logs -
Jenkinsfile
r96812c0 r054514d 174 174 175 175 def notify_server(int wait) { 176 sh """curl --data "wait=${wait}" -X POST http ://plg2:8082/jenkins/notify > /dev/null || true"""176 sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true""" 177 177 return 178 178 } … … 329 329 330 330 //Then publish the results 331 sh 'curl -H \'Content-Type: application/json\' --data @bench.json http ://plg2:8082/jenkins/publish > /dev/null || true'331 sh 'curl -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true' 332 332 } 333 333 } -
README
r96812c0 r054514d 107 107 - the implicit coercion of structure types to the type of their first member is 108 108 not implemented 109 109 110 110 Who is responsible for cfa-cc? 111 111 ------------------------------ … … 115 115 The Cforall project maintains a web page: 116 116 117 http ://plg.uwaterloo.ca/~cforall117 https://cforall.uwaterloo.ca -
doc/bibliography/pl.bib
r96812c0 r054514d 377 377 } 378 378 379 @article{Hoare61, 380 keywords = {quick sort}, 381 contributer = {pabuhr@plg}, 382 author = {C. A. R. Hoare}, 383 title = {Algorithms 63/64: Partition/Quicksort}, 384 journal = cacm, 385 volume = 4, 386 number = 7, 387 month = jul, 388 year = 1961, 389 pages = {321}, 390 } 391 379 392 @article{Cormack81, 380 393 keywords = {}, … … 635 648 year = 2008, 636 649 pages = {8-15}, 650 } 651 652 @article{Joung00, 653 author = {Joung, Yuh-Jzer}, 654 title = {Asynchronous group mutual exclusion}, 655 journal = {Distributed Computing}, 656 year = {2000}, 657 month = {Nov}, 658 volume = {13}, 659 number = {4}, 660 pages = {189--206}, 637 661 } 638 662 … … 5791 5815 @manual{Python, 5792 5816 keywords = {Python}, 5793 contributer = {pabuhr },5817 contributer = {pabuhr@plg}, 5794 5818 title = {Python Reference Manual, Release 2.5}, 5795 5819 author = {Guido van Rossum}, … … 5822 5846 } 5823 5847 5824 @article{Hoare61, 5825 keywords = {quick sort}, 5826 contributer = {pabuhr@plg}, 5827 author = {C. A. R. Hoare}, 5828 title = {Algorithms 63/64: Partition/Quicksort}, 5829 journal = cacm, 5830 volume = 4, 5831 number = 7, 5832 month = jul, 5833 year = 1961, 5834 pages = {321}, 5848 @article{Nakaike15, 5849 keywords = {hardware transactional memory}, 5850 contributer = {pabuhr@plg}, 5851 author = {Nakaike, Takuya and Odaira, Rei and Gaudet, Matthew and Michael, Maged M. and Tomari, Hisanobu}, 5852 title = {Quantitative Comparison of Hardware Transactional Memory for Blue Gene/Q, zEnterprise {EC12}, {I}ntel Core, and {POWER8}}, 5853 journal = {SIGARCH Comput. Archit. News}, 5854 volume = {43}, 5855 number = {3}, 5856 month = jun, 5857 year = {2015}, 5858 pages = {144--157}, 5859 publisher = {ACM}, 5860 address = {New York, NY, USA}, 5835 5861 } 5836 5862 -
doc/papers/concurrency/Paper.tex
r96812c0 r054514d 70 70 %\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}} 71 71 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 72 %\def\myCHarFont{\fontencoding{T1}\selectfont}%73 % \def\{{\ttfamily\upshape\myCHarFont \char`\}}}%74 72 75 73 \renewcommand*{\thefootnote}{\Alph{footnote}} % hack because fnsymbol does not work … … 741 739 The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code has the three suspend points, representing the three states in the Fibonacci formula, to context switch back to the caller's resume. 742 740 The interface function, @next@, takes a Fibonacci instance and context switches to it using @resume@; 743 on re turn, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.741 on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned. 744 742 The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack; 745 743 when the coroutine main returns, its stack is deallocated. 746 744 Hence, @Fib@ is an object at creation, transitions to a coroutine on its first resume, and transitions back to an object when the coroutine main finishes. 747 745 Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}. 748 Coroutine generators are called \newterm{output coroutines} because values are returned by the coroutine.749 750 Figure~\ref{f:CFAFmt} shows an \newterm{input coroutine}, @Format@, for restructuring text into groups of character blocks of fixed size.746 Coroutine generators are called \newterm{output coroutines} because values are only returned. 747 748 Figure~\ref{f:CFAFmt} shows an \newterm{input coroutine}, @Format@, for restructuring text into groups of characters of fixed-size blocks. 751 749 For example, the input of the left is reformatted into the output on the right. 752 750 \begin{quote} … … 763 761 \end{tabular} 764 762 \end{quote} 765 The example takes advantage of resuming coroutines in the constructor to prime the coroutine loops so the first character sent for formatting appears inside the nested loops.763 The example takes advantage of resuming a coroutine in the constructor to prime the loops so the first character sent for formatting appears inside the nested loops. 766 764 The destruction provides a newline if formatted text ends with a full line. 767 765 Figure~\ref{f:CFmt} shows the C equivalent formatter, where the loops of the coroutine are flatten (linearized) and rechecked on each call because execution location is not retained between calls. … … 778 776 void main( Format & fmt ) with( fmt ) { 779 777 for ( ;; ) { 780 for ( g = 0; g < 5; g += 1 ) { // group778 for ( g = 0; g < 5; g += 1 ) { // group 781 779 for ( b = 0; b < 4; b += 1 ) { // block 782 780 `suspend();` … … 814 812 }; 815 813 void format( struct Format * fmt ) { 816 if ( fmt->ch != -1 ) { // not EOF814 if ( fmt->ch != -1 ) { // not EOF ? 817 815 printf( "%c", fmt->ch ); 818 816 fmt->b += 1; … … 823 821 } 824 822 if ( fmt->g == 5 ) { // group 825 printf( "\n" ); 823 printf( "\n" ); // separator 826 824 fmt->g = 0; 827 825 } … … 850 848 851 849 The previous examples are \newterm{asymmetric (semi) coroutine}s because one coroutine always calls a resuming function for another coroutine, and the resumed coroutine always suspends back to its last resumer, similar to call/return for normal functions. 852 However, there is no stack growth because @resume@/@suspend@ context switch to an existing stack frames rather than create a new one.853 \newterm{Symmetric (full) coroutine}s have a coroutine call a resuming function for another coroutine, which eventually forms a cycle.850 However, there is no stack growth because @resume@/@suspend@ context switch to existing stack-frames rather than create new ones. 851 \newterm{Symmetric (full) coroutine}s have a coroutine call a resuming function for another coroutine, which eventually forms a resuming-call cycle. 854 852 (The trivial cycle is a coroutine resuming itself.) 855 853 This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch. … … 935 933 The @start@ function communicates both the number of elements to be produced and the consumer into the producer's coroutine structure. 936 934 Then the @resume@ to @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it. 937 @prod@'s coroutine main starts, creates local variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random val es, calling the consumer to deliver the values, and printing the status returned from the consumer.935 @prod@'s coroutine main starts, creates local variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random values, calling the consumer to deliver the values, and printing the status returned from the consumer. 938 936 939 937 The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status. 940 938 For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine. 941 The consumer iterates until the @done@ flag is set, prints, increments status, and calls back to the producer 's @payment@ member, and on return prints the receipt from the producer and increments the money for the next payment.942 The call from the consumer to the producer's @payment@ memberintroduces the cycle between producer and consumer.939 The consumer iterates until the @done@ flag is set, prints, increments status, and calls back to the producer via @payment@, and on return from @payment@, prints the receipt from the producer and increments @money@ (inflation). 940 The call from the consumer to the @payment@ introduces the cycle between producer and consumer. 943 941 When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed. 944 The context switch restarts the producer at the point where it was last context switched and it continues in member@delivery@ after the resume.945 946 The @delivery@ member returns the status value in @prod@'s @main@ member, where the status is printed.942 The context switch restarts the producer at the point where it was last context switched, so it continues in @delivery@ after the resume. 943 944 @delivery@ returns the status value in @prod@'s coroutine main, where the status is printed. 947 945 The loop then repeats calling @delivery@, where each call resumes the consumer coroutine. 948 946 The context switch to the consumer continues in @payment@. 949 The consumer increments and returns the receipt to the call in @cons@'s @main@ member.947 The consumer increments and returns the receipt to the call in @cons@'s coroutine main. 950 948 The loop then repeats calling @payment@, where each call resumes the producer coroutine. 951 949 … … 954 952 The context switch restarts @cons@ in @payment@ and it returns with the last receipt. 955 953 The consumer terminates its loops because @done@ is true, its @main@ terminates, so @cons@ transitions from a coroutine back to an object, and @prod@ reactivates after the resume in @stop@. 956 The @stop@ member returns and @prod@'s @main@ memberterminates.954 @stop@ returns and @prod@'s coroutine main terminates. 957 955 The program main restarts after the resume in @start@. 958 The @start@ member returns and the program main terminates. 959 960 961 \subsubsection{Construction} 962 963 One important design challenge for implementing coroutines and threads (shown in section \ref{threads}) is that the runtime system needs to run code after the user-constructor runs to connect the fully constructed object into the system. 964 In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling. 965 However, the underlying challenge remains the same for coroutines and threads. 966 967 The runtime system needs to create the coroutine's stack and, more importantly, prepare it for the first resumption. 968 The timing of the creation is non-trivial since users expect both to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor. 969 There are several solutions to this problem but the chosen option effectively forces the design of the coroutine. 970 971 Furthermore, \CFA faces an extra challenge as polymorphic routines create invisible thunks when cast to non-polymorphic routines and these thunks have function scope. 972 For example, the following code, while looking benign, can run into undefined behaviour because of thunks: 973 974 \begin{cfa} 975 // async: Runs function asynchronously on another thread 976 forall(otype T) 977 extern void async(void (*func)(T*), T* obj); 978 979 forall(otype T) 980 void noop(T*) {} 981 982 void bar() { 983 int a; 984 async(noop, &a); // start thread running noop with argument a 985 } 986 \end{cfa} 987 988 The generated C code\footnote{Code trimmed down for brevity} creates a local thunk to hold type information: 989 990 \begin{cfa} 991 extern void async(/* omitted */, void (*func)(void*), void* obj); 992 993 void noop(/* omitted */, void* obj){} 994 995 void bar(){ 996 int a; 997 void _thunk0(int* _p0){ 998 /* omitted */ 999 noop(/* omitted */, _p0); 1000 } 1001 /* omitted */ 1002 async(/* omitted */, ((void (*)(void*))(&_thunk0)), (&a)); 1003 } 1004 \end{cfa} 1005 The problem in this example is a storage management issue, the function pointer @_thunk0@ is only valid until the end of the block, which limits the viable solutions because storing the function pointer for too long causes undefined behaviour; \ie the stack-based thunk being destroyed before it can be used. 1006 This challenge is an extension of challenges that come with second-class routines. 1007 Indeed, GCC nested routines also have the limitation that nested routine cannot be passed outside of the declaration scope. 1008 The case of coroutines and threads is simply an extension of this problem to multiple call stacks. 1009 1010 1011 \subsubsection{Alternative: Composition} 1012 1013 One solution to this challenge is to use composition/containment, where coroutine fields are added to manage the coroutine. 1014 1015 \begin{cfa} 1016 struct Fibonacci { 1017 int fn; // used for communication 1018 coroutine c; // composition 1019 }; 1020 1021 void FibMain(void*) { 1022 //... 1023 } 1024 1025 void ?{}(Fibonacci& this) { 1026 this.fn = 0; 1027 // Call constructor to initialize coroutine 1028 (this.c){myMain}; 1029 } 1030 \end{cfa} 1031 The downside of this approach is that users need to correctly construct the coroutine handle before using it. 1032 Like any other objects, the user must carefully choose construction order to prevent usage of objects not yet constructed. 1033 However, in the case of coroutines, users must also pass to the coroutine information about the coroutine main, like in the previous example. 1034 This opens the door for user errors and requires extra runtime storage to pass at runtime information that can be known statically. 1035 1036 1037 \subsubsection{Alternative: Reserved keyword} 1038 1039 The next alternative is to use language support to annotate coroutines as follows: 1040 \begin{cfa} 1041 coroutine Fibonacci { 1042 int fn; // used for communication 1043 }; 1044 \end{cfa} 1045 The @coroutine@ keyword means the compiler can find and inject code where needed. 1046 The downside of this approach is that it makes coroutine a special case in the language. 1047 Users wanting to extend coroutines or build their own for various reasons can only do so in ways offered by the language. 1048 Furthermore, implementing coroutines without language supports also displays the power of the programming language used. 1049 While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed by users without using the language support. 1050 The reserved keywords are only present to improve ease of use for the common cases. 1051 1052 1053 \subsubsection{Alternative: Lambda Objects} 956 @start@ returns and the program main terminates. 957 958 959 \subsection{Coroutine Implementation} 960 961 A significant implementation challenge for coroutines (and threads, see section \ref{threads}) is adding extra fields and executing code after/before the coroutine constructor/destructor and coroutine main to create/initialize/de-initialize/destroy extra fields and the stack. 962 There are several solutions to this problem and the chosen option forced the \CFA coroutine design. 963 964 Object-oriented inheritance provides extra fields and code in a restricted context, but it requires programmers to explicitly perform the inheritance: 965 \begin{cfa} 966 struct mycoroutine $\textbf{\textsf{inherits}}$ baseCoroutine { ... } 967 \end{cfa} 968 and the programming language (and possibly its tool set, \eg debugger) may need to understand @baseCoroutine@ because of the stack. 969 Furthermore, the execution of constructs/destructors is in the wrong order for certain operations, \eg for threads; 970 \eg, if the thread is implicitly started, it must start \emph{after} all constructors, because the thread relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived. 971 972 An alternatively is composition: 973 \begin{cfa} 974 struct mycoroutine { 975 ... // declarations 976 baseCoroutine dummy; // composition, last declaration 977 } 978 \end{cfa} 979 which also requires an explicit declaration that must be the last one to ensure correct initialization order. 980 However, there is nothing preventing wrong placement or multiple declarations. 1054 981 1055 982 For coroutines as for threads, many implementations are based on routine pointers or function objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}. 1056 For example, Boost implements coroutines in terms of four functor object 983 For example, Boost implements coroutines in terms of four functor object-types: 1057 984 \begin{cfa} 1058 985 asymmetric_coroutine<>::pull_type … … 1061 988 symmetric_coroutine<>::yield_type 1062 989 \end{cfa} 1063 Often, the canonical threading paradigm in languages is based on function pointers, @pthread@ being one of the most well-known examples. 1064 The main problem of this approach is that the thread usage is limited to a generic handle that must otherwise be wrapped in a custom type. 1065 Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda based coroutines adds very little. 1066 1067 A variation of this would be to use a simple function pointer in the same way @pthread@ does for threads: 1068 \begin{cfa} 1069 void foo( coroutine_t cid, void* arg ) { 1070 int* value = (int*)arg; 990 Similarly, the canonical threading paradigm is often based on function pointers, \eg @pthread@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}. 991 However, the generic thread-handle (identifier) is limited (few operations), unless it is wrapped in a custom type. 992 \begin{cfa} 993 void mycor( coroutine_t cid, void * arg ) { 994 int * value = (int *)arg; $\C{// type unsafe, pointer-size only}$ 1071 995 // Coroutine body 1072 996 } 1073 1074 997 int main() { 1075 int value = 0; 1076 coroutine_t cid = coroutine_create( &foo, (void*)&value ); 1077 coroutine_resume( &cid ); 1078 } 1079 \end{cfa} 1080 This semantics is more common for thread interfaces but coroutines work equally well. 1081 As discussed in section \ref{threads}, this approach is superseded by static approaches in terms of expressivity. 1082 1083 1084 \subsubsection{Alternative: Trait-Based Coroutines} 1085 1086 Finally, the underlying approach, which is the one closest to \CFA idioms, is to use trait-based lazy coroutines. 1087 This approach defines a coroutine as anything that satisfies the trait @is_coroutine@ (as defined below) and is used as a coroutine. 1088 1089 \begin{cfa} 1090 trait is_coroutine(dtype T) { 1091 void main(T& this); 1092 coroutine_desc* get_coroutine(T& this); 998 int input = 0, output; 999 coroutine_t cid = coroutine_create( &mycor, (void *)&input ); $\C{// type unsafe, pointer-size only}$ 1000 coroutine_resume( cid, (void *)input, (void **)&output ); $\C{// type unsafe, pointer-size only}$ 1001 } 1002 \end{cfa} 1003 Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda-based coroutines adds very little. 1004 1005 The selected approach is to use language support by introducing a new kind of aggregate (structure): 1006 \begin{cfa} 1007 coroutine Fibonacci { 1008 int fn; // communication variables 1093 1009 }; 1094 1095 forall( dtype T | is_coroutine(T) ) void suspend(T&); 1096 forall( dtype T | is_coroutine(T) ) void resume (T&); 1097 \end{cfa} 1098 This ensures that an object is not a coroutine until @resume@ is called on the object. 1099 Correspondingly, any object that is passed to @resume@ is a coroutine since it must satisfy the @is_coroutine@ trait to compile. 1010 \end{cfa} 1011 The @coroutine@ keyword means the compiler (and tool set) can find and inject code where needed. 1012 The downside of this approach is that it makes coroutine a special case in the language. 1013 Users wanting to extend coroutines or build their own for various reasons can only do so in ways offered by the language. 1014 Furthermore, implementing coroutines without language supports also displays the power of a programming language. 1015 While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed without using the language support. 1016 The reserved keyword eases use for the common cases. 1017 1018 Part of the mechanism to generalize coroutines is using a \CFA trait, which defines a coroutine as anything satisfying the trait @is_coroutine@, and this trait is used to restrict coroutine-manipulation functions: 1019 \begin{cfa} 1020 trait is_coroutine( dtype T ) { 1021 void main( T & this ); 1022 coroutine_desc * get_coroutine( T & this ); 1023 }; 1024 forall( dtype T | is_coroutine(T) ) void get_coroutine( T & ); 1025 forall( dtype T | is_coroutine(T) ) void suspend( T & ); 1026 forall( dtype T | is_coroutine(T) ) void resume( T & ); 1027 \end{cfa} 1028 This definition ensures there is a statically-typed @main@ function that is the starting point (first stack frame) of a coroutine. 1029 No return value or additional parameters are necessary for this function, because the coroutine type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values. 1030 As well, any object passed to @suspend@ and @resume@ is a coroutine since it must satisfy the @is_coroutine@ trait to compile. 1100 1031 The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ routine. 1101 The \CFA keyword @coroutine@ simply has the effect of implementing the getter and forward declarations required for users to implement the main routine.1102 1103 \begin{ center}1104 \begin{ tabular}{c c c}1105 \begin{cfa}[tabsize=3] 1106 coroutine MyCoroutine { 1107 int someValue; 1032 The \CFA keyword @coroutine@ implicitly implements the getter and forward declarations required for implementing the coroutine main: 1033 \begin{cquote} 1034 \begin{tabular}{@{}ccc@{}} 1035 \begin{cfa} 1036 coroutine MyCor { 1037 int value; 1038 1108 1039 }; 1109 \end{cfa} & == & \begin{cfa}[tabsize=3] 1110 struct MyCoroutine { 1111 int someValue; 1112 coroutine_desc __cor; 1040 \end{cfa} 1041 & {\Large $\Rightarrow$} & 1042 \begin{tabular}{@{}ccc@{}} 1043 \begin{cfa} 1044 struct MyCor { 1045 int value; 1046 coroutine_desc cor; 1113 1047 }; 1114 1115 static inline 1116 coroutine_desc* get_coroutine( 1117 struct MyCoroutine& this 1118 ) { 1119 return &this.__cor; 1120 } 1121 1122 void main(struct MyCoroutine* this); 1048 \end{cfa} 1049 & 1050 \begin{cfa} 1051 static inline coroutine_desc * 1052 get_coroutine( MyCor & this ) { 1053 return &this.cor; 1054 } 1055 \end{cfa} 1056 & 1057 \begin{cfa} 1058 void main( MyCor * this ); 1059 1060 1061 1123 1062 \end{cfa} 1124 1063 \end{tabular} 1125 \end{center} 1126 1127 The combination of these two approaches allows users new to coroutining and concurrency to have an easy and concise specification, while more advanced users have tighter control on memory layout and initialization. 1128 1129 \subsection{Thread Interface}\label{threads} 1130 The basic building blocks of multithreading in \CFA are \textbf{cfathread}. 1131 Both user and kernel threads are supported, where user threads are the concurrency mechanism and kernel threads are the parallel mechanism. 1132 User threads offer a flexible and lightweight interface. 1133 A thread can be declared using a struct declaration @thread@ as follows: 1134 1135 \begin{cfa} 1136 thread foo {}; 1137 \end{cfa} 1138 1139 As for coroutines, the keyword is a thin wrapper around a \CFA trait: 1140 1141 \begin{cfa} 1142 trait is_thread(dtype T) { 1143 void ^?{}(T & mutex this); 1144 void main(T & this); 1145 thread_desc* get_thread(T & this); 1064 \end{tabular} 1065 \end{cquote} 1066 The combination of these two approaches allows an easy and concise specification to coroutining (and concurrency) for normal users, while more advanced users have tighter control on memory layout and initialization. 1067 1068 1069 \subsection{Thread Interface} 1070 \label{threads} 1071 1072 Both user and kernel threads are supported, where user threads provide concurrency and kernel threads provide parallelism. 1073 Like coroutines and for the same design reasons, the selected approach for user threads is to use language support by introducing a new kind of aggregate (structure) and a \CFA trait: 1074 \begin{cquote} 1075 \begin{tabular}{@{}c@{\hspace{2\parindentlnth}}c@{}} 1076 \begin{cfa} 1077 thread myThread { 1078 // communication variables 1146 1079 }; 1147 \end{cfa} 1148 1149 Obviously, for this thread implementation to be useful it must run some user code. 1150 Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}). 1151 However, this proposal considers that statically tying a @main@ routine to a thread supersedes this approach. 1152 Since the @main@ routine is already a special routine in \CFA (where the program begins), it is a natural extension of the semantics to use overloading to declare mains for different threads (the normal main being the main of the initial thread). 1080 1081 1082 \end{cfa} 1083 & 1084 \begin{cfa} 1085 trait is_thread( dtype T ) { 1086 void main( T & this ); 1087 thread_desc * get_thread( T & this ); 1088 void ^?{}( T & `mutex` this ); 1089 }; 1090 \end{cfa} 1091 \end{tabular} 1092 \end{cquote} 1093 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitors}.) 1094 Like a coroutine, the statically-typed @main@ function is the starting point (first stack frame) of a user thread. 1095 The difference is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates an instance of @main@; 1096 whereas, a user thread receives its own thread from the runtime system, which starts in @main@ as some point after the thread constructor is run.\footnote{ 1097 The \lstinline@main@ function is already a special routine in C (where the program begins), so it is a natural extension of the semantics to use overloading to declare mains for different coroutines/threads (the normal main being the main of the initial thread).} 1098 No return value or additional parameters are necessary for this function, because the task type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values. 1099 1100 \begin{comment} % put in appendix with coroutine version ??? 1153 1101 As such the @main@ routine of a thread can be defined as 1154 1102 \begin{cfa} … … 1189 1137 } 1190 1138 \end{cfa} 1191 1192 1139 A consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \textbf{api}. 1193 1194 Of course, for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution. 1195 While using an \textbf{api} such as @fork@ and @join@ is relatively common in the literature, such an interface is unnecessary.1196 Indeed, the simplest approach is to use \textbf{raii} principles and have threads @fork@ after the constructor has completed and @join@ before the destructor runs.1197 \begin{cfa} 1198 thread World; 1199 1200 void main( World & this) {1140 \end{comment} 1141 1142 For user threads to be useful, it must be possible to start and stop the underlying thread, and wait for it to complete execution. 1143 While using an API such as @fork@ and @join@ is relatively common, such an interface is awkward and unnecessary. 1144 A simple approach is to use allocation/deallocation principles, and have threads implicitly @fork@ after construction and @join@ before destruction. 1145 \begin{cfa} 1146 thread World {}; 1147 void main( World & this ) { 1201 1148 sout | "World!" | endl; 1202 1149 } 1203 1204 void main() { 1205 World w; 1206 // Thread forks here 1207 1208 // Printing "Hello " and "World!" are run concurrently 1209 sout | "Hello " | endl; 1210 1211 // Implicit join at end of scope 1212 } 1213 \end{cfa} 1214 1215 This semantic has several advantages over explicit semantics: a thread is always started and stopped exactly once, users cannot make any programming errors, and it naturally scales to multiple threads meaning basic synchronization is very simple. 1216 1217 \begin{cfa} 1218 thread MyThread { 1219 //... 1150 int main() { 1151 World w`[10]`; $\C{// implicit forks after creation}$ 1152 sout | "Hello " | endl; $\C{// "Hello " and 10 "World!" printed concurrently}$ 1153 } $\C{// implicit joins before destruction}$ 1154 \end{cfa} 1155 This semantics ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination) synchronization. 1156 This tree-structure (lattice) create/delete from C block-structure is generalized by using dynamic allocation, so threads can outlive the scope in which they are created, much like dynamically allocating memory lets objects outlive the scope in which they are created. 1157 \begin{cfa} 1158 int main() { 1159 MyThread * heapLived; 1160 { 1161 MyThread blockLived; $\C{// fork block-based thread}$ 1162 heapLived = `new`( MyThread ); $\C{// fork heap-based thread}$ 1163 ... 1164 } $\C{// join block-based thread}$ 1165 ... 1166 `delete`( heapLived ); $\C{// join heap-based thread}$ 1167 } 1168 \end{cfa} 1169 The heap-based approach allows arbitrary thread-creation topologies, with respect to fork/join-style concurrency. 1170 1171 Figure~\ref{s:ConcurrentMatrixSummation} shows concurrently adding the rows of a matrix and then totalling the subtotals sequential, after all the row threads have terminated. 1172 The program uses heap-based threads because each thread needs different constructor values. 1173 (Python provides a simple iteration mechanism to initialize array elements to different values allowing stack allocation.) 1174 The allocation/deallocation pattern appears unusual because allocated objects are immediately deleted without any intervening code. 1175 However, for threads, the deletion provides implicit synchronization, which is the intervening code. 1176 While the subtotals are added in linear order rather than completion order, which slight inhibits concurrency, the computation is restricted by the critical-path thread (\ie the thread that takes the longest), and so any inhibited concurrency is very small as totalling the subtotals is trivial. 1177 1178 \begin{figure} 1179 \begin{cfa} 1180 thread Adder { 1181 int * row, cols, & subtotal; $\C{// communication}$ 1220 1182 }; 1221 1222 // main 1223 void main(MyThread& this) { 1224 //... 1225 } 1226 1227 void foo() { 1228 MyThread thrds[10]; 1229 // Start 10 threads at the beginning of the scope 1230 1231 DoStuff(); 1232 1233 // Wait for the 10 threads to finish 1234 } 1235 \end{cfa} 1236 1237 However, one of the drawbacks of this approach is that threads always form a tree where nodes must always outlive their children, \ie they are always destroyed in the opposite order of construction because of C scoping rules. 1238 This restriction is relaxed by using dynamic allocation, so threads can outlive the scope in which they are created, much like dynamically allocating memory lets objects outlive the scope in which they are created. 1239 1240 \begin{cfa} 1241 thread MyThread { 1242 //... 1243 }; 1244 1245 void main(MyThread& this) { 1246 //... 1247 } 1248 1249 void foo() { 1250 MyThread* long_lived; 1251 { 1252 // Start a thread at the beginning of the scope 1253 MyThread short_lived; 1254 1255 // create another thread that will outlive the thread in this scope 1256 long_lived = new MyThread; 1257 1258 DoStuff(); 1259 1260 // Wait for the thread short_lived to finish 1261 } 1262 DoMoreStuff(); 1263 1264 // Now wait for the long_lived to finish 1265 delete long_lived; 1266 } 1267 \end{cfa} 1268 1269 1270 % ====================================================================== 1271 % ====================================================================== 1272 \section{Concurrency} 1273 % ====================================================================== 1274 % ====================================================================== 1275 Several tools can be used to solve concurrency challenges. 1276 Since many of these challenges appear with the use of mutable shared state, some languages and libraries simply disallow mutable shared state (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka (Scala)~\cite{Akka}). 1277 In these paradigms, interaction among concurrent objects relies on message passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (channels~\cite{CSP,Go} for example). 1278 However, in languages that use routine calls as their core abstraction mechanism, these approaches force a clear distinction between concurrent and non-concurrent paradigms (\ie message passing versus routine calls). 1279 This distinction in turn means that, in order to be effective, programmers need to learn two sets of design patterns. 1183 void ?{}( Adder & adder, int row[], int cols, int & subtotal ) { 1184 adder.[ row, cols, &subtotal ] = [ row, cols, &subtotal ]; 1185 } 1186 void main( Adder & adder ) with( adder ) { 1187 subtotal = 0; 1188 for ( int c = 0; c < cols; c += 1 ) { 1189 subtotal += row[c]; 1190 } 1191 } 1192 int main() { 1193 const int rows = 10, cols = 1000; 1194 int matrix[rows][cols], subtotals[rows], total = 0; 1195 // read matrix 1196 Adder * adders[rows]; 1197 for ( int r = 0; r < rows; r += 1 ) { $\C{// start threads to sum rows}$ 1198 adders[r] = new( matrix[r], cols, &subtotals[r] ); 1199 } 1200 for ( int r = 0; r < rows; r += 1 ) { $\C{// wait for threads to finish}$ 1201 delete( adders[r] ); $\C{// termination join}$ 1202 total += subtotals[r]; $\C{// total subtotal}$ 1203 } 1204 sout | total | endl; 1205 } 1206 \end{cfa} 1207 \caption{Concurrent Matrix Summation} 1208 \label{s:ConcurrentMatrixSummation} 1209 \end{figure} 1210 1211 1212 \section{Synchronization / Mutual Exclusion} 1213 1214 Uncontrolled non-deterministic execution is meaningless. 1215 To reestablish meaningful execution requires mechanisms to reintroduce determinism (control non-determinism), called synchronization and mutual exclusion, where synchronization is a timing relationship among threads and mutual exclusion is an access-control mechanism on data shared by threads. 1216 Since many deterministic challenges appear with the use of mutable shared state, some languages/libraries disallow it (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka~\cite{Akka} (Scala)). 1217 In these paradigms, interaction among concurrent objects is performed by stateless message-passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (\eg channels~\cite{CSP,Go}). 1218 However, in call/return-based languages, these approaches force a clear distinction (\ie introduce a new programming paradigm) between non-concurrent and concurrent computation (\ie function call versus message passing). 1219 This distinction means a programmers needs to learn two sets of design patterns. 1280 1220 While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account. 1281 1282 Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on basic constructs like routine calls and shared objects. 1283 At the lowest level, concurrent paradigms are implemented as atomic operations and locks. 1284 Many such mechanisms have been proposed, including semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}. 1285 However, for productivity reasons it is desirable to have a higher-level construct be the core concurrency paradigm~\cite{Hochstein05}. 1286 1287 An approach that is worth mentioning because it is gaining in popularity is transactional memory~\cite{Herlihy93}. 1288 While this approach is even pursued by system languages like \CC~\cite{Cpp-Transactions}, the performance and feature set is currently too restrictive to be the main concurrency paradigm for system languages, which is why it was rejected as the core paradigm for concurrency in \CFA. 1289 1290 One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared-memory systems, is the \emph{monitor}. 1221 In contrast, approaches based on statefull models more closely resemble the standard call/return programming-model, resulting in a single programming paradigm. 1222 1223 At the lowest level, concurrent control is implemented as atomic operations, upon which different kinds of locks mechanism are constructed, \eg semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}. 1224 However, for productivity it is always desirable to use the highest-level construct that provides the necessary efficiency~\cite{Hochstein05}. 1225 A newer approach is transactional memory~\cite{Herlihy93}. 1226 While this approach is pursued in hardware~\cite{Nakaike15} and system languages, like \CC~\cite{Cpp-Transactions}, the performance and feature set is still too restrictive to be the main concurrency paradigm for system languages, which is why it was rejected as the core paradigm for concurrency in \CFA. 1227 1228 One of the most natural, elegant, and efficient mechanisms for synchronization and mutual exclusion for shared-memory systems is the \emph{monitor}. 1291 1229 Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. 1292 Many programming languages ---\eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}---provide monitors as explicit language constructs.1230 Many programming languages -- \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java} -- provide monitors as explicit language constructs. 1293 1231 In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors. 1294 For these reasons, this project proposes monitors as the core concurrency construct. 1295 1296 1297 \subsection{Basics} 1298 1299 Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronization. 1300 Mutual-exclusion is the concept that only a fixed number of threads can access a critical section at any given time, where a critical section is a group of instructions on an associated portion of data that requires the restricted access. 1301 On the other hand, synchronization enforces relative ordering of execution and synchronization tools provide numerous mechanisms to establish timing relationships among threads. 1302 1303 1304 \subsubsection{Mutual-Exclusion} 1305 1306 As mentioned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once. 1232 For these reasons, this project proposes monitors as the core concurrency construct, upon which even higher-level approaches can be easily constructed.. 1233 1234 1235 \subsection{Mutual Exclusion} 1236 1237 A group of instructions manipulating a specific instance of shared data that must be performed atomically is called an (individual) \newterm{critical-section}~\cite{Dijkstra65}. 1238 A generalization is a \newterm{group critical-section}~\cite{Joung00}, where multiple tasks with the same session may use the resource simultaneously, but different sessions may not use the resource simultaneously. 1239 The readers/writer problem~\cite{Courtois71} is an instance of a group critical-section, where readers have the same session and all writers have a unique session. 1240 \newterm{Mutual exclusion} enforces the correction number of threads are using a critical section at the same time. 1241 1307 1242 However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use. 1308 Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to higher-level concurrency techniques, which sacrifice some performance in orderto improve ease of use.1309 Ease of use comes by either guaranteeing some problems cannot occur (\eg being deadlock free) or by offering a more explicit coupling between data and correspondingcritical section.1243 Methods range from low-level locks, which are fast and flexible but require significant attention for correctness, to higher-level concurrency techniques, which sacrifice some performance to improve ease of use. 1244 Ease of use comes by either guaranteeing some problems cannot occur (\eg deadlock free), or by offering a more explicit coupling between shared data and critical section. 1310 1245 For example, the \CC @std::atomic<T>@ offers an easy way to express mutual-exclusion on a restricted set of operations (\eg reading/writing large types atomically). 1311 Another challenge with low-level locks is composability.1312 Locks have restricted composability because it takes careful organizing for multiple locks to be used while preventing deadlocks.1313 Easing composability is another feature higher-level mutual-exclusion mechanisms often offer. 1314 1315 1316 \subsubsection{Synchronization} 1317 1318 As with mutual-exclusion, low-level synchronization primitives often offer good performance and good flexibility at the cost of ease of use.1319 Again, higher-level mechanisms often simplify usage by adding either better coupling between synchronization and data (\eg message passing) or offering a simpler solution to otherwise involved challenges.1246 However, a significant challenge with (low-level) locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock. 1247 Easing composability is another feature higher-level mutual-exclusion mechanisms offer. 1248 1249 1250 \subsection{Synchronization} 1251 1252 Synchronization enforces relative ordering of execution, and synchronization tools provide numerous mechanisms to establish these timing relationships. 1253 Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use. 1254 Higher-level mechanisms often simplify usage by adding better coupling between synchronization and data (\eg message passing), or offering a simpler solution to otherwise involved challenges, \eg barrier lock. 1320 1255 As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}. 1321 Most of the time, synchronization happens within a critical section, where threads must acquire mutual-exclusion in a certain order. 1322 However, it may also be desirable to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}. 1323 Not satisfying this property is called \textbf{barging}. 1324 For example, where event \textit{X} tries to effect event \textit{Y} but another thread acquires the critical section and emits \textit{Z} before \textit{Y}. 1325 The classic example is the thread that finishes using a resource and unblocks a thread waiting to use the resource, but the unblocked thread must compete to acquire the resource. 1256 Often synchronization is used to order access to a critical section, \eg ensuring the next kind of thread to enter a critical section is a reader thread 1257 If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, the reader has \newterm{barged}. 1258 Barging can result in staleness/freshness problems, where a reader barges ahead of a write and reads temporally stale data, or a writer barges ahead of another writer overwriting data with a fresh value preventing the previous value from having an opportunity to be read. 1326 1259 Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs. 1327 This challenge is often split into two different methods, barging avoidance and barging prevention. 1328 Algorithms that use flag variables to detect barging threads are said to be using barging avoidance, while algorithms that baton-pass locks~\cite{Andrews89} between threads instead of releasing the locks are said to be using barging prevention. 1329 1330 1331 % ====================================================================== 1332 % ====================================================================== 1260 This challenge is often split into two different approaches, barging avoidance and barging prevention. 1261 Algorithms that allow a barger but divert it until later are avoiding the barger, while algorithms that preclude a barger from entering during synchronization in the critical section prevent the barger completely. 1262 baton-pass locks~\cite{Andrews89} between threads instead of releasing the locks are said to be using barging prevention. 1263 1264 1333 1265 \section{Monitors} 1334 % ====================================================================== 1335 % ====================================================================== 1266 \label{s:Monitors} 1267 1336 1268 A \textbf{monitor} is a set of routines that ensure mutual-exclusion when accessing shared state. 1337 1269 More precisely, a monitor is a programming technique that associates mutual-exclusion to routine scopes, as opposed to mutex locks, where mutual-exclusion is defined by lock/release calls independently of any scoping of the calling routine. … … 2501 2433 Given these building blocks, it is possible to reproduce all three of the popular paradigms. 2502 2434 Indeed, \textbf{uthread} is the default paradigm in \CFA. 2503 However, disabling \textbf{preemption} on the \textbf{cfacluster} means \textbf{cfathread} effectively become \textbf{fiber}.2435 However, disabling \textbf{preemption} on a cluster means threads effectively become fibers. 2504 2436 Since several \textbf{cfacluster} with different scheduling policy can coexist in the same application, this allows \textbf{fiber} and \textbf{uthread} to coexist in the runtime of an application. 2505 2437 Finally, it is possible to build executors for thread pools from \textbf{uthread} or \textbf{fiber}, which includes specialized jobs like actors~\cite{Actors}. -
doc/papers/general/Paper.tex
r96812c0 r054514d 243 243 Nevertheless, C, first standardized almost forty years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive. 244 244 245 \CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining both source and runtime compatibility with C and a familiar programming model for programmers.245 \CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining source and runtime compatibility in the familiar C programming model. 246 246 The four key design goals for \CFA~\cite{Bilson03} are: 247 247 (1) The behaviour of standard C code must remain the same when translated by a \CFA compiler as when translated by a C compiler; … … 273 273 Starting with a translator versus a compiler makes it easier and faster to generate and debug C object-code rather than intermediate, assembler or machine code. 274 274 The translator design is based on the \emph{visitor pattern}, allowing multiple passes over the abstract code-tree, which works well for incrementally adding new feature through additional visitor passes. 275 At the heart of the translator is the type resolver, which handles the polymorphic routine/type overload-resolution.275 At the heart of the translator is the type resolver, which handles the polymorphic function/type overload-resolution. 276 276 % @plg2[8]% cd cfa-cc/src; cloc libcfa 277 277 % ------------------------------------------------------------------------------- … … 310 310 311 311 Finally, it is impossible to describe a programming language without usages before definitions. 312 Therefore, syntax and semantics appear before explanations ;313 hence, patience is necessary until details are presented.312 Therefore, syntax and semantics appear before explanations, and related work (Section~\ref{s:RelatedWork}) is deferred until \CFA is presented; 313 hence, patience is necessary until details are discussed. 314 314 315 315 … … 329 329 \end{quote} 330 330 \vspace{-9pt} 331 C already has a limited form of ad-hoc polymorphism in the form ofits basic arithmetic operators, which apply to a variety of different types using identical syntax.331 C already has a limited form of ad-hoc polymorphism in its basic arithmetic operators, which apply to a variety of different types using identical syntax. 332 332 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; 333 333 Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C. … … 653 653 } 654 654 \end{cfa} 655 Since @pair( T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@, so the generated code is identical to a function written in standard C using @void *@, yet the \CFA version is type-checked to ensure the fields of both pairs and the arguments to the comparison function match in type.655 Since @pair( T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@, so the generated code is identical to a function written in standard C using @void *@, yet the \CFA version is type-checked to ensure the members of both pairs and the arguments to the comparison function match in type. 656 656 657 657 Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag-structures}. … … 815 815 \subsection{Member Access} 816 816 817 It is also possible to access multiple fields from a single expression using a \newterm{member-access}.817 It is also possible to access multiple members from a single expression using a \newterm{member-access}. 818 818 The result is a single tuple-valued expression whose type is the tuple of the types of the members, \eg: 819 819 \begin{cfa} … … 1020 1020 \begin{cfa} 1021 1021 forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 { 1022 T0 field_0; T1 field_1; $\C{// generated before the first 2-tuple}$1022 T0 member_0; T1 member_1; $\C{// generated before the first 2-tuple}$ 1023 1023 }; 1024 1024 _tuple2(int, int) f() { 1025 1025 _tuple2(double, double) x; 1026 1026 forall( dtype T0, dtype T1, dtype T2 | sized(T0) | sized(T1) | sized(T2) ) struct _tuple3 { 1027 T0 field_0; T1 field_1; T2 field_2; $\C{// generated before the first 3-tuple}$1027 T0 member_0; T1 member_1; T2 member_2; $\C{// generated before the first 3-tuple}$ 1028 1028 }; 1029 1029 _tuple3(int, double, int) y; … … 1033 1033 1034 1034 \begin{comment} 1035 Since tuples are essentially structures, tuple indexing expressions are just fieldaccesses:1035 Since tuples are essentially structures, tuple indexing expressions are just member accesses: 1036 1036 \begin{cfa} 1037 1037 void f(int, [double, char]); … … 1047 1047 _tuple2(int, double) x; 1048 1048 1049 x. field_0+x.field_1;1050 printf("%d %g\n", x. field_0, x.field_1);1051 f(x. field_0, (_tuple2){ x.field_1, 'z' });1052 \end{cfa} 1053 Note that due to flattening, @x@ used in the argument position is converted into the list of its fields.1049 x.member_0+x.member_1; 1050 printf("%d %g\n", x.member_0, x.member_1); 1051 f(x.member_0, (_tuple2){ x.member_1, 'z' }); 1052 \end{cfa} 1053 Note that due to flattening, @x@ used in the argument position is converted into the list of its members. 1054 1054 In the call to @f@, the second and third argument components are structured into a tuple argument. 1055 1055 Similarly, tuple member expressions are recursively expanded into a list of member access expressions. … … 1083 1083 1084 1084 The various kinds of tuple assignment, constructors, and destructors generate GNU C statement expressions. 1085 A variable is generated to store the value produced by a statement expression, since its fields may need to be constructed with a non-trivial constructor and it may need to be referred to multiple time, \eg in a unique expression.1085 A variable is generated to store the value produced by a statement expression, since its members may need to be constructed with a non-trivial constructor and it may need to be referred to multiple time, \eg in a unique expression. 1086 1086 The use of statement expressions allows the translator to arbitrarily generate additional temporary variables as needed, but binds the implementation to a non-standard extension of the C language. 1087 1087 However, there are other places where the \CFA translator makes use of GNU C extensions, such as its use of nested functions, so this restriction is not new. … … 1493 1493 1494 1494 Heterogeneous data is often aggregated into a structure/union. 1495 To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate field-qualification by opening a scope containing the fieldidentifiers.1495 To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate member-qualification by opening a scope containing the member identifiers. 1496 1496 \begin{cquote} 1497 1497 \vspace*{-\baselineskip}%??? … … 1530 1530 The type must be an aggregate type. 1531 1531 (Enumerations are already opened.) 1532 The object is the implicit qualifier for the open structure- fields.1532 The object is the implicit qualifier for the open structure-members. 1533 1533 1534 1534 All expressions in the expression list are open in parallel within the compound statement, which is different from Pascal, which nests the openings from left to right. 1535 The difference between parallel and nesting occurs for fields with the same name and type:1536 \begin{cfa} 1537 struct S { int `i`; int j; double m; } s, w; 1535 The difference between parallel and nesting occurs for members with the same name and type: 1536 \begin{cfa} 1537 struct S { int `i`; int j; double m; } s, w; $\C{// member i has same type in structure types S and T}$ 1538 1538 struct T { int `i`; int k; int m; } t, w; 1539 with ( s, t ) { 1539 with ( s, t ) { $\C{// open structure variables s and t in parallel}$ 1540 1540 j + k; $\C{// unambiguous, s.j + t.k}$ 1541 1541 m = 5.0; $\C{// unambiguous, s.m = 5.0}$ … … 1549 1549 For parallel semantics, both @s.i@ and @t.i@ are visible, so @i@ is ambiguous without qualification; 1550 1550 for nested semantics, @t.i@ hides @s.i@, so @i@ implies @t.i@. 1551 \CFA's ability to overload variables means fields with the same name but different types are automatically disambiguated, eliminating most qualification when opening multiple aggregates.1551 \CFA's ability to overload variables means members with the same name but different types are automatically disambiguated, eliminating most qualification when opening multiple aggregates. 1552 1552 Qualification or a cast is used to disambiguate. 1553 1553 … … 1555 1555 \begin{cfa} 1556 1556 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ 1557 `s.i = i;` j = 3; m = 5.5; $\C{// initialize fields}$1557 `s.i = i;` j = 3; m = 5.5; $\C{// initialize members}$ 1558 1558 } 1559 1559 \end{cfa} … … 1659 1659 \lstMakeShortInline@% 1660 1660 \end{cquote} 1661 The only exception is bit 1661 The only exception is bit-field specification, which always appear to the right of the base type. 1662 1662 % Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a function parameter. 1663 1663 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. … … 1715 1715 // pointer to array of 5 doubles 1716 1716 1717 // common bit 1717 // common bit-field syntax 1718 1718 1719 1719 … … 1911 1911 \subsection{Type Nesting} 1912 1912 1913 Nested types provide a mechanism to organize associated types and refactor a subset of fields into a named aggregate (\eg sub-aggregates @name@, @address@, @department@, within aggregate @employe@).1913 Nested types provide a mechanism to organize associated types and refactor a subset of members into a named aggregate (\eg sub-aggregates @name@, @address@, @department@, within aggregate @employe@). 1914 1914 Java nested types are dynamic (apply to objects), \CC are static (apply to the \lstinline[language=C++]@class@), and C hoists (refactors) nested types into the enclosing scope, meaning there is no need for type qualification. 1915 1915 Since \CFA in not object-oriented, adopting dynamic scoping does not make sense; 1916 instead \CFA adopts \CC static nesting, using the field-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@'' (see Figure~\ref{f:TypeNestingQualification}).1916 instead \CFA adopts \CC static nesting, using the member-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@'' (see Figure~\ref{f:TypeNestingQualification}). 1917 1917 \begin{figure} 1918 1918 \centering … … 2005 2005 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}. 2006 2006 \begin{cfa} 2007 struct VLA { int len, * data; }; $\C{// variable length array of integers}$2008 void ?{}( VLA & vla ) with ( vla ) { len = 10; data = alloc( len); } $\C{// default constructor}$2007 struct VLA { int size, * data; }; $\C{// variable length array of integers}$ 2008 void ?{}( VLA & vla ) with ( vla ) { size = 10; data = alloc( size ); } $\C{// default constructor}$ 2009 2009 void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$ 2010 2010 { … … 2013 2013 \end{cfa} 2014 2014 @VLA@ is a \newterm{managed type}\footnote{ 2015 A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a fieldof a managed type.2015 A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a member of a managed type. 2016 2016 A managed type is implicitly constructed at allocation and destructed at deallocation to ensure proper interaction with runtime resources, in this case, the @data@ array in the heap. 2017 2017 For details of the code-generation placement of implicit constructor and destructor calls among complex executable statements see~\cite[\S~2.2]{Schluntz17}. … … 2019 2019 \CFA also provides syntax for \newterm{initialization} and \newterm{copy}: 2020 2020 \begin{cfa} 2021 void ?{}( VLA & vla, int size, char fill ) with ( vla) { $\C{// initialization}$2022 len = size; data = alloc( len, fill );2021 void ?{}( VLA & vla, int size, char fill = '\0' ) { $\C{// initialization}$ 2022 vla.[ size, data ] = [ size, alloc( size, fill ) ]; 2023 2023 } 2024 2024 void ?{}( VLA & vla, VLA other ) { $\C{// copy, shallow}$ 2025 vla .len = other.len; vla.data = other.data;2025 vla = other; 2026 2026 } 2027 2027 \end{cfa} … … 2036 2036 2037 2037 \CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC. 2038 Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of member fields in user-defined constructors and reuse of existing storage allocations.2038 Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of members in user-defined constructors and reuse of existing storage allocations. 2039 2039 Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls: 2040 2040 \begin{cfa} … … 2048 2048 y{ x }; $\C{// reallocate y, points to x}$ 2049 2049 x{}; $\C{// reallocate x, not pointing to y}$ 2050 // ^z{}; ^y{}; ^x{}; 2051 } 2050 } // ^z{}; ^y{}; ^x{}; 2052 2051 \end{cfa} 2053 2052 … … 2060 2059 For compatibility with C, a copy constructor from the first union member type is also defined. 2061 2060 For @struct@ types, each of the four functions are implicitly defined to call their corresponding functions on each member of the struct. 2062 To better simulate the behaviour of C initializers, a set of \newterm{ fieldconstructors} is also generated for structures.2061 To better simulate the behaviour of C initializers, a set of \newterm{member constructors} is also generated for structures. 2063 2062 A constructor is generated for each non-empty prefix of a structure's member-list to copy-construct the members passed as parameters and default-construct the remaining members. 2064 To allow users to limit the set of constructors available for a type, when a user declares any constructor or destructor, the corresponding generated function and all fieldconstructors for that type are hidden from expression resolution;2063 To allow users to limit the set of constructors available for a type, when a user declares any constructor or destructor, the corresponding generated function and all member constructors for that type are hidden from expression resolution; 2065 2064 similarly, the generated default constructor is hidden upon declaration of any constructor. 2066 2065 These semantics closely mirror the rule for implicit declaration of constructors in \CC\cite[p.~186]{ANSI98:C++}. … … 2740 2739 2741 2740 \section{Related Work} 2741 \label{s:RelatedWork} 2742 2742 2743 2743 … … 2793 2793 C provides variadic functions through @va_list@ objects, but the programmer is responsible for managing the number of arguments and their types, so the mechanism is type unsafe. 2794 2794 KW-C~\cite{Buhr94a}, a predecessor of \CFA, introduced tuples to C as an extension of the C syntax, taking much of its inspiration from SETL. 2795 The main contributions of that work were adding MRVF, tuple mass and multiple assignment, and record- fieldaccess.2795 The main contributions of that work were adding MRVF, tuple mass and multiple assignment, and record-member access. 2796 2796 \CCeleven introduced @std::tuple@ as a library variadic template structure. 2797 2797 Tuples are a generalization of @std::pair@, in that they allow for arbitrary length, fixed-size aggregation of heterogeneous values. -
src/CodeGen/CodeGenerator.cc
r96812c0 r054514d 119 119 120 120 string CodeGenerator::mangleName( DeclarationWithType * decl ) { 121 if ( pretty ) return decl->get_name(); 122 if ( decl->get_mangleName() != "" ) { 121 // GCC builtins should always be printed unmangled 122 if ( pretty || decl->linkage.is_gcc_builtin ) return decl->name; 123 if ( decl->mangleName != "" ) { 123 124 // need to incorporate scope level in order to differentiate names for destructors 124 125 return decl->get_scopedMangleName(); 125 126 } else { 126 return decl-> get_name();127 return decl->name; 127 128 } // if 128 129 } -
src/Common/Heap.cc
r96812c0 r054514d 30 30 #else 31 31 struct StatBlock { 32 const char * name = nullptr; 33 size_t mallocs = 0; 34 size_t frees = 0; 32 const char * name = nullptr; ///< Name of this pass 33 size_t mallocs = 0; ///< Allocations in this pass 34 size_t frees = 0; ///< Frees in this pass 35 size_t n_allocs = 0; ///< Current number of live allocations 36 size_t peak_allocs = 0; ///< Peak number of live allocations this pass 35 37 }; 36 38 37 StatBlock passes[100] = {{ "Pre-Parse", 0, 0 }};39 StatBlock passes[100] = {{ "Pre-Parse", 0, 0, 0, 0 }}; 38 40 const size_t passes_size = sizeof(passes) / sizeof(passes[0]); 39 41 size_t passes_cnt = 1; … … 43 45 passes[passes_cnt].mallocs = 0; 44 46 passes[passes_cnt].frees = 0; 47 passes[passes_cnt].n_allocs 48 = passes[passes_cnt].peak_allocs 49 = passes[passes_cnt-1].n_allocs; 45 50 passes_cnt++; 46 51 … … 55 60 } 56 61 57 void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees ) {62 void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees, size_t overall_peak) { 58 63 std::cerr << std::setw(nc) << stat.name; 59 64 std::cerr << " | "; 60 65 61 print(stat.mallocs, total_mallocs); 62 print(stat.frees , total_frees ); 66 print(stat.mallocs, total_mallocs); 67 print(stat.frees, total_frees ); 68 print(stat.peak_allocs, overall_peak ); 63 69 std::cerr << "\n"; 64 70 } … … 75 81 size_t total_mallocs = 0; 76 82 size_t total_frees = 0; 83 size_t overall_peak = 0; 77 84 for(size_t i = 0; i < passes_cnt; i++) { 78 85 nc = std::max(nc, std::strlen(passes[i].name)); 79 86 total_mallocs += passes[i].mallocs; 80 87 total_frees += passes[i].frees; 81 } 82 size_t nct = nc + 44; 88 overall_peak = std::max(overall_peak, passes[i].peak_allocs); 89 } 90 size_t nct = nc + 65; 83 91 84 92 const char * const title = "Heap Usage Statistic"; … … 88 96 print('-', nct); 89 97 std::cerr << std::setw(nc) << "Pass"; 90 std::cerr << " | Malloc Count | Free Count | " << std::endl;98 std::cerr << " | Malloc Count | Free Count | Peak Allocs |" << std::endl; 91 99 92 100 print('-', nct); 93 101 for(size_t i = 0; i < passes_cnt; i++) { 94 print(passes[i], nc, total_mallocs, total_frees );102 print(passes[i], nc, total_mallocs, total_frees, overall_peak); 95 103 } 96 104 print('-', nct); 97 print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees); 105 print({"Sum", total_mallocs, total_frees, 0, overall_peak}, 106 nc, total_mallocs, total_frees, overall_peak); 98 107 99 108 } … … 158 167 void * malloc( size_t size ) { 159 168 static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr )); 160 if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++; 169 if( passes_cnt > 0 ) { 170 passes[passes_cnt - 1].mallocs++; 171 passes[passes_cnt - 1].n_allocs++; 172 passes[passes_cnt - 1].peak_allocs 173 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 174 } 161 175 return __malloc( size ); 162 176 } … … 164 178 void free( void * ptr ) { 165 179 static auto __free = reinterpret_cast<void (*)(void *)>(interpose_symbol( "free", nullptr )); 166 if( passes_cnt > 0 ) passes[passes_cnt - 1].frees++; 180 if( passes_cnt > 0 ) { 181 passes[passes_cnt - 1].frees++; 182 passes[passes_cnt - 1].n_allocs--; 183 } 167 184 return __free( ptr ); 168 185 } … … 170 187 void * calloc( size_t nelem, size_t size ) { 171 188 static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr )); 172 if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++; 189 if( passes_cnt > 0 ) { 190 passes[passes_cnt - 1].mallocs++; 191 passes[passes_cnt - 1].n_allocs++; 192 passes[passes_cnt - 1].peak_allocs 193 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 194 } 173 195 return __calloc( nelem, size ); 174 196 } -
src/Concurrency/Keywords.cc
r96812c0 r054514d 191 191 void postvisit( StructDecl * decl ); 192 192 193 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );193 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first ); 194 194 void validate( DeclarationWithType * ); 195 195 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &); … … 441 441 void MutexKeyword::postvisit(FunctionDecl* decl) { 442 442 443 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl ); 443 bool first = false; 444 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first ); 444 445 if( mutexArgs.empty() ) return; 445 446 446 if( CodeGen::isConstructor(decl->name) ) SemanticError( decl, "constructors cannot have mutex parameters" );447 if( CodeGen::isConstructor(decl->name) && first ) SemanticError( decl, "constructors cannot have mutex parameters" ); 447 448 448 449 bool isDtor = CodeGen::isDestructor( decl->name ); … … 484 485 } 485 486 486 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {487 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) { 487 488 std::list<DeclarationWithType*> mutexArgs; 488 489 490 bool once = true; 489 491 for( auto arg : decl->get_functionType()->get_parameters()) { 490 492 //Find mutex arguments 491 493 Type* ty = arg->get_type(); 492 494 if( ! ty->get_mutex() ) continue; 495 496 if(once) {first = true;} 497 once = false; 493 498 494 499 //Append it to the list -
src/Parser/LinkageSpec.h
r96812c0 r054514d 27 27 Overrideable = 1 << 2, 28 28 Builtin = 1 << 3, 29 GccBuiltin = 1 << 4, 29 30 30 NoOfSpecs = 1 << 4,31 NoOfSpecs = 1 << 5, 31 32 }; 32 33 … … 38 39 bool is_overridable : 1; 39 40 bool is_builtin : 1; 41 bool is_gcc_builtin : 1; 40 42 }; 41 43 constexpr Spec( unsigned int val ) : val( val ) {} … … 61 63 inline bool isOverridable( Spec spec ) { return spec.is_overridable; } 62 64 inline bool isBuiltin( Spec spec ) { return spec.is_builtin; } 65 inline bool isGccBuiltin( Spec spec ) { return spec.is_gcc_builtin; } 63 66 64 67 // Pre-defined flag combinations: … … 72 75 constexpr Spec const AutoGen = { Mangle | Generate | Overrideable }; 73 76 // gcc internal 74 constexpr Spec const Compiler = { Builtin };77 constexpr Spec const Compiler = { Mangle | Builtin | GccBuiltin }; 75 78 // mangled builtins 76 79 constexpr Spec const BuiltinCFA = { Mangle | Generate | Builtin }; -
src/Parser/TypeData.cc
r96812c0 r054514d 575 575 576 576 case DeclarationNode::Int128: 577 ret = td->signedness == 1? BasicType::UnsignedInt128 : BasicType::SignedInt128;577 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128; 578 578 if ( td->length != DeclarationNode::NoLength ) { 579 579 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); … … 599 599 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); 600 600 } // if 601 if ( td->basictype == DeclarationNode::Float&& td->length == DeclarationNode::Long ) {601 if ( td->basictype != DeclarationNode::Double && td->length == DeclarationNode::Long ) { 602 602 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); 603 603 } // if … … 605 605 const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble; 606 606 } // if 607 608 if ( td->basictype == DeclarationNode::Float80 || td->basictype == DeclarationNode::Float128 ) { 609 if ( td->complextype != DeclarationNode::NoComplexType ) { 610 genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype ); 611 } 612 if ( td->basictype == DeclarationNode::Float80 ) ret = BasicType::Float80; 613 else ret = BasicType::Float128; 614 break; 615 } 607 616 608 617 ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ]; -
src/Parser/parser.yy
r96812c0 r054514d 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 22 08:41:57201813 // Update Count : 33 5312 // Last Modified On : Mon May 28 17:01:36 2018 13 // Update Count : 3383 14 14 // 15 15 … … 326 326 %type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr 327 327 328 %type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ type_list_opt328 %type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt 329 329 330 330 %type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier … … 852 852 // '[' ']' 853 853 // { $$ = new ExpressionNode( build_tuple() ); } 854 // '[' push assignment_expression pop ']'854 // | '[' push assignment_expression pop ']' 855 855 // { $$ = new ExpressionNode( build_tuple( $3 ) ); } 856 '[' ',' tuple_expression_list']'857 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $ 3) ) ); }858 | '[' assignment_expression ',' tuple_expression_list']'859 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)$ 2->set_last( $4) ) ); }856 '[' push ',' tuple_expression_list pop ']' 857 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $4 ) ) ); } 858 | '[' push assignment_expression ',' tuple_expression_list pop ']' 859 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)$3->set_last( $5 ) ) ); } 860 860 ; 861 861 … … 883 883 labeled_statement 884 884 | compound_statement 885 | expression_statement { $$ = $1; }885 | expression_statement 886 886 | selection_statement 887 887 | iteration_statement … … 1200 1200 type_specifier_nobody 1201 1201 | type_specifier_nobody declarator 1202 { 1203 $$ = $2->addType( $1 ); 1204 } 1202 { $$ = $2->addType( $1 ); } 1205 1203 | type_specifier_nobody variable_abstract_declarator 1206 1204 { $$ = $2->addType( $1 ); } 1207 1205 | cfa_abstract_declarator_tuple no_attr_identifier // CFA 1208 { 1209 $$ = $1->addName( $2 ); 1210 } 1206 { $$ = $1->addName( $2 ); } 1211 1207 | cfa_abstract_declarator_tuple // CFA 1212 1208 ; … … 1286 1282 1287 1283 declaration_list_opt: // used at beginning of switch statement 1288 pop 1284 pop // empty 1289 1285 { $$ = nullptr; } 1290 1286 | declaration_list … … 1321 1317 1322 1318 local_label_list: // GCC, local label 1323 no_attr_identifier_or_type_name {}1324 | local_label_list ',' no_attr_identifier_or_type_name {}1319 no_attr_identifier_or_type_name 1320 | local_label_list ',' no_attr_identifier_or_type_name 1325 1321 ; 1326 1322 … … 1385 1381 | declaration_qualifier_list type_qualifier_list cfa_function_specifier 1386 1382 { $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); } 1387 | cfa_function_declaration ',' identifier_or_type_name '(' cfa_parameter_type_list_opt')'1383 | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' 1388 1384 { 1389 1385 // Append the return type at the start (left-hand-side) to each identifier in the list. 1390 1386 DeclarationNode * ret = new DeclarationNode; 1391 1387 ret->type = maybeClone( $1->type->base ); 1392 $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $ 5, nullptr ) );1388 $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) ); 1393 1389 } 1394 1390 ; 1395 1391 1396 1392 cfa_function_specifier: // CFA 1397 // '[' ']' identifier_or_type_name '(' push cfa_parameter_ type_list_opt pop ')' // S/R conflict1393 // '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict 1398 1394 // { 1399 1395 // $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true ); 1400 1396 // } 1401 // '[' ']' identifier '(' push cfa_parameter_ type_list_opt pop ')'1397 // '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')' 1402 1398 // { 1403 1399 // typedefTable.setNextIdentifier( *$5 ); 1404 1400 // $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true ); 1405 1401 // } 1406 // | '[' ']' TYPEDEFname '(' push cfa_parameter_ type_list_opt pop ')'1402 // | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')' 1407 1403 // { 1408 1404 // typedefTable.setNextIdentifier( *$5 ); … … 1412 1408 // identifier_or_type_name must be broken apart because of the sequence: 1413 1409 // 1414 // '[' ']' identifier_or_type_name '(' cfa_parameter_ type_list_opt ')'1410 // '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')' 1415 1411 // '[' ']' type_specifier 1416 1412 // 1417 1413 // type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be 1418 1414 // flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name. 1419 cfa_abstract_tuple identifier_or_type_name '(' cfa_parameter_type_list_opt')'1415 cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' 1420 1416 // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator). 1421 { $$ = DeclarationNode::newFunction( $2, $1, $ 4, 0 ); }1422 | cfa_function_return identifier_or_type_name '(' cfa_parameter_type_list_opt')'1423 { $$ = DeclarationNode::newFunction( $2, $1, $ 4, 0 ); }1417 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); } 1418 | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' 1419 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); } 1424 1420 ; 1425 1421 1426 1422 cfa_function_return: // CFA 1427 '[' cfa_parameter_list ']' 1428 { $$ = DeclarationNode::newTuple( $2 ); } 1429 | '[' cfa_parameter_list ',' cfa_abstract_parameter_list ']' 1430 // To obtain LR(1 ), the last cfa_abstract_parameter_list is added into this flattened rule to lookahead to the 1431 // ']'. 1432 { $$ = DeclarationNode::newTuple( $2->appendList( $4 ) ); } 1423 '[' push cfa_parameter_list pop ']' 1424 { $$ = DeclarationNode::newTuple( $3 ); } 1425 | '[' push cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ']' 1426 // To obtain LR(1 ), the last cfa_abstract_parameter_list is added into this flattened rule to lookahead to the ']'. 1427 { $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); } 1433 1428 ; 1434 1429 … … 1604 1599 1605 1600 forall: 1606 FORALL '(' 1607 { 1608 typedefTable.enterScope(); 1609 } 1610 type_parameter_list ')' // CFA 1611 { 1612 typedefTable.leaveScope(); 1613 $$ = DeclarationNode::newForall( $4 ); 1614 } 1601 FORALL '(' push type_parameter_list pop ')' // CFA 1602 { $$ = DeclarationNode::newForall( $4 ); } 1615 1603 ; 1616 1604 … … 1980 1968 ; 1981 1969 1982 cfa_parameter_ type_list_opt: // CFA, abstract + real1970 cfa_parameter_ellipsis_list_opt: // CFA, abstract + real 1983 1971 // empty 1984 1972 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); } … … 1987 1975 | cfa_abstract_parameter_list 1988 1976 | cfa_parameter_list 1989 | cfa_parameter_list ','cfa_abstract_parameter_list1990 { $$ = $1->appendList( $ 3); }1991 | cfa_abstract_parameter_list ','ELLIPSIS1977 | cfa_parameter_list pop ',' push cfa_abstract_parameter_list 1978 { $$ = $1->appendList( $5 ); } 1979 | cfa_abstract_parameter_list pop ',' push ELLIPSIS 1992 1980 { $$ = $1->addVarArgs(); } 1993 | cfa_parameter_list ','ELLIPSIS1981 | cfa_parameter_list pop ',' push ELLIPSIS 1994 1982 { $$ = $1->addVarArgs(); } 1995 1983 ; … … 1999 1987 // factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'. 2000 1988 cfa_parameter_declaration 2001 | cfa_abstract_parameter_list ','cfa_parameter_declaration2002 { $$ = $1->appendList( $ 3); }2003 | cfa_parameter_list ','cfa_parameter_declaration2004 { $$ = $1->appendList( $ 3); }2005 | cfa_parameter_list ',' cfa_abstract_parameter_list ','cfa_parameter_declaration2006 { $$ = $1->appendList( $ 3 )->appendList( $5); }1989 | cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration 1990 { $$ = $1->appendList( $5 ); } 1991 | cfa_parameter_list pop ',' push cfa_parameter_declaration 1992 { $$ = $1->appendList( $5 ); } 1993 | cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration 1994 { $$ = $1->appendList( $5 )->appendList( $9 ); } 2007 1995 ; 2008 1996 2009 1997 cfa_abstract_parameter_list: // CFA, new & old style abstract 2010 1998 cfa_abstract_parameter_declaration 2011 | cfa_abstract_parameter_list ','cfa_abstract_parameter_declaration2012 { $$ = $1->appendList( $ 3); }1999 | cfa_abstract_parameter_list pop ',' push cfa_abstract_parameter_declaration 2000 { $$ = $1->appendList( $5 ); } 2013 2001 ; 2014 2002 … … 2159 2147 '.' no_attr_identifier // C99, field name 2160 2148 { $$ = new ExpressionNode( build_varref( $2 ) ); } 2161 | '[' assignment_expression ']'// C99, single array element2149 | '[' push assignment_expression pop ']' // C99, single array element 2162 2150 // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple. 2163 { $$ = $2; }2164 | '[' subrange ']' // CFA, multiple array elements2165 { $$ = $2; }2166 | '[' constant_expression ELLIPSIS constant_expression ']' // GCC, multiple array elements2167 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild< Expression >( $2 ), maybeMoveBuild< Expression >( $4 ) ) ); }2168 | '.' '[' field_list ']' // CFA, tuple field selector2169 2151 { $$ = $3; } 2152 | '[' push subrange pop ']' // CFA, multiple array elements 2153 { $$ = $3; } 2154 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements 2155 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild< Expression >( $3 ), maybeMoveBuild< Expression >( $5 ) ) ); } 2156 | '.' '[' push field_list pop ']' // CFA, tuple field selector 2157 { $$ = $4; } 2170 2158 ; 2171 2159 … … 2238 2226 '|' no_attr_identifier_or_type_name '(' type_list ')' 2239 2227 { $$ = DeclarationNode::newTraitUse( $2, $4 ); } 2240 | '|' '{' push trait_declaration_list '}'2228 | '|' '{' push trait_declaration_list pop '}' 2241 2229 { $$ = $4; } 2242 | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list '}' '(' type_list ')'2230 | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' '(' type_list ')' 2243 2231 { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; } 2244 2232 ; … … 2286 2274 TRAIT no_attr_identifier_or_type_name '(' push type_parameter_list pop ')' '{' '}' 2287 2275 { $$ = DeclarationNode::newTrait( $2, $5, 0 ); } 2288 | TRAIT no_attr_identifier_or_type_name '(' push type_parameter_list pop ')' '{' 2289 { typedefTable.enterScope(); } 2290 trait_declaration_list '}' 2276 | TRAIT no_attr_identifier_or_type_name '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' 2291 2277 { $$ = DeclarationNode::newTrait( $2, $5, $10 ); } 2292 2278 ; … … 2294 2280 trait_declaration_list: // CFA 2295 2281 trait_declaration 2296 | trait_declaration_list p ush trait_declaration2297 { $$ = $1->appendList( $ 3); }2282 | trait_declaration_list pop push trait_declaration 2283 { $$ = $1->appendList( $4 ); } 2298 2284 ; 2299 2285 2300 2286 trait_declaration: // CFA 2301 cfa_trait_declaring_list pop';'2302 | trait_declaring_list pop';'2287 cfa_trait_declaring_list ';' 2288 | trait_declaring_list ';' 2303 2289 ; 2304 2290 2305 2291 cfa_trait_declaring_list: // CFA 2306 2292 cfa_variable_specifier 2307 { $$ = $1; }2308 2293 | cfa_function_specifier 2309 { $$ = $1; }2310 2294 | cfa_trait_declaring_list pop ',' push identifier_or_type_name 2311 2295 { $$ = $1->appendList( $1->cloneType( $5 ) ); } … … 2366 2350 } 2367 2351 | type_qualifier_list 2368 { 2369 if ( $1->type->forall ) xxx = forall = true; // remember generic type 2370 } 2352 { if ( $1->type->forall ) xxx = forall = true; } // remember generic type 2371 2353 push '{' external_definition_list '}' // CFA, namespace 2372 2354 { … … 2381 2363 } 2382 2364 | declaration_qualifier_list 2383 { 2384 if ( $1->type->forall ) xxx = forall = true; // remember generic type 2385 } 2365 { if ( $1->type->forall ) xxx = forall = true; } // remember generic type 2386 2366 push '{' external_definition_list '}' // CFA, namespace 2387 2367 { … … 2423 2403 // declaration must still have a type_specifier. OBSOLESCENT (see 1) 2424 2404 | function_declarator compound_statement 2425 { 2426 typedefTable.leaveScope(); 2427 $$ = $1->addFunctionBody( $2 ); 2428 } 2405 { $$ = $1->addFunctionBody( $2 ); } 2429 2406 | KR_function_declarator KR_declaration_list_opt compound_statement 2430 { 2431 typedefTable.leaveScope(); 2432 $$ = $1->addOldDeclList( $2 )->addFunctionBody( $3 ); 2433 } 2407 { $$ = $1->addOldDeclList( $2 )->addFunctionBody( $3 ); } 2434 2408 ; 2435 2409 … … 2444 2418 cfa_function_declaration with_clause_opt compound_statement // CFA 2445 2419 { 2446 typedefTable.leaveScope();2447 2420 // Add the function body to the last identifier in the function definition list, i.e., foo3: 2448 2421 // [const double] foo1(), foo2( int ), foo3( double ) { return 3.0; } … … 2453 2426 { 2454 2427 rebindForall( $1, $2 ); 2455 typedefTable.leaveScope();2456 2428 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 ); 2457 2429 } … … 2459 2431 { 2460 2432 rebindForall( $1, $2 ); 2461 typedefTable.leaveScope();2462 2433 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 ); 2463 2434 } 2464 2435 // handles default int return type, OBSOLESCENT (see 1) 2465 2436 | type_qualifier_list function_declarator with_clause_opt compound_statement 2466 { 2467 typedefTable.leaveScope(); 2468 $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); 2469 } 2437 { $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); } 2470 2438 // handles default int return type, OBSOLESCENT (see 1) 2471 2439 | declaration_qualifier_list function_declarator with_clause_opt compound_statement 2472 { 2473 typedefTable.leaveScope(); 2474 $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); 2475 } 2440 { $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); } 2476 2441 // handles default int return type, OBSOLESCENT (see 1) 2477 2442 | declaration_qualifier_list type_qualifier_list function_declarator with_clause_opt compound_statement 2478 { 2479 typedefTable.leaveScope(); 2480 $$ = $3->addFunctionBody( $5, $4 )->addQualifiers( $2 )->addQualifiers( $1 ); 2481 } 2443 { $$ = $3->addFunctionBody( $5, $4 )->addQualifiers( $2 )->addQualifiers( $1 ); } 2482 2444 2483 2445 // Old-style K&R function definition, OBSOLESCENT (see 4) … … 2485 2447 { 2486 2448 rebindForall( $1, $2 ); 2487 typedefTable.leaveScope();2488 2449 $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addType( $1 ); 2489 2450 } 2490 2451 // handles default int return type, OBSOLESCENT (see 1) 2491 2452 | type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement 2492 { 2493 typedefTable.leaveScope(); 2494 $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); 2495 } 2453 { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); } 2496 2454 // handles default int return type, OBSOLESCENT (see 1) 2497 2455 | declaration_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement 2498 { 2499 typedefTable.leaveScope(); 2500 $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); 2501 } 2456 { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); } 2502 2457 // handles default int return type, OBSOLESCENT (see 1) 2503 2458 | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement 2504 { 2505 typedefTable.leaveScope(); 2506 $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 ); 2507 } 2459 { $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 ); } 2508 2460 ; 2509 2461 … … 2702 2654 paren_identifier '(' identifier_list ')' // function_declarator handles empty parameter 2703 2655 { $$ = $1->addIdList( $3 ); } 2704 | '(' KR_function_ptr ')' '(' p arameter_type_list_opt')'2705 { $$ = $2->addParamList( $ 5); }2656 | '(' KR_function_ptr ')' '(' push parameter_type_list_opt pop ')' 2657 { $$ = $2->addParamList( $6 ); } 2706 2658 | '(' KR_function_no_ptr ')' // redundant parenthesis 2707 2659 { $$ = $2; } … … 2821 2773 2822 2774 identifier_parameter_function: 2823 paren_identifier '(' p arameter_type_list_opt ')'// empty parameter list OBSOLESCENT (see 3)2824 { $$ = $1->addParamList( $ 3); }2825 | '(' identifier_parameter_ptr ')' '(' p arameter_type_list_opt')' // empty parameter list OBSOLESCENT (see 3)2826 { $$ = $2->addParamList( $ 5); }2775 paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2776 { $$ = $1->addParamList( $4 ); } 2777 | '(' identifier_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2778 { $$ = $2->addParamList( $6 ); } 2827 2779 | '(' identifier_parameter_function ')' // redundant parenthesis 2828 2780 { $$ = $2; } … … 2874 2826 2875 2827 type_parameter_function: 2876 typedef '(' p arameter_type_list_opt ')'// empty parameter list OBSOLESCENT (see 3)2877 { $$ = $1->addParamList( $ 3); }2878 | '(' type_parameter_ptr ')' '(' p arameter_type_list_opt')' // empty parameter list OBSOLESCENT (see 3)2879 { $$ = $2->addParamList( $ 5); }2828 typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2829 { $$ = $1->addParamList( $4 ); } 2830 | '(' type_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2831 { $$ = $2->addParamList( $6 ); } 2880 2832 ; 2881 2833 … … 2924 2876 2925 2877 abstract_function: 2926 '(' p arameter_type_list_opt ')'// empty parameter list OBSOLESCENT (see 3)2927 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $ 2, nullptr ); }2928 | '(' abstract_ptr ')' '(' p arameter_type_list_opt')' // empty parameter list OBSOLESCENT (see 3)2929 { $$ = $2->addParamList( $ 5); }2878 '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2879 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $3, nullptr ); } 2880 | '(' abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2881 { $$ = $2->addParamList( $6 ); } 2930 2882 | '(' abstract_function ')' // redundant parenthesis 2931 2883 { $$ = $2; } … … 2942 2894 2943 2895 multi_array_dimension: 2944 '[' assignment_expression']'2945 { $$ = DeclarationNode::newArray( $ 2, 0, false ); }2946 | '[' '*' ']'// C992896 '[' push assignment_expression pop ']' 2897 { $$ = DeclarationNode::newArray( $3, 0, false ); } 2898 | '[' push '*' pop ']' // C99 2947 2899 { $$ = DeclarationNode::newVarArray( 0 ); } 2948 | multi_array_dimension '[' assignment_expression']'2949 { $$ = $1->addArray( DeclarationNode::newArray( $ 3, 0, false ) ); }2950 | multi_array_dimension '[' '*' ']'// C992900 | multi_array_dimension '[' push assignment_expression pop ']' 2901 { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); } 2902 | multi_array_dimension '[' push '*' pop ']' // C99 2951 2903 { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); } 2952 2904 ; … … 3015 2967 3016 2968 abstract_parameter_function: 3017 '(' p arameter_type_list_opt ')'// empty parameter list OBSOLESCENT (see 3)3018 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $ 2, nullptr ); }3019 | '(' abstract_parameter_ptr ')' '(' p arameter_type_list_opt')' // empty parameter list OBSOLESCENT (see 3)3020 { $$ = $2->addParamList( $ 5); }2969 '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2970 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $3, nullptr ); } 2971 | '(' abstract_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 2972 { $$ = $2->addParamList( $6 ); } 3021 2973 | '(' abstract_parameter_function ')' // redundant parenthesis 3022 2974 { $$ = $2; } … … 3039 2991 '[' ']' 3040 2992 { $$ = DeclarationNode::newArray( 0, 0, false ); } 3041 // multi_array_dimension handles the '[' '*' ']' case3042 | '[' type_qualifier_list '*' ']'// remaining C993043 { $$ = DeclarationNode::newVarArray( $ 2); }3044 | '[' type_qualifier_list']'3045 { $$ = DeclarationNode::newArray( 0, $ 2, false ); }3046 // multi_array_dimension handles the '[' assignment_expression ']' case3047 | '[' type_qualifier_list assignment_expression']'3048 { $$ = DeclarationNode::newArray( $ 3, $2, false ); }3049 | '[' STATIC type_qualifier_list_opt assignment_expression']'3050 { $$ = DeclarationNode::newArray( $ 4, $3, true ); }3051 | '[' type_qualifier_list STATIC assignment_expression']'3052 { $$ = DeclarationNode::newArray( $ 4, $2, true ); }2993 // multi_array_dimension handles the '[' '*' ']' case 2994 | '[' push type_qualifier_list '*' pop ']' // remaining C99 2995 { $$ = DeclarationNode::newVarArray( $3 ); } 2996 | '[' push type_qualifier_list pop ']' 2997 { $$ = DeclarationNode::newArray( 0, $3, false ); } 2998 // multi_array_dimension handles the '[' assignment_expression ']' case 2999 | '[' push type_qualifier_list assignment_expression pop ']' 3000 { $$ = DeclarationNode::newArray( $4, $3, false ); } 3001 | '[' push STATIC type_qualifier_list_opt assignment_expression pop ']' 3002 { $$ = DeclarationNode::newArray( $5, $4, true ); } 3003 | '[' push type_qualifier_list STATIC assignment_expression pop ']' 3004 { $$ = DeclarationNode::newArray( $5, $3, true ); } 3053 3005 ; 3054 3006 … … 3094 3046 3095 3047 variable_abstract_function: 3096 '(' variable_abstract_ptr ')' '(' p arameter_type_list_opt')' // empty parameter list OBSOLESCENT (see 3)3097 { $$ = $2->addParamList( $ 5); }3048 '(' variable_abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3049 { $$ = $2->addParamList( $6 ); } 3098 3050 | '(' variable_abstract_function ')' // redundant parenthesis 3099 3051 { $$ = $2; } … … 3158 3110 3159 3111 cfa_array_parameter_1st_dimension: 3160 '[' type_qualifier_list '*' ']'// remaining C993161 { $$ = DeclarationNode::newVarArray( $ 2); }3162 | '[' type_qualifier_list assignment_expression']'3163 { $$ = DeclarationNode::newArray( $ 3, $2, false ); }3164 | '[' declaration_qualifier_list assignment_expression']'3112 '[' push type_qualifier_list '*' pop ']' // remaining C99 3113 { $$ = DeclarationNode::newVarArray( $3 ); } 3114 | '[' push type_qualifier_list assignment_expression pop ']' 3115 { $$ = DeclarationNode::newArray( $4, $3, false ); } 3116 | '[' push declaration_qualifier_list assignment_expression pop ']' 3165 3117 // declaration_qualifier_list must be used because of shift/reduce conflict with 3166 3118 // assignment_expression, so a semantic check is necessary to preclude them as a type_qualifier cannot 3167 3119 // appear in this context. 3168 { $$ = DeclarationNode::newArray( $ 3, $2, true ); }3169 | '[' declaration_qualifier_list type_qualifier_list assignment_expression']'3170 { $$ = DeclarationNode::newArray( $ 4, $3->addQualifiers( $3 ), true ); }3120 { $$ = DeclarationNode::newArray( $4, $3, true ); } 3121 | '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']' 3122 { $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); } 3171 3123 ; 3172 3124 … … 3180 3132 // 3181 3133 // cfa_abstract_tuple identifier_or_type_name 3182 // '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ type_list_opt ')'3134 // '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')' 3183 3135 // 3184 3136 // since a function return type can be syntactically identical to a tuple type: … … 3237 3189 3238 3190 cfa_abstract_tuple: // CFA 3239 '[' cfa_abstract_parameter_list ']' 3240 { $$ = DeclarationNode::newTuple( $2 ); } 3191 '[' push cfa_abstract_parameter_list pop ']' 3192 { $$ = DeclarationNode::newTuple( $3 ); } 3193 | '[' push type_specifier_nobody ELLIPSIS ']' 3194 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; } 3195 | '[' push type_specifier_nobody ELLIPSIS constant_expression ']' 3196 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; } 3241 3197 ; 3242 3198 3243 3199 cfa_abstract_function: // CFA 3244 // '[' ']' '(' cfa_parameter_ type_list_opt ')'3200 // '[' ']' '(' cfa_parameter_ellipsis_list_opt ')' 3245 3201 // { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); } 3246 cfa_abstract_tuple '(' cfa_parameter_type_list_opt')'3247 { $$ = DeclarationNode::newFunction( nullptr, $1, $ 3, nullptr ); }3248 | cfa_function_return '(' cfa_parameter_type_list_opt')'3249 { $$ = DeclarationNode::newFunction( nullptr, $1, $ 3, nullptr ); }3202 cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')' 3203 { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); } 3204 | cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')' 3205 { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); } 3250 3206 ; 3251 3207 -
src/ResolvExpr/CommonType.cc
r96812c0 r054514d 176 176 } 177 177 178 static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES][ BasicType::NUMBER_OF_BASIC_TYPES ] =178 static const BasicType::Kind combinedType[][ BasicType::NUMBER_OF_BASIC_TYPES ] = 179 179 { 180 /* Bool Char SignedChar UnsignedChar ShortSignedInt ShortUnsignedInt SignedInt UnsignedInt LongSignedInt LongUnsignedInt LongLongSignedInt LongLongUnsignedInt Float Double LongDouble FloatComplex DoubleComplex LongDoubleComplex FloatImaginary DoubleImaginary LongDoubleImaginary SignedInt128 UnsignedInt128 */ 181 /* Bool */ { BasicType::Bool, BasicType::Char, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 182 /* Char */ { BasicType::Char, BasicType::Char, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 183 /* SignedChar */ { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 184 /* UnsignedChar */ { BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 185 /* ShortSignedInt */ { BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 186 /* ShortUnsignedInt */ { BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 187 /* SignedInt */ { BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 188 /* UnsignedInt */ { BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 189 /* LongSignedInt */ { BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 190 /* LongUnsignedInt */ { BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 191 /* LongLongSignedInt */ { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 192 /* LongLongUnsignedInt */ { BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 193 /* Float */ { BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Float, BasicType::Float, }, 194 /* Double */ { BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::LongDouble, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Double, BasicType::Double, }, 195 /* LongDouble */ { BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDouble, BasicType::LongDouble, }, 196 /* FloatComplex */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::FloatComplex, }, 197 /* DoubleComplex */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, }, 198 /* LongDoubleComplex */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, }, 199 /* FloatImaginary */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::FloatImaginary, BasicType::FloatImaginary, }, 200 /* DoubleImaginary */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::DoubleImaginary, BasicType::DoubleImaginary, }, 201 /* LongDoubleImaginary */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary }, 202 /* SignedInt128 */ { BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, }, 203 /* UnsignedInt128 */ { BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::UnsignedInt128, BasicType::UnsignedInt128, }, 180 /* Bool Char SignedChar UnsignedChar ShortSignedInt ShortUnsignedInt SignedInt UnsignedInt LongSignedInt LongUnsignedInt LongLongSignedInt LongLongUnsignedInt Float Double LongDouble FloatComplex DoubleComplex LongDoubleComplex FloatImaginary DoubleImaginary LongDoubleImaginary SignedInt128 UnsignedInt128 Float80 Float128 */ 181 /* Bool */ { BasicType::Bool, BasicType::Char, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 182 /* Char */ { BasicType::Char, BasicType::Char, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 183 /* SignedChar */ { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::SignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 184 /* UnsignedChar */ { BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::UnsignedChar, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 185 /* ShortSignedInt */ { BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortSignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 186 /* ShortUnsignedInt */ { BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::ShortUnsignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 187 /* SignedInt */ { BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::SignedInt, BasicType::UnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 188 /* UnsignedInt */ { BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 189 /* LongSignedInt */ { BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongSignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 190 /* LongUnsignedInt */ { BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 191 /* LongLongSignedInt */ { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongSignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 192 /* LongLongUnsignedInt */ { BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 }, 193 /* Float */ { BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Float, BasicType::Float, BasicType::Float80, BasicType::Float128 }, 194 /* Double */ { BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::Double, BasicType::LongDouble, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::Double, BasicType::Double, BasicType::Float80, BasicType::Float128 }, 195 /* LongDouble */ { BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDouble, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDouble, BasicType::LongDouble, BasicType::BasicType::LongDouble, BasicType::Float128 }, 196 /* FloatComplex */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, }, 197 /* DoubleComplex */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex }, 198 /* LongDoubleComplex */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, }, 199 /* FloatImaginary */ { BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::FloatImaginary, BasicType::FloatImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 200 /* DoubleImaginary */ { BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::DoubleImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::DoubleImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 201 /* LongDoubleImaginary */ { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, }, 202 /* SignedInt128 */ { BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::SignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::SignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, }, 203 /* UnsignedInt128 */ { BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::UnsignedInt128, BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, }, 204 /* Float80 */ { BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::LongDouble, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::Float80, BasicType::Float80, BasicType::Float80, BasicType::Float128 }, 205 /* Float128 */ { BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::Float128, BasicType::Float128, BasicType::Float128, BasicType::Float128 }, 204 206 }; 207 static_assert( 208 sizeof(combinedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES, 209 "Each basic type kind should have a corresponding row in the combined type matrix" 210 ); 205 211 206 212 CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) -
src/ResolvExpr/ConversionCost.cc
r96812c0 r054514d 230 230 */ 231 231 232 static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = { 233 /* Src \ Dest: Bool Char SChar UChar Short UShort Int UInt Long ULong LLong ULLong Float Double LDbl FCplex DCplex LDCplex FImag DImag LDImag I128, U128 */ 234 /* Bool */ { 0, 1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 12, 13, 14, 12, 13, 14, -1, -1, -1, 10, 11, }, 235 /* Char */ { -1, 0, -1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, }, 236 /* SChar */ { -1, -1, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, }, 237 /* UChar */ { -1, -1, -1, 0, 1, 2, 3, 4, 4, 5, 6, 7, 10, 11, 12, 10, 11, 12, -1, -1, -1, 8, 9, }, 238 /* Short */ { -1, -1, -1, -1, 0, 1, 2, 3, 3, 4, 5, 6, 9, 10, 11, 9, 10, 11, -1, -1, -1, 7, 8, }, 239 /* UShort */{ -1, -1, -1, -1, -1, 0, 1, 2, 2, 3, 4, 5, 8, 9, 10, 8, 9, 10, -1, -1, -1, 6, 7, }, 240 /* Int */ { -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 7, 8, 9, 7, 8, 9, -1, -1, -1, 5, 6, }, 241 /* UInt */ { -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, }, 242 /* Long */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, }, 243 /* ULong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 5, 6, 7, 5, 6, 7, -1, -1, -1, 3, 4, }, 244 /* LLong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 4, 5, 6, 4, 5, 6, -1, -1, -1, 2, 3, }, 245 /* ULLong */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 4, 5, 3, 4, 5, -1, -1, -1, 1, 2, }, 246 247 /* Float */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 1, 2, 3, -1, -1, -1, -1, -1, }, 248 /* Double */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 1, 2, -1, -1, -1, -1, -1, }, 249 /* LDbl */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1, -1, -1, }, 250 /* FCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, -1, -1, -1, -1, }, 251 /* DCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, -1, -1, -1, }, 252 /* LDCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, }, 253 /* FImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 0, 1, 2, -1, -1, }, 254 /* DImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, 0, 1, -1, -1, }, 255 /* LDImag */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, -1, -1, }, 256 257 /* I128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 3, 4, 5, -1, -1, -1, 0, 1, }, 258 /* U128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 2, 3, 4, -1, -1, -1, -1, 0, }, 232 static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = { 233 /* Src \ Dest: Bool Char SChar UChar Short UShort Int UInt Long ULong LLong ULLong Float Double LDbl FCplex DCplex LDCplex FImag DImag LDImag I128, U128, F80, F128 */ 234 /* Bool */ { 0, 1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 12, 13, 14, 12, 13, 14, -1, -1, -1, 10, 11, 14, 15}, 235 /* Char */ { -1, 0, -1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, 13, 14}, 236 /* SChar */ { -1, -1, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 11, 12, 13, 11, 12, 13, -1, -1, -1, 9, 10, 13, 14}, 237 /* UChar */ { -1, -1, -1, 0, 1, 2, 3, 4, 4, 5, 6, 7, 10, 11, 12, 10, 11, 12, -1, -1, -1, 8, 9, 12, 13}, 238 /* Short */ { -1, -1, -1, -1, 0, 1, 2, 3, 3, 4, 5, 6, 9, 10, 11, 9, 10, 11, -1, -1, -1, 7, 8, 11, 12}, 239 /* UShort */{ -1, -1, -1, -1, -1, 0, 1, 2, 2, 3, 4, 5, 8, 9, 10, 8, 9, 10, -1, -1, -1, 6, 7, 10, 11}, 240 /* Int */ { -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 7, 8, 9, 7, 8, 9, -1, -1, -1, 5, 6, 9, 10}, 241 /* UInt */ { -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, 8, 9}, 242 /* Long */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 6, 7, 8, 6, 7, 8, -1, -1, -1, 4, 5, 8, 9}, 243 /* ULong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 5, 6, 7, 5, 6, 7, -1, -1, -1, 3, 4, 7, 8}, 244 /* LLong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 4, 5, 6, 4, 5, 6, -1, -1, -1, 2, 3, 6, 7}, 245 /* ULLong */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 4, 5, 3, 4, 5, -1, -1, -1, 1, 2, 5, 6}, 246 247 /* Float */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 1, 2, 3, -1, -1, -1, -1, -1, 2, 3}, 248 /* Double */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 1, 2, -1, -1, -1, -1, -1, 1, 2}, 249 /* LDbl */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1}, 250 /* FCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, -1, -1, -1, -1, -1, -1}, 251 /* DCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1}, 252 /* LDCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1}, 253 /* FImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 0, 1, 2, -1, -1, -1, -1}, 254 /* DImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, 0, 1, -1, -1, -1, -1}, 255 /* LDImag */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, -1, -1, -1, -1}, 256 257 /* I128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 3, 4, 5, -1, -1, -1, 0, 1, 4, 4}, 258 /* U128 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 2, 3, 4, -1, -1, -1, -1, 0, 3, 3}, 259 260 /* F80 */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 0, 1}, 261 /* F128 */ { -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}, 259 262 }; 263 static_assert( 264 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES, 265 "Each basic type kind should have a corresponding row in the cost matrix" 266 ); 267 260 268 261 269 void ConversionCost::postvisit( VoidType * ) { -
src/SymTab/Mangler.cc
r96812c0 r054514d 171 171 "w", // SignedInt128 172 172 "Uw", // UnsignedInt128 173 "a", // Float80 174 "A", // Float128 173 175 }; 176 static_assert( 177 sizeof(btLetter)/sizeof(btLetter[0]) == BasicType::NUMBER_OF_BASIC_TYPES, 178 "Each basic type kind should have a corresponding mangler letter" 179 ); 174 180 175 181 printQualifiers( basicType ); 182 assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) ); 176 183 mangleName << btLetter[ basicType->get_kind() ]; 177 184 } -
src/SynTree/BasicType.cc
r96812c0 r054514d 55 55 case DoubleImaginary: 56 56 case LongDoubleImaginary: 57 case Float80: 58 case Float128: 57 59 return false; 58 60 case NUMBER_OF_BASIC_TYPES: -
src/SynTree/Type.cc
r96812c0 r054514d 24 24 using namespace std; 25 25 26 const char *BasicType::typeNames[ BasicType::NUMBER_OF_BASIC_TYPES] = {26 const char *BasicType::typeNames[] = { 27 27 "_Bool", 28 28 "char", … … 48 48 "__int128", 49 49 "unsigned __int128", 50 "__float80", 51 "__float128" 50 52 }; 53 static_assert( 54 sizeof(BasicType::typeNames)/sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES, 55 "Each basic type name should have a corresponding kind enum value" 56 ); 51 57 52 58 Type::Type( const Qualifiers &tq, const std::list< Attribute * > & attributes ) : tq( tq ), attributes( attributes ) {} -
src/SynTree/Type.h
r96812c0 r054514d 231 231 SignedInt128, 232 232 UnsignedInt128, 233 Float80, 234 Float128, 233 235 NUMBER_OF_BASIC_TYPES 234 236 } kind; -
src/libcfa/bits/locks.h
r96812c0 r054514d 39 39 #endif 40 40 41 #if __SIZEOF_SIZE_T__ == 842 #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_8( &(lock), 1 ) == 043 #define __lock_release( lock ) __sync_lock_release_8( &(lock) );44 #elif __SIZEOF_SIZE_T__ == 445 #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_4( &(lock), 1 ) == 046 #define __lock_release( lock ) __sync_lock_release_4( &(lock) );47 #else48 #error unsupported architecture49 #endif50 51 41 struct __spinlock_t { 52 __ALIGN__ volatile size_t lock; 42 // Wrap in struct to prevent false sharing with debug info 43 struct { 44 // Align lock on 128-bit boundary 45 __ALIGN__ volatile _Bool lock; 46 }; 53 47 #ifdef __CFA_DEBUG__ 48 // previous function to acquire the lock 54 49 const char * prev_name; 50 // previous thread to acquire the lock 55 51 void* prev_thrd; 56 52 #endif … … 78 74 // Lock the spinlock, return false if already acquired 79 75 static inline _Bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) { 80 _Bool result = __lock_test_and_test_and_set( this.lock);76 _Bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0); 81 77 if( result ) { 82 78 disable_interrupts(); … … 94 90 95 91 for ( unsigned int i = 1;; i += 1 ) { 96 if ( __lock_test_and_test_and_set( this.lock) ) break;92 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break; 97 93 #ifndef NOEXPBACK 98 94 // exponential spin … … 112 108 } 113 109 114 // // Lock the spinlock, yield if already acquired115 // static inline void lock_yield( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {116 // for ( unsigned int i = 1;; i += 1 ) {117 // if ( __lock_test_and_test_and_set( this.lock ) ) break;118 // yield( i );119 // }120 // disable_interrupts();121 // __cfaabi_dbg_debug_do(122 // this.prev_name = caller;123 // this.prev_thrd = this_thread;124 // )125 // }126 127 110 static inline void unlock( __spinlock_t & this ) { 128 111 enable_interrupts_noPoll(); 129 __ lock_release( this.lock);112 __atomic_clear( &this.lock, __ATOMIC_RELEASE ); 130 113 } 131 114 #endif -
src/libcfa/concurrency/alarm.c
r96812c0 r054514d 10 10 // Created On : Fri Jun 2 11:31:25 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 9 13:36:18201813 // Update Count : 6 112 // Last Modified On : Fri May 25 06:25:47 2018 13 // Update Count : 67 14 14 // 15 15 … … 37 37 38 38 void __kernel_set_timer( Duration alarm ) { 39 verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (% luns)", alarm.tv);39 verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (%jins)", alarm.tv); 40 40 setitimer( ITIMER_REAL, &(itimerval){ alarm }, NULL ); 41 41 } -
src/libcfa/concurrency/preemption.c
r96812c0 r054514d 161 161 void disable_interrupts() { 162 162 with( kernelTLS.preemption_state ) { 163 enabled = false; 163 #if GCC_VERSION > 50000 164 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free"); 165 #endif 166 167 // Set enabled flag to false 168 // should be atomic to avoid preemption in the middle of the operation. 169 // use memory order RELAXED since there is no inter-thread on this variable requirements 170 __atomic_store_n(&enabled, false, __ATOMIC_RELAXED); 171 172 // Signal the compiler that a fence is needed but only for signal handlers 173 __atomic_signal_fence(__ATOMIC_ACQUIRE); 174 164 175 __attribute__((unused)) unsigned short new_val = disable_count + 1; 165 176 disable_count = new_val; … … 171 182 // If counter reaches 0, execute any pending CtxSwitch 172 183 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 173 processor * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic add174 thread_desc * thrd = kernelTLS.this_thread; // Cache the thread now since interrupts can start happening after the atomic add184 processor * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store 185 thread_desc * thrd = kernelTLS.this_thread; // Cache the thread now since interrupts can start happening after the atomic store 175 186 176 187 with( kernelTLS.preemption_state ){ … … 181 192 // Check if we need to prempt the thread because an interrupt was missed 182 193 if( prev == 1 ) { 183 enabled = true; 194 #if GCC_VERSION > 50000 195 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free"); 196 #endif 197 198 // Set enabled flag to true 199 // should be atomic to avoid preemption in the middle of the operation. 200 // use memory order RELAXED since there is no inter-thread on this variable requirements 201 __atomic_store_n(&enabled, true, __ATOMIC_RELAXED); 202 203 // Signal the compiler that a fence is needed but only for signal handlers 204 __atomic_signal_fence(__ATOMIC_RELEASE); 184 205 if( proc->pending_preemption ) { 185 206 proc->pending_preemption = false; … … 200 221 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 201 222 if( prev == 1 ) { 202 kernelTLS.preemption_state.enabled = true; 223 #if GCC_VERSION > 50000 224 static_assert(__atomic_always_lock_free(sizeof(kernelTLS.preemption_state.enabled), &kernelTLS.preemption_state.enabled), "Must be lock-free"); 225 #endif 226 // Set enabled flag to true 227 // should be atomic to avoid preemption in the middle of the operation. 228 // use memory order RELAXED since there is no inter-thread on this variable requirements 229 __atomic_store_n(&kernelTLS.preemption_state.enabled, true, __ATOMIC_RELAXED); 230 231 // Signal the compiler that a fence is needed but only for signal handlers 232 __atomic_signal_fence(__ATOMIC_RELEASE); 203 233 } 204 234 } … … 352 382 353 383 // Clear sighandler mask before context switching. 384 #if GCC_VERSION > 50000 354 385 static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" ); 386 #endif 355 387 if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), NULL ) == -1 ) { 356 388 abort( "internal error, sigprocmask" ); -
src/prelude/Makefile.am
r96812c0 r054514d 37 37 # create forward declarations for gcc builtins 38 38 gcc-builtins.cf : gcc-builtins.c prototypes.sed 39 ${AM_V_GEN}@BACKEND_CC@ -E -P $< | sed-f prototypes.sed > $@39 ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E -P $< | sed -r -f prototypes.sed > $@ 40 40 41 gcc-builtins.c : builtins.def prototypes.awk 42 ${AM_V_GEN}@BACKEND_CC@ -E prototypes.c | awk -f prototypes.awk > $@41 gcc-builtins.c : builtins.def prototypes.awk sync-builtins.cf 42 ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E prototypes.c | awk -f prototypes.awk > $@ 43 43 44 44 builtins.def : -
src/prelude/Makefile.in
r96812c0 r054514d 506 506 # create forward declarations for gcc builtins 507 507 gcc-builtins.cf : gcc-builtins.c prototypes.sed 508 ${AM_V_GEN}@BACKEND_CC@ -E -P $< | sed-f prototypes.sed > $@509 510 gcc-builtins.c : builtins.def prototypes.awk 511 ${AM_V_GEN}@BACKEND_CC@ -E prototypes.c | awk -f prototypes.awk > $@508 ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E -P $< | sed -r -f prototypes.sed > $@ 509 510 gcc-builtins.c : builtins.def prototypes.awk sync-builtins.cf 511 ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E prototypes.c | awk -f prototypes.awk > $@ 512 512 513 513 builtins.def : -
src/prelude/builtins.def
r96812c0 r054514d 190 190 191 191 /* Builtin used by implementation of Cilk Plus. Most of these are decomposed 192 by the compiler but a few are implemented in libcilkrts. */ 192 by the compiler but a few are implemented in libcilkrts. */ 193 193 #undef DEF_CILK_BUILTIN_STUB 194 194 #define DEF_CILK_BUILTIN_STUB(ENUM, NAME) \ … … 204 204 205 205 /* Builtin used by the implementation of libsanitizer. These 206 functions are mapped to the actual implementation of the 206 functions are mapped to the actual implementation of the 207 207 libtsan library. */ 208 208 #undef DEF_SANITIZER_BUILTIN … … 217 217 #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ 218 218 DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \ 219 false, false, false, ATTRS, false, flag_cilkplus) 219 false, false, false, ATTRS, false, flag_cilkplus) 220 220 221 221 /* Builtin used by the implementation of Pointer Bounds Checker. */ … … 927 927 DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) 928 928 929 #if 0 //Ifdefed out because we hard-coded the proper overloadings of the atomic built-ins 929 930 /* Synchronization Primitives. */ 930 931 #include "sync-builtins.def" 931 932 932 #if 0933 933 /* Offloading and Multi Processing builtins. */ 934 934 #include "omp-builtins.def" -
src/prelude/prototypes.awk
r96812c0 r054514d 5 5 # file "LICENCE" distributed with Cforall. 6 6 # 7 # prototypes.awk -- 7 # prototypes.awk -- 8 8 # 9 9 # Author : Peter A. Buhr … … 12 12 # Last Modified On : Tue Jul 5 14:32:52 2016 13 13 # Update Count : 32 14 # 14 # 15 15 16 16 # http://llvm.org/svn/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def … … 83 83 } # BEGIN 84 84 85 /BT_FN/ { 85 /BT_FN/ { 86 86 for (i = 1; i <= NF; i++) { 87 87 if( match($i, "BT_FN") != 0 ) { … … 116 116 117 117 # generate function return type as macro 118 for ( t = 0; t < N; t += 1 ) { # find longest match 118 for ( t = 0; t < N; t += 1 ) { # find longest match 119 119 type = types[t]; 120 120 if ( index( prototype, type ) == 1 ) { # found match … … 150 150 # extras 151 151 printf( "\n#include \"builtins.def\"\n\n" ); 152 printf( "\n#include \"sync-builtins.cf\"\n\n" ); 152 153 printf( "extern const char *__PRETTY_FUNCTION__;\n" ); 153 154 } # END -
src/prelude/prototypes.sed
r96812c0 r054514d 2 2 /targetm/s/.*// #Remove targetm declarations 3 3 /__Unsupported/s/.*// #Remove Unsupported types declarations 4 s/void (const char \*)0();//#Remove void (const char \*)0();4 s/void \(const char \*\)0\(\);// #Remove void (const char \*)0(); 5 5 s/\"//g #Remove extraenous quotes in declarations 6 /__builtin_/s/_ /_/g #Remove extraenous spaces in declarations 6 /__builtin_/s/_ /_/g #Remove extraenous spaces in declarations 7 8 #Fix gcc overloading 9 # various sed rules for the gcc sync builtins which are overloaded 10 # kept here because they generate an acceptable approximate of the correct prototypes 11 12 #/__sync_/s/_[0-9][0-9]*\(.*\)/\(\);/g #hack since it will accept any parameters 13 #/__atomic_/s/_[0-9][0-9]*\(.*\)/\(\);/g #hack since it will accept any parameters 14 15 #/_16/s/void \*/__int128 \*/g 16 #/_8/s/void \*/long long int \*/g 17 #/_4/s/void \*/int \*/g 18 #/_2/s/void \*/short \*/g 19 #/_1/s/void \*/char \*/g 20 21 #s/([a-zA-Z0-9_ ]+)\s+__sync([a-z_]+)_([0-9]+)\((.*)\);/\1 __sync\2\(\4\,...); \1 __sync\2_\3\(\4\,...);/ 22 #s/([a-zA-Z0-9_ ]+)\s+__atomic([a-z_]+)_([0-9]+)\((.*)\);/\1 __atomic\2\(\4\); \1 __atomic\2_\3\(\4\);/ -
src/tests/.expect/io2.txt
r96812c0 r054514d 1 9 6 28 0 7 1 22 1 2 33 1234 1235 6 opening delimiters7 x (1 x [2 x {3 x =4 x $5 x £6 x ¥7 x ¡8 x ¿9 x «108 9 closing delimiters10 1, x 2. x 3; x 4! x 5? x 6% x 7¢ x 8» x 9) x 10] x 11} x11 12 opening/closing delimiters13 x`1`x'2'x"3"x:4:x 5 x 6 x14 715 x16 817 x18 919 x20 1021 x22 23 override opening/closing delimiters24 x ( 1 ) x 2 , x 3 :x: 425 26 1 input bacis types 27 2 -
src/tests/.expect/math1.x64.txt
r96812c0 r054514d 12 12 \ 16 256 13 13 \ 912673 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i 14 log:0 0 0 0.346574+0.785398i 0.346573590279973+0.785398163397448i 0.346573590279972655+0.78539816339744831i15 log2:3 3 316 log10:2 2 217 log1p:0.693147 0.693147180559945 0.69314718055994530918 ilogb:0 0 019 logb:3 3 320 sqrt:1 1 1 1.09868+0.45509i 1.09868411346781+0.455089860562227i 1.09868411346780997+0.455089860562227341i21 cbrt:3 3 322 hypot:1.41421 1.4142135623731 1.41421356237309505 -
src/tests/.expect/math1.x86.txt
r96812c0 r054514d 12 12 \ 16 256 13 13 \ 912673 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i 14 log:0 0 0 0.346574+0.785398i 0.346573590279973+0.785398163397448i 0.346573590279972655+0.78539816339744831i15 log2:3 3 316 log10:2 2 217 log1p:0.693147 0.693147180559945 0.69314718055994530918 ilogb:0 0 019 logb:3 3 320 sqrt:1 1 1 1.09868+0.45509i 1.09868411346781+0.455089860562227i 1.09868411346780997+0.455089860562227341i21 cbrt:3 3 322 hypot:1.41421 1.4142135623731 1.41421356237309505 -
src/tests/.expect/math2.x64.txt
r96812c0 r054514d 1 log:0 0 0 0.346574+0.785398i 0.346573590279973+0.785398163397448i 0.346573590279972655+0.78539816339744831i 2 log2:3 3 3 3 log10:2 2 2 4 log1p:0.693147 0.693147180559945 0.693147180559945309 5 ilogb:0 0 0 6 logb:3 3 3 7 sqrt:1 1 1 1.09868+0.45509i 1.09868411346781+0.455089860562227i 1.09868411346780997+0.455089860562227341i 8 cbrt:3 3 3 9 hypot:1.41421 1.4142135623731 1.41421356237309505 1 10 sin:0.841471 0.841470984807897 0.841470984807896507 1.29846+0.634964i 1.29845758141598+0.634963914784736i 1.29845758141597729+0.634963914784736108i 2 11 cos:0.540302 0.54030230586814 0.540302305868139717 0.83373-0.988898i 0.833730025131149-0.988897705762865i 0.833730025131149049-0.988897705762865096i … … 6 15 atan:0.785398 0.785398163397448 0.78539816339744831 1.01722+0.402359i 1.01722196789785+0.402359478108525i 1.01722196789785137+0.402359478108525094i 7 16 atan2:0.785398 0.785398163397448 0.78539816339744831 atan:0.785398 0.785398163397448 0.78539816339744831 8 sinh:1.1752 1.1752011936438 1.17520119364380146 0.634964+1.29846i 0.634963914784736+1.29845758141598i 0.634963914784736108+1.29845758141597729i9 cosh:1.54308 1.54308063481524 1.54308063481524378 0.83373+0.988898i 0.833730025131149+0.988897705762865i 0.833730025131149049+0.988897705762865096i10 tanh:0.761594 0.761594155955765 0.761594155955764888 1.08392+0.271753i 1.08392332733869+0.271752585319512i 1.08392332733869454+0.271752585319511717i11 acosh:0 0 0 1.06128+0.904557i 1.06127506190504+0.904556894302381i 1.06127506190503565+0.904556894302381364i12 asinh:0.881374 0.881373587019543 0.881373587019543025 1.06128+0.666239i 1.06127506190504+0.666239432492515i 1.06127506190503565+0.666239432492515255i13 atanh:inf inf inf 0.402359+1.01722i 0.402359478108525+1.01722196789785i 0.402359478108525094+1.01722196789785137i14 erf:0.842701 0.842700792949715 0.84270079294971486915 erfc:0.157299 0.157299207050285 0.15729920705028513116 lgamma:1.79176 1.79175946922805 1.79175946922805517 lgamma:1.79176 1 1.79175946922805 1 1.791759469228055 118 tgamma:6 6 6 -
src/tests/.expect/math2.x86.txt
r96812c0 r054514d 1 log:0 0 0 0.346574+0.785398i 0.346573590279973+0.785398163397448i 0.346573590279972655+0.78539816339744831i 2 log2:3 3 3 3 log10:2 2 2 4 log1p:0.693147 0.693147180559945 0.693147180559945309 5 ilogb:0 0 0 6 logb:3 3 3 7 sqrt:1 1 1 1.09868+0.45509i 1.09868411346781+0.455089860562227i 1.09868411346780997+0.455089860562227341i 8 cbrt:3 3 3 9 hypot:1.41421 1.4142135623731 1.41421356237309505 1 10 sin:0.841471 0.841470984807897 0.841470984807896507 1.29846+0.634964i 1.29845758141598+0.634963914784736i 1.29845758141597729+0.634963914784736108i 2 11 cos:0.540302 0.54030230586814 0.540302305868139717 0.83373-0.988898i 0.833730025131149-0.988897705762865i 0.833730025131149049-0.988897705762865096i … … 6 15 atan:0.785398 0.785398163397448 0.78539816339744831 1.01722+0.402359i 1.01722196789785+0.402359478108525i 1.01722196789785137+0.402359478108525094i 7 16 atan2:0.785398 0.785398163397448 0.78539816339744831 atan:0.785398 0.785398163397448 0.78539816339744831 8 sinh:1.1752 1.1752011936438 1.17520119364380146 0.634964+1.29846i 0.634963914784736+1.29845758141598i 0.634963914784736108+1.29845758141597729i9 cosh:1.54308 1.54308063481524 1.54308063481524378 0.83373+0.988898i 0.833730025131149+0.988897705762865i 0.833730025131149049+0.988897705762865096i10 tanh:0.761594 0.761594155955765 0.761594155955764888 1.08392+0.271753i 1.08392332733869+0.271752585319512i 1.08392332733869454+0.271752585319511717i11 acosh:0 0 0 1.06128+0.904557i 1.06127506190504+0.904556894302381i 1.06127506190503565+0.904556894302381364i12 asinh:0.881374 0.881373587019543 0.881373587019543025 1.06128+0.666239i 1.06127506190504+0.666239432492515i 1.06127506190503565+0.666239432492515255i13 atanh:inf inf inf 0.402359+1.01722i 0.402359478108525+1.01722196789785i 0.402359478108525094+1.01722196789785137i14 erf:0.842701 0.842700792949715 0.84270079294971486915 erfc:0.157299 0.157299207050285 0.15729920705028513116 lgamma:1.79176 1.79175946922805 1.79175946922805517 lgamma:1.79176 1 1.79175946922805 1 1.791759469228055 118 tgamma:6 6 6 -
src/tests/.expect/math3.x64.txt
r96812c0 r054514d 1 floor:1 1 1 2 ceil:2 2 2 3 trunc:3 3 3 4 rint:2 2 2 5 rint:2 2 2 6 rint:2 2 2 7 lrint:2 2 2 8 llrint:2 2 2 9 nearbyint:4 4 4 10 round:2 2 2 11 round:2 2 2 12 round:2 2 2 13 lround:2 2 2 14 llround:2 2 2 15 copysign:-1 -1 -1 16 frexp:0.5 3 0.5 3 0.5 3 17 ldexp:8 8 8 18 modf:2 0.3 2 0.3 2 0.3 19 modf:2, 0.3 2, 0.3 2, 0.3 20 nextafter:2 2 2 21 nexttoward:2 2 2 22 scalbn:16 16 16 23 scalbln:16 16 16 1 sinh:1.1752 1.1752011936438 1.17520119364380146 0.634964+1.29846i 0.634963914784736+1.29845758141598i 0.634963914784736108+1.29845758141597729i 2 cosh:1.54308 1.54308063481524 1.54308063481524378 0.83373+0.988898i 0.833730025131149+0.988897705762865i 0.833730025131149049+0.988897705762865096i 3 tanh:0.761594 0.761594155955765 0.761594155955764888 1.08392+0.271753i 1.08392332733869+0.271752585319512i 1.08392332733869454+0.271752585319511717i 4 acosh:0 0 0 1.06128+0.904557i 1.06127506190504+0.904556894302381i 1.06127506190503565+0.904556894302381364i 5 asinh:0.881374 0.881373587019543 0.881373587019543025 1.06128+0.666239i 1.06127506190504+0.666239432492515i 1.06127506190503565+0.666239432492515255i 6 atanh:inf inf inf 0.402359+1.01722i 0.402359478108525+1.01722196789785i 0.402359478108525094+1.01722196789785137i 7 erf:0.842701 0.842700792949715 0.842700792949714869 8 erfc:0.157299 0.157299207050285 0.157299207050285131 9 lgamma:1.79176 1.79175946922805 1.791759469228055 10 lgamma:1.79176 1 1.79175946922805 1 1.791759469228055 1 11 tgamma:6 6 6 -
src/tests/.expect/math3.x86.txt
r96812c0 r054514d 1 floor:1 1 1 2 ceil:2 2 2 3 trunc:3 3 3 4 rint:2 2 2 5 rint:2 2 2 6 rint:2 2 2 7 lrint:2 2 2 8 llrint:2 2 2 9 nearbyint:4 4 4 10 round:2 2 2 11 round:2 2 2 12 round:2 2 2 13 lround:2 2 2 14 llround:2 2 2 15 copysign:-1 -1 -1 16 frexp:0.5 3 0.5 3 0.5 3 17 ldexp:8 8 8 18 modf:2 0.3 2 0.3 2 0.3 19 modf:2, 0.3 2, 0.3 2, 0.3 20 nextafter:2 2 2 21 nexttoward:2 2 2 22 scalbn:16 16 16 23 scalbln:16 16 16 1 sinh:1.1752 1.1752011936438 1.17520119364380146 0.634964+1.29846i 0.634963914784736+1.29845758141598i 0.634963914784736108+1.29845758141597729i 2 cosh:1.54308 1.54308063481524 1.54308063481524378 0.83373+0.988898i 0.833730025131149+0.988897705762865i 0.833730025131149049+0.988897705762865096i 3 tanh:0.761594 0.761594155955765 0.761594155955764888 1.08392+0.271753i 1.08392332733869+0.271752585319512i 1.08392332733869454+0.271752585319511717i 4 acosh:0 0 0 1.06128+0.904557i 1.06127506190504+0.904556894302381i 1.06127506190503565+0.904556894302381364i 5 asinh:0.881374 0.881373587019543 0.881373587019543025 1.06128+0.666239i 1.06127506190504+0.666239432492515i 1.06127506190503565+0.666239432492515255i 6 atanh:inf inf inf 0.402359+1.01722i 0.402359478108525+1.01722196789785i 0.402359478108525094+1.01722196789785137i 7 erf:0.842701 0.842700792949715 0.842700792949714869 8 erfc:0.157299 0.157299207050285 0.157299207050285131 9 lgamma:1.79176 1.79175946922805 1.791759469228055 10 lgamma:1.79176 1 1.79175946922805 1 1.791759469228055 1 11 tgamma:6 6 6 -
src/tests/Makefile.am
r96812c0 r054514d 129 129 warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@ 130 130 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only 131 132 #builtins 133 builtins/sync: builtins/sync.c @CFA_BINDIR@/@CFA_NAME@ 134 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only -
src/tests/Makefile.in
r96812c0 r054514d 807 807 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only 808 808 809 #builtins 810 builtins/sync: builtins/sync.c @CFA_BINDIR@/@CFA_NAME@ 811 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only 812 809 813 # Tell versions [3.59,3.63) of GNU make to not export all variables. 810 814 # Otherwise a system limit (for SysV at least) may be exceeded. -
src/tests/concurrent/coroutineYield.c
r96812c0 r054514d 3 3 #include <stdlib> 4 4 #include <thread> 5 #include <time> 6 7 #ifndef PREEMPTION_RATE 8 #define PREEMPTION_RATE 10`ms 9 #endif 10 11 Duration default_preemption() { 12 return PREEMPTION_RATE; 13 } 5 14 6 15 #ifdef LONG_TEST -
src/tests/concurrent/examples/datingService.c
r96812c0 r054514d 8 8 // Created On : Mon Oct 30 12:56:20 2017 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Wed Mar 14 22:48:40201811 // Update Count : 2 310 // Last Modified On : Sun May 27 09:05:18 2018 11 // Update Count : 26 12 12 // 13 13 … … 18 18 #include <unistd.h> // getpid 19 19 20 enum { NoOfPairs = 20 };20 enum { CompCodes = 20 }; // number of compatibility codes 21 21 22 22 monitor DatingService { 23 condition Girls[ NoOfPairs], Boys[NoOfPairs];23 condition Girls[CompCodes], Boys[CompCodes]; 24 24 unsigned int GirlPhoneNo, BoyPhoneNo; 25 25 }; // DatingService … … 47 47 } // DatingService boy 48 48 49 unsigned int girlck[ NoOfPairs];50 unsigned int boyck[ NoOfPairs];49 unsigned int girlck[CompCodes]; 50 unsigned int boyck[CompCodes]; 51 51 52 52 thread Girl { … … 88 88 int main() { 89 89 DatingService TheExchange; 90 Girl * girls[ NoOfPairs];91 Boy * boys[ NoOfPairs];90 Girl * girls[CompCodes]; 91 Boy * boys[CompCodes]; 92 92 93 93 srandom( /*getpid()*/ 103 ); 94 94 95 for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {95 for ( unsigned int i = 0; i < CompCodes; i += 1 ) { 96 96 girls[i] = new( &TheExchange, i, i ); 97 boys[i] = new( &TheExchange, i, NoOfPairs - ( i + 1 ) );97 boys[i] = new( &TheExchange, i, CompCodes - ( i + 1 ) ); 98 98 } // for 99 99 100 for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {100 for ( unsigned int i = 0; i < CompCodes; i += 1 ) { 101 101 delete( boys[i] ); 102 102 delete( girls[i] ); 103 103 } // for 104 104 105 for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {105 for ( unsigned int i = 0; i < CompCodes; i += 1 ) { 106 106 if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort(); 107 107 } // for -
src/tests/concurrent/examples/matrixSum.c
r96812c0 r054514d 11 11 // Created On : Mon Oct 9 08:29:28 2017 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Tue Dec 5 22:56:46 201714 // Update Count : 413 // Last Modified On : Fri May 25 09:34:27 2018 14 // Update Count : 10 15 15 // 16 16 … … 20 20 21 21 thread Adder { 22 int * row, cols, *subtotal; // communication22 int * row, cols, & subtotal; // communication 23 23 }; 24 24 25 25 void ?{}( Adder & adder, int row[], int cols, int & subtotal ) { 26 adder.row = row; 27 adder.cols = cols; 28 adder.subtotal = &subtotal; 26 adder.[ row, cols ] = [ row, cols ]; // expression disallowed in multi-member access 27 &adder.subtotal = &subtotal; 29 28 } 30 29 31 void main( Adder & adder ) with( adder ) { 32 *subtotal = 0;33 34 *subtotal += row[c];35 30 void main( Adder & adder ) with( adder ) { // thread starts here 31 subtotal = 0; 32 for ( int c = 0; c < cols; c += 1 ) { 33 subtotal += row[c]; 34 } // for 36 35 } 37 36 38 37 int main() { 39 40 41 processor p; // extrakernel thread38 const int rows = 10, cols = 1000; 39 int matrix[rows][cols], subtotals[rows], total = 0; 40 processor p; // add kernel thread 42 41 43 42 for ( int r = 0; r < rows; r += 1 ) { 44 43 for ( int c = 0; c < cols; c += 1 ) { 45 44 matrix[r][c] = 1; 46 45 } // for 47 48 49 46 } // for 47 Adder * adders[rows]; 48 for ( int r = 0; r < rows; r += 1 ) { // start threads to sum rows 50 49 adders[r] = &(*malloc()){ matrix[r], cols, subtotals[r] }; 51 50 // adders[r] = new( matrix[r], cols, &subtotals[r] ); 52 53 51 } // for 52 for ( int r = 0; r < rows; r += 1 ) { // wait for threads to finish 54 53 delete( adders[r] ); 55 54 total += subtotals[r]; // total subtotals 56 57 55 } // for 56 sout | total | endl; 58 57 } 59 58 -
src/tests/concurrent/signal/block.c
r96812c0 r054514d 14 14 #include <time> 15 15 16 #ifdef LONG_TEST17 static const unsigned long N = 150_000ul;18 #else19 static const unsigned long N = 5_000ul;20 #endif21 22 16 #ifndef PREEMPTION_RATE 23 17 #define PREEMPTION_RATE 10`ms … … 27 21 return PREEMPTION_RATE; 28 22 } 23 24 #ifdef LONG_TEST 25 static const unsigned long N = 150_000ul; 26 #else 27 static const unsigned long N = 5_000ul; 28 #endif 29 29 30 30 enum state_t { WAITED, SIGNAL, BARGE }; -
src/tests/concurrent/signal/disjoint.c
r96812c0 r054514d 4 4 #include <thread> 5 5 #include <time> 6 7 #ifdef LONG_TEST8 static const unsigned long N = 300_000ul;9 #else10 static const unsigned long N = 10_000ul;11 #endif12 6 13 7 #ifndef PREEMPTION_RATE … … 18 12 return PREEMPTION_RATE; 19 13 } 14 15 #ifdef LONG_TEST 16 static const unsigned long N = 300_000ul; 17 #else 18 static const unsigned long N = 10_000ul; 19 #endif 20 20 21 21 enum state_t { WAIT, SIGNAL, BARGE }; -
src/tests/concurrent/signal/wait.c
r96812c0 r054514d 12 12 #include <time> 13 13 14 #ifdef LONG_TEST15 static const unsigned long N = 375_000ul;16 #else17 static const unsigned long N = 2_500ul;18 #endif19 20 14 #ifndef PREEMPTION_RATE 21 15 #define PREEMPTION_RATE 10`ms … … 25 19 return PREEMPTION_RATE; 26 20 } 21 22 #ifdef LONG_TEST 23 static const unsigned long N = 375_000ul; 24 #else 25 static const unsigned long N = 2_500ul; 26 #endif 27 27 28 28 monitor global_t {}; -
src/tests/io2.c
r96812c0 r054514d 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // io .c --7 // io2.c -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Wed Mar 2 16:56:02 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jan 26 15:19:34201813 // Update Count : 10 012 // Last Modified On : Thu May 24 21:17:41 2018 13 // Update Count : 103 14 14 // 15 15 … … 37 37 enum { size = 10 }; 38 38 char s1[size], s2[size]; 39 40 int x = 3, y = 5, z = 7;41 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;42 sout | 1 | 2 | 3 | endl;43 sout | '1' | '2' | '3' | endl;44 sout | 1 | "" | 2 | "" | 3 | endl;45 sout | endl;46 47 sout | "opening delimiters" | endl;48 sout49 | "x (" | 150 | "x [" | 251 | "x {" | 352 | "x =" | 453 | "x $" | 554 | "x £" | 655 | "x ¥" | 756 | "x ¡" | 857 | "x ¿" | 958 | "x «" | 1059 | endl | endl;60 61 sout | "closing delimiters" | endl;62 sout63 | 1 | ", x"64 | 2 | ". x"65 | 3 | "; x"66 | 4 | "! x"67 | 5 | "? x"68 | 6 | "% x"69 | 7 | "¢ x"70 | 8 | "» x"71 | 9 | ") x"72 | 10 | "] x"73 | 11 | "} x"74 | endl | endl;75 76 sout | "opening/closing delimiters" | endl;77 sout78 | "x`" | 1 | "`x'" | 279 | "'x\"" | 3 | "\"x:" | 480 | ":x " | 5 | " x\t" | 681 | "\tx\f" | 7 | "\fx\v" | 882 | "\vx\n" | 9 | "\nx\r" | 1083 | "\rx"84 | endl | endl;85 86 sout | "override opening/closing delimiters" | endl;87 sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4 | endl;88 sout | endl;89 39 90 40 ifstream in = { "io.data" }; // create / open file … … 181 131 // Local Variables: // 182 132 // tab-width: 4 // 183 // compile-command: "cfa io .c" //133 // compile-command: "cfa io2.c" // 184 134 // End: // -
src/tests/math1.c
r96812c0 r054514d 10 10 // Created On : Fri Apr 22 14:59:21 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 11 15:16:41 201713 // Update Count : 8 412 // Last Modified On : Thu May 24 21:01:15 2018 13 // Update Count : 85 14 14 // 15 15 … … 48 48 sout | "\\" | b | b \ e | endl; 49 49 sout | "\\" | 'a' \ 3u | 2 \ 8u | 4 \ 3u | -4 \ 3u | 4 \ -3 | -4 \ -3 | 4.0 \ 2.1 | (1.0f+2.0fi) \ (3.0f+2.0fi) | endl; 50 51 //---------------------- Logarithm ----------------------52 53 sout | "log:" | log( 1.0F ) | log( 1.0D ) | log( 1.0L ) | log( 1.0F+1.0FI ) | log( 1.0D+1.0DI ) | log( 1.0DL+1.0LI ) | endl;54 sout | "log2:" | log2( 8.0F ) | log2( 8.0D ) | log2( 8.0L ) | endl;55 sout | "log10:" | log10( 100.0F ) | log10( 100.0D ) | log10( 100.0L ) | endl;56 sout | "log1p:" | log1p( 1.0F ) | log1p( 1.0D ) | log1p( 1.0L ) | endl;57 sout | "ilogb:" | ilogb( 1.0F ) | ilogb( 1.0D ) | ilogb( 1.0L ) | endl;58 sout | "logb:" | logb( 8.0F ) | logb( 8.0D ) | logb( 8.0L ) | endl;59 60 sout | "sqrt:" | sqrt( 1.0F ) | sqrt( 1.0D ) | sqrt( 1.0L ) | sqrt( 1.0F+1.0FI ) | sqrt( 1.0D+1.0DI ) | sqrt( 1.0DL+1.0LI ) | endl;61 sout | "cbrt:" | cbrt( 27.0F ) | cbrt( 27.0D ) | cbrt( 27.0L ) | endl;62 sout | "hypot:" | hypot( 1.0F, -1.0F ) | hypot( 1.0D, -1.0D ) | hypot( 1.0L, -1.0L ) | endl;63 50 } // main 64 51 -
src/tests/math2.c
r96812c0 r054514d 10 10 // Created On : Fri Apr 22 14:59:21 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 11 15:40:04 201713 // Update Count : 8 112 // Last Modified On : Thu May 24 21:06:10 2018 13 // Update Count : 82 14 14 // 15 15 … … 21 21 double d; 22 22 long double l; 23 24 //---------------------- Logarithm ---------------------- 25 26 sout | "log:" | log( 1.0F ) | log( 1.0D ) | log( 1.0L ) | log( 1.0F+1.0FI ) | log( 1.0D+1.0DI ) | log( 1.0DL+1.0LI ) | endl; 27 sout | "log2:" | log2( 8.0F ) | log2( 8.0D ) | log2( 8.0L ) | endl; 28 sout | "log10:" | log10( 100.0F ) | log10( 100.0D ) | log10( 100.0L ) | endl; 29 sout | "log1p:" | log1p( 1.0F ) | log1p( 1.0D ) | log1p( 1.0L ) | endl; 30 sout | "ilogb:" | ilogb( 1.0F ) | ilogb( 1.0D ) | ilogb( 1.0L ) | endl; 31 sout | "logb:" | logb( 8.0F ) | logb( 8.0D ) | logb( 8.0L ) | endl; 32 33 sout | "sqrt:" | sqrt( 1.0F ) | sqrt( 1.0D ) | sqrt( 1.0L ) | sqrt( 1.0F+1.0FI ) | sqrt( 1.0D+1.0DI ) | sqrt( 1.0DL+1.0LI ) | endl; 34 sout | "cbrt:" | cbrt( 27.0F ) | cbrt( 27.0D ) | cbrt( 27.0L ) | endl; 35 sout | "hypot:" | hypot( 1.0F, -1.0F ) | hypot( 1.0D, -1.0D ) | hypot( 1.0L, -1.0L ) | endl; 23 36 24 37 //---------------------- Trigonometric ---------------------- … … 32 45 sout | "atan2:" | atan2( 1.0F, 1.0F ) | atan2( 1.0D, 1.0D ) | atan2( 1.0L, 1.0L ); 33 46 sout | "atan:" | atan( 1.0F, 1.0F ) | atan( 1.0D, 1.0D ) | atan( 1.0L, 1.0L ) | endl; 34 35 //---------------------- Hyperbolic ----------------------36 37 sout | "sinh:" | sinh( 1.0F ) | sinh( 1.0D ) | sinh( 1.0L ) | sinh( 1.0F+1.0FI ) | sinh( 1.0D+1.0DI ) | sinh( 1.0DL+1.0LI ) | endl;38 sout | "cosh:" | cosh( 1.0F ) | cosh( 1.0D ) | cosh( 1.0L ) | cosh( 1.0F+1.0FI ) | cosh( 1.0D+1.0DI ) | cosh( 1.0DL+1.0LI ) | endl;39 sout | "tanh:" | tanh( 1.0F ) | tanh( 1.0D ) | tanh( 1.0L ) | tanh( 1.0F+1.0FI ) | tanh( 1.0D+1.0DI ) | tanh( 1.0DL+1.0LI ) | endl;40 sout | "acosh:" | acosh( 1.0F ) | acosh( 1.0D ) | acosh( 1.0L ) | acosh( 1.0F+1.0FI ) | acosh( 1.0D+1.0DI ) | acosh( 1.0DL+1.0LI ) | endl;41 sout | "asinh:" | asinh( 1.0F ) | asinh( 1.0D ) | asinh( 1.0L ) | asinh( 1.0F+1.0FI ) | asinh( 1.0D+1.0DI ) | asinh( 1.0DL+1.0LI ) | endl;42 sout | "atanh:" | atanh( 1.0F ) | atanh( 1.0D ) | atanh( 1.0L ) | atanh( 1.0F+1.0FI ) | atanh( 1.0D+1.0DI ) | atanh( 1.0DL+1.0LI ) | endl;43 44 //---------------------- Error / Gamma ----------------------45 46 sout | "erf:" | erf( 1.0F ) | erf( 1.0D ) | erf( 1.0L ) | endl;47 sout | "erfc:" | erfc( 1.0F ) | erfc( 1.0D ) | erfc( 1.0L ) | endl;48 sout | "lgamma:" | lgamma( 4.0F ) | lgamma( 4.0D ) | lgamma( 4.0L ) | endl;49 int sign;50 f = lgamma( 4.0F, &sign );51 sout | "lgamma:" | f | sign;52 d = lgamma( 4.0D, &sign );53 sout | d | sign;54 l = lgamma( 4.0L, &sign );55 sout | l | sign | endl;56 sout | "tgamma:" | tgamma( 4.0F ) | tgamma( 4.0D ) | tgamma( 4.0L ) | endl;57 47 } // main 58 48 -
src/tests/math3.c
r96812c0 r054514d 10 10 // Created On : Fri Apr 22 14:59:21 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 11 15:40:03 201713 // Update Count : 8 112 // Last Modified On : Thu May 24 21:06:12 2018 13 // Update Count : 82 14 14 // 15 15 … … 22 22 long double l; 23 23 24 //---------------------- Nearest Integer----------------------24 //---------------------- Hyperbolic ---------------------- 25 25 26 sout | "floor:" | floor( 1.2F ) | floor( 1.2D ) | floor( 1.2L ) | endl; 27 sout | "ceil:" | ceil( 1.6F ) | ceil( 1.6D ) | ceil( 1.6L ) | endl; 28 sout | "trunc:" | trunc( 3.5F ) | trunc( 3.5D ) | trunc( 3.5L ) | endl; 29 sout | "rint:" | (float)rint( 1.5F ) | (double)rint( 1.5D ) | (long double)rint( 1.5L ) | endl; 30 sout | "rint:" | (long int)rint( 1.5F ) | (long int)rint( 1.5D ) | (long int)rint( 1.5L ) | endl; 31 sout | "rint:" | (long long int)rint( 1.5F ) | (long long int)rint( 1.5D ) | (long long int)rint( 1.5L ) | endl; 32 sout | "lrint:" | lrint( 1.5F ) | lrint( 1.5D ) | lrint( 1.5L ) | endl; 33 sout | "llrint:" | llrint( 1.5F ) | llrint( 1.5D ) | llrint( 1.5L ) | endl; 34 sout | "nearbyint:" | nearbyint( 3.5F ) | nearbyint( 3.5D ) | nearbyint( 3.5L ) | endl; 35 sout | "round:" | (float)round( 1.5F ) | (double)round( 1.5D ) | (long double)round( 1.5L ) | endl; 36 sout | "round:" | (long int)round( 1.5F ) | (long int)round( 1.5D ) | (long int)round( 1.5L ) | endl; 37 sout | "round:" | (long long int)round( 1.5F ) | (long long int)round( 1.5D ) | (long long int)round( 1.5L ) | endl; 38 sout | "lround:" | lround( 1.5F ) | lround( 1.5D ) | lround( 1.5L ) | endl; 39 sout | "llround:" | llround( 1.5F ) | llround( 1.5D ) | llround( 1.5L ) | endl; 26 sout | "sinh:" | sinh( 1.0F ) | sinh( 1.0D ) | sinh( 1.0L ) | sinh( 1.0F+1.0FI ) | sinh( 1.0D+1.0DI ) | sinh( 1.0DL+1.0LI ) | endl; 27 sout | "cosh:" | cosh( 1.0F ) | cosh( 1.0D ) | cosh( 1.0L ) | cosh( 1.0F+1.0FI ) | cosh( 1.0D+1.0DI ) | cosh( 1.0DL+1.0LI ) | endl; 28 sout | "tanh:" | tanh( 1.0F ) | tanh( 1.0D ) | tanh( 1.0L ) | tanh( 1.0F+1.0FI ) | tanh( 1.0D+1.0DI ) | tanh( 1.0DL+1.0LI ) | endl; 29 sout | "acosh:" | acosh( 1.0F ) | acosh( 1.0D ) | acosh( 1.0L ) | acosh( 1.0F+1.0FI ) | acosh( 1.0D+1.0DI ) | acosh( 1.0DL+1.0LI ) | endl; 30 sout | "asinh:" | asinh( 1.0F ) | asinh( 1.0D ) | asinh( 1.0L ) | asinh( 1.0F+1.0FI ) | asinh( 1.0D+1.0DI ) | asinh( 1.0DL+1.0LI ) | endl; 31 sout | "atanh:" | atanh( 1.0F ) | atanh( 1.0D ) | atanh( 1.0L ) | atanh( 1.0F+1.0FI ) | atanh( 1.0D+1.0DI ) | atanh( 1.0DL+1.0LI ) | endl; 40 32 41 //---------------------- Manipulation----------------------33 //---------------------- Error / Gamma ---------------------- 42 34 43 sout | "copysign:" | copysign( 1.0F, -1.0F ) | copysign( 1.0D, -1.0D ) | copysign( 1.0L, -1.0L ) | endl; 44 int exp; 45 f = frexp( 4.0F, &exp ); 46 sout | "frexp:" | f | exp; 47 d = frexp( 4.0D, &exp ); 48 sout | d | exp; 49 l = frexp( 4.0L, &exp ); 50 sout | l | exp | endl; 51 sout | "ldexp:" | ldexp( 2.0F, 2 ) | ldexp( 2.0D, 2 ) | ldexp( 2.0L, 2 ) | endl; 52 float fi; 53 double di; 54 long double ldi; 55 f = modf( 2.3F, &fi ); 56 sout | "modf:" | fi | f; 57 d = modf( 2.3D, &di ); 58 sout | di | d; 59 l = modf( 2.3L, &ldi ); 60 sout | ldi | l | endl; 61 sout | "modf:" | modf( 2.3F ) | modf( 2.3D ) | modf( 2.3L ) | endl; 62 sout | "nextafter:" | nextafter( 2.0F, 3.0F ) | nextafter( 2.0D, 3.0D ) | nextafter( 2.0L, 3.0L ) | endl; 63 sout | "nexttoward:" | nexttoward( 2.0F, 3.0F ) | nexttoward( 2.0D, 3.0D ) | nexttoward( 2.0L, 3.0L ) | endl; 64 65 sout | "scalbn:" | scalbn( 2.0F, 3 ) | scalbn( 2.0D, 3 ) | scalbn( 2.0L, 3 ) | endl; 66 sout | "scalbln:" | scalbln( 2.0F, 3L ) | scalbln( 2.0D, 3L ) | scalbln( 2.0L, 3L ) | endl; 35 sout | "erf:" | erf( 1.0F ) | erf( 1.0D ) | erf( 1.0L ) | endl; 36 sout | "erfc:" | erfc( 1.0F ) | erfc( 1.0D ) | erfc( 1.0L ) | endl; 37 sout | "lgamma:" | lgamma( 4.0F ) | lgamma( 4.0D ) | lgamma( 4.0L ) | endl; 38 int sign; 39 f = lgamma( 4.0F, &sign ); 40 sout | "lgamma:" | f | sign; 41 d = lgamma( 4.0D, &sign ); 42 sout | d | sign; 43 l = lgamma( 4.0L, &sign ); 44 sout | l | sign | endl; 45 sout | "tgamma:" | tgamma( 4.0F ) | tgamma( 4.0D ) | tgamma( 4.0L ) | endl; 67 46 } // main 68 47 -
src/tests/preempt_longrun/Makefile.am
r96812c0 r054514d 17 17 repeats=10 18 18 max_time=600 19 preempt=1 _000ul19 preempt=10ul\`ms 20 20 debug=-debug 21 21 -
src/tests/preempt_longrun/Makefile.in
r96812c0 r054514d 450 450 repeats = 10 451 451 max_time = 600 452 preempt = 1 _000ul452 preempt = 10ul\`ms 453 453 debug = -debug 454 454 REPEAT = ${abs_top_srcdir}/tools/repeat -
src/tests/preempt_longrun/create.c
r96812c0 r054514d 1 1 #include <kernel> 2 2 #include <thread> 3 4 static const unsigned long N = 60_000ul; 3 #include <time> 5 4 6 5 #ifndef PREEMPTION_RATE 7 # define PREEMPTION_RATE 10`ms6 #error PREEMPTION_RATE not defined in makefile 8 7 #endif 9 8 … … 11 10 return PREEMPTION_RATE; 12 11 } 12 13 static const unsigned long N = 60_000ul; 13 14 14 15 thread worker_t {}; -
src/tests/preempt_longrun/enter.c
r96812c0 r054514d 2 2 #include <monitor> 3 3 #include <thread> 4 5 static const unsigned long N = 2_100_000ul; 4 #include <time> 6 5 7 6 #ifndef PREEMPTION_RATE 8 # define PREEMPTION_RATE 10`ms7 #error PREEMPTION_RATE not defined in makefile 9 8 #endif 10 9 … … 12 11 return PREEMPTION_RATE; 13 12 } 13 14 static const unsigned long N = 2_100_000ul; 14 15 15 16 monitor mon_t {}; -
src/tests/preempt_longrun/enter3.c
r96812c0 r054514d 2 2 #include <monitor> 3 3 #include <thread> 4 5 static const unsigned long N = 500_000ul; 4 #include <time> 6 5 7 6 #ifndef PREEMPTION_RATE 8 # define PREEMPTION_RATE 10`ms7 #error PREEMPTION_RATE not defined in makefile 9 8 #endif 10 9 … … 12 11 return PREEMPTION_RATE; 13 12 } 13 14 static const unsigned long N = 500_000ul; 14 15 15 16 monitor mon_t {}; -
src/tests/preempt_longrun/processor.c
r96812c0 r054514d 1 1 #include <kernel> 2 2 #include <thread> 3 4 static const unsigned long N = 5_000ul; 3 #include <time> 5 4 6 5 #ifndef PREEMPTION_RATE 7 # define PREEMPTION_RATE 10`ms6 #error PREEMPTION_RATE not defined in makefile 8 7 #endif 9 8 … … 11 10 return PREEMPTION_RATE; 12 11 } 12 13 static const unsigned long N = 5_000ul; 13 14 14 15 int main(int argc, char* argv[]) { -
src/tests/preempt_longrun/stack.c
r96812c0 r054514d 1 1 #include <kernel> 2 #include <math> 2 3 #include <thread> 3 4 #include <math> 4 #include <time> 5 5 6 6 #ifndef PREEMPTION_RATE 7 # define PREEMPTION_RATE 10`ms7 #error PREEMPTION_RATE not defined in makefile 8 8 #endif 9 9 -
src/tests/preempt_longrun/yield.c
r96812c0 r054514d 1 1 #include <kernel> 2 2 #include <thread> 3 #include <time> 4 5 #ifndef PREEMPTION_RATE 6 #error PREEMPTION_RATE not defined in makefile 7 #endif 8 9 Duration default_preemption() { 10 return PREEMPTION_RATE; 11 } 3 12 4 13 #ifdef LONG_TEST … … 7 16 static const unsigned long N = 325_000ul; 8 17 #endif 9 10 #ifndef PREEMPTION_RATE11 #define PREEMPTION_RATE 10`ms12 #endif13 14 Duration default_preemption() {15 return PREEMPTION_RATE;16 }17 18 18 19 thread worker_t {}; -
src/tests/test.py
r96812c0 r054514d 78 78 else : 79 79 print('ERROR: No expected file for test %s, ignoring it' % testname, file=sys.stderr) 80 81 # make sure we have at least some test to run82 if not tests :83 print('ERROR: No valid test to run', file=sys.stderr)84 sys.exit(1)85 80 86 81 return tests … … 266 261 tests = validTests( options ) 267 262 263 # make sure we have at least some test to run 264 if not tests : 265 print('ERROR: No valid test to run', file=sys.stderr) 266 sys.exit(1) 267 268 268 269 # sort the test alphabetically for convenience 269 270 tests.sort(key=lambda t: (t.arch if t.arch else '') + t.target())
Note: See TracChangeset
for help on using the changeset viewer.