Changeset 2055098


Ignore:
Timestamp:
May 1, 2017, 1:40:13 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
5544465, ed8a0d2
Parents:
12d3187 (diff), 13e2c54 (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

Files:
9 added
1 deleted
38 edited
1 moved

Legend:

Unmodified
Added
Removed
  • .gitignore

    r12d3187 r2055098  
    11# build files
    22*.[ao]
     3*.pyc
    34
    45# generated by configure
  • doc/generic_types/evaluation/Makefile

    r12d3187 r2055098  
     1CC = gcc
    12CFA = cfa
    23DEPFLAGS = -MMD -MP
     
    67endif
    78CXXFLAGS = $(CFLAGS) --std=c++14
     9MAKEFILE_NAME = ${firstword ${MAKEFILE_LIST}}
    810
    9 .PHONY: all clean distclean run-c run-cpp run-cfa run
     11.PHONY : all clean run-c run-cpp run-cfa run
    1012
    11 all: c-bench cpp-bench cfa-bench cpp-vbench
     13all : c-bench cpp-bench cpp-vbench cfa-bench
    1214
    1315# rewrite object generation to auto-determine deps
     
    1719
    1820c-%.o : c-%.c
    19 c-%.o : c-%.c c-%.d
    2021        $(COMPILE.c) $(OUTPUT_OPTION) -c $<
    2122
    2223cpp-%.o : cpp-%.cpp
    23 cpp-%.o : cpp-%.cpp cpp-%.d
    2424        $(COMPILE.cpp) $(OUTPUT_OPTION) -c $<
    2525
    2626cfa-%.o : cfa-%.c
    27 cfa-%.o : cfa-%.c cfa-%.d
    2827        $(COMPILE.cfa) $(OUTPUT_OPTION) -c $<
    2928
    30 COBJS = c-stack.o c-pair.o c-print.o
    31 CPPOBJS =
    32 CPPVOBJS = cpp-vstack.o
    33 CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o
     29COBJS = c-stack.o c-pair.o c-print.o c-bench.o
     30CPPOBJS = cpp-bench.o
     31CPPVOBJS = cpp-vstack.o cpp-vbench.o
     32CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o cfa-bench.o
    3433
    35 CFILES = c-bench.c bench.h $(COBJS:.o=.h) $(COBJS:.o=.c)
    36 CPPFILES = cpp-bench.cpp bench.hpp cpp-stack.hpp cpp-pair.hpp cpp-print.hpp
    37 CPPVFILES = cpp-vbench.cpp bench.hpp object.hpp $(CPPVOBJS:.o=.hpp) $(CPPVOBJS:.o=.cpp) cpp-vprint.hpp
    38 CFAFILES = cfa-bench.c bench.h $(CFAOBJS:.o=.h) $(CFAOBJS:.o=.c)
     34${COBJS} ${CPPOBJS} ${CPPVOBJS} ${CFAOBJS} : ${MAKEFILE_NAME}
    3935
    40 c-bench: c-bench.c c-bench.d $(COBJS)
    41         $(COMPILE.c) -o $@ $< $(COBJS) $(LDFLAGS)
     36CFILES = bench.h $(patsubst c-bench.h,,$(COBJS:.o=.h)) $(COBJS:.o=.c)
     37CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp cpp-print.hpp $(CPPOBJS:.o=.cpp)
     38CPPVFILES = bench.hpp object.hpp cpp-vprint.hpp $(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp)
     39CFAFILES = bench.h $(patsubst cfa-bench.h,,$(CFAOBJS:.o=.h)) $(CFAOBJS:.o=.c)
    4240
    43 cpp-bench: cpp-bench.cpp cpp-bench.d $(CPPOBJS)
    44         $(COMPILE.cpp) -o $@ $< $(CPPOBJS) $(LDFLAGS)
     41c-bench : $(COBJS) c-bench.o
     42        $(COMPILE.c) $(LDFLAGS) $^ -o $@
    4543
    46 cpp-vbench: cpp-vbench.cpp cpp-vbench.d $(CPPVOBJS)
    47         $(COMPILE.cpp) -o $@ $< $(CPPVOBJS) $(LDFLAGS)
     44cpp-bench : $(CPPOBJS) cpp-bench.o
     45        $(COMPILE.cpp) $(LDFLAGS) $^ -o $@
    4846
    49 cfa-bench: cfa-bench.c cfa-bench.d $(CFAOBJS)
    50         $(COMPILE.cfa) -o $@ $< $(CFAOBJS) $(LDFLAGS)
     47cpp-vbench : $(CPPVOBJS) cpp-vbench.o
     48        $(COMPILE.cpp) $(LDFLAGS) $^ -o $@
    5149
    52 clean:
    53         -rm $(COBJS) c-bench
    54         -rm $(CPPOBJS) cpp-bench
    55         -rm $(CPPVOBJS) cpp-vbench
    56         -rm $(CFAOBJS) cfa-bench
     50cfa-bench : $(CFAOBJS) cfa-bench.o
     51        $(COMPILE.cfa) $(LDFLAGS) $^ -o $@
    5752
    58 distclean: clean
    59         -rm $(COBJS:.o=.d) c-bench.d
    60         -rm $(CPPOBJS:.o=.d) cpp-bench.d
    61         -rm $(CPPVOBJS:.o=.d) cpp-vbench.d
    62         -rm $(CFAOBJS:.o=.d) cfa-bench.d
     53# include dependency files
     54-include $(COBJS:.o=.d)
     55-include $(CPPOBJS:.o=.d)
     56-include $(CPPVOBJS:.o=.d)
     57-include $(CFAOBJS:.o=.d)
    6358
    64 run-c: c-bench
     59clean :
     60        rm -f $(COBJS) $(COBJS:.o=.d) c-bench
     61        rm -f $(CPPOBJS) $(CPPOBJS:.o=.d) cpp-bench
     62        rm -f $(CPPVOBJS) $(CPPVOBJS:.o=.d) cpp-vbench
     63        rm -f $(CFAOBJS) $(CFAOBJS:.o=.d) cfa-bench
     64
     65run-c : c-bench
    6566        @echo
    6667        @echo '## C ##'
    67         @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./c-bench
     68        @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./$<
    6869        @printf 'source_size:\t%8d lines\n' `cat $(CFILES) | wc -l`
    6970        @printf 'redundant_type_annotations:%8d lines\n' `cat $(CFILES) | fgrep '/***/' -c`
    70         @printf 'binary_size:\t%8d bytes\n' `stat -c %s c-bench`
     71        @printf 'binary_size:\t%8d bytes\n' `stat -c %s $<`
    7172
    72 run-cfa: cfa-bench
     73run-cpp : cpp-bench
     74        @echo
     75        @echo '## C++ ##'
     76        @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./$<
     77        @printf 'source_size:\t%8d lines\n' `cat $(CPPFILES) | wc -l`
     78        @printf 'redundant_type_annotations:%8d lines\n' `cat $(CPPFILES) | fgrep '/***/' -c`
     79        @printf 'binary_size:\t%8d bytes\n' `stat -c %s $<`
     80
     81run-cppv : cpp-vbench
     82        @echo
     83        @echo '## C++obj ##'
     84        @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./$<
     85        @printf 'source_size:\t%8d lines\n' `cat $(CPPVFILES) | wc -l`
     86        @printf 'redundant_type_annotations:%8d lines\n' `cat $(CPPVFILES) | fgrep '/***/' -c`
     87        @printf 'binary_size:\t%8d bytes\n' `stat -c %s $<`
     88
     89run-cfa : cfa-bench
    7390        @echo
    7491        @echo '## Cforall ##'
    75         @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cfa-bench
     92        @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./$<
    7693        @printf 'source_size:\t%8d lines\n' `cat $(CFAFILES) | wc -l`
    7794        @printf 'redundant_type_annotations:%8d lines\n' `cat $(CFAFILES) | fgrep '/***/' -c`
    78         @printf 'binary_size:\t%8d bytes\n' `stat -c %s cfa-bench`
     95        @printf 'binary_size:\t%8d bytes\n' `stat -c %s $<`
    7996
    80 run-cpp: cpp-bench
    81         @echo
    82         @echo '## C++ ##'
    83         @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cpp-bench
    84         @printf 'source_size:\t%8d lines\n' `cat $(CPPFILES) | wc -l`
    85         @printf 'redundant_type_annotations:%8d lines\n' `cat $(CPPFILES) | fgrep '/***/' -c`
    86         @printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-bench`
    87 
    88 run-cppv: cpp-vbench
    89         @echo
    90         @echo '## C++obj ##'
    91         @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./cpp-vbench
    92         @printf 'source_size:\t%8d lines\n' `cat $(CPPVFILES) | wc -l`
    93         @printf 'redundant_type_annotations:%8d lines\n' `cat $(CPPVFILES) | fgrep '/***/' -c`
    94         @printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-vbench`
    95 
    96 run: run-c run-cfa run-cpp run-cppv
    97 
    98 # so make doesn't fail without dependency files
    99 %.d: ;
    100 
    101 # so make won't delete dependency files
    102 .PRECIOUS: %.d
    103 
    104 # include dependency files
    105 -include: $(COBJS:.o=.d)
    106 -include: $(CPPOBJS:.o=.d)
    107 -include: $(CFAOBJS:.o=.d)
    108 -include: c-bench.d
    109 -include: cpp-bench.d
    110 -include: cfa-bench.d
     97run : run-c run-cfa run-cpp run-cppv
  • doc/generic_types/evaluation/c-bench.c

    r12d3187 r2055098  
    3939
    4040int main(int argc, char** argv) {
    41         FILE * out = fopen("c-out.txt", "w");
     41        FILE * out = fopen("/dev/null", "w");
    4242        int maxi = 0, vali = 42;
    4343        struct stack si = new_stack(), ti;
  • doc/generic_types/evaluation/c-stack.c

    r12d3187 r2055098  
    1111void copy_stack(struct stack* s, const struct stack* t, void* (*copy)(const void*)) {
    1212        struct stack_node** crnt = &s->head;
    13         struct stack_node* next = t->head;
    14         while ( next ) {
     13        for ( struct stack_node* next = t->head; next; next = next->next ) {
    1514                *crnt = malloc(sizeof(struct stack_node)); /***/
    1615                **crnt = (struct stack_node){ copy(next->value) }; /***/
    1716                crnt = &(*crnt)->next;
    18                 next = next->next;
    1917        }
    2018        *crnt = 0;
     
    2220
    2321void clear_stack(struct stack* s, void (*free_el)(void*)) {
    24         struct stack_node* next = s->head;
    25         while ( next ) {
     22    for ( struct stack_node* next = s->head; next; ) {
    2623                struct stack_node* crnt = next;
    2724                next = crnt->next;
  • doc/generic_types/evaluation/cfa-bench.c

    r12d3187 r2055098  
    66
    77int main( int argc, char *argv[] ) {
    8         FILE * out = fopen( "cfa-out.txt", "w" );
     8        FILE * out = fopen( "/dev/null", "w" );
    99        int maxi = 0, vali = 42;
    1010        stack(int) si, ti;
  • doc/generic_types/evaluation/cfa-stack.c

    r12d3187 r2055098  
    1111forall(otype T) void ?{}(stack(T)* s, stack(T) t) {
    1212        stack_node(T)** crnt = &s->head;
    13         stack_node(T)* next = t.head;
    14         while ( next ) {
     13        for ( stack_node(T)* next = t.head; next; next = next->next ) {
    1514                *crnt = ((stack_node(T)*)malloc()){ next->value }; /***/
    1615                stack_node(T)* acrnt = *crnt;
    1716                crnt = &acrnt->next;
    18                 next = next->next;
    1917        }
    2018        *crnt = 0;
     
    4644
    4745forall(otype T) void clear(stack(T)* s) {
    48         stack_node(T)* next = s->head;
    49         while ( next ) {
     46    for ( stack_node(T)* next = s->head; next; ) {
    5047                stack_node(T)* crnt = next;
    5148                next = crnt->next;
  • doc/generic_types/evaluation/cpp-bench.cpp

    r12d3187 r2055098  
    77
    88int main(int argc, char** argv) {
    9         std::ofstream out{"cpp-out.txt"};
     9        std::ofstream out{"/dev/null"};
    1010        int maxi = 0, vali = 42;
    1111        stack<int> si, ti;
  • doc/generic_types/evaluation/cpp-stack.hpp

    r12d3187 r2055098  
    1313        void copy(const stack<T>& o) {
    1414                node** crnt = &head;
    15                 node* next = o.head;
    16                 while ( next ) {
     15                for ( node* next = o.head; next; next = next->next ) {
    1716                        *crnt = new node{ next->value }; /***/
    1817                        crnt = &(*crnt)->next;
    19                         next = next->next;
    2018                }
    2119                *crnt = nullptr;
     
    2321public:
    2422        void clear() {
    25                 node* next = head;
    26                 while ( next ) {
     23            for ( node* next = head; next; ) {
    2724                        node* crnt = next;
    2825                        next = crnt->next;
  • doc/generic_types/evaluation/cpp-vbench.cpp

    r12d3187 r2055098  
    77
    88int main(int argc, char** argv) {
    9         std::ofstream out{"cpp-vout.txt"};
     9        std::ofstream out{"/dev/null"};
    1010        integer maxi{ 0 }, vali{ 42 };
    1111        stack si, ti;
  • doc/generic_types/evaluation/cpp-vstack.cpp

    r12d3187 r2055098  
    66void stack::copy(const stack& o) {
    77        node** crnt = &head;
    8         node* next = o.head;
    9         while ( next ) {
     8        for ( node* next = o.head; next; next = next->next ) {
    109                *crnt = new node{ *next->value };
    1110                crnt = &(*crnt)->next;
    12                 next = next->next;
    1311        }
    1412        *crnt = nullptr;
     
    3533
    3634void stack::clear() {
    37         node* next = head;
    38         while ( next ) {
     35    for ( node* next = head; next; ) {
    3936                node* crnt = next;
    4037                next = crnt->next;
  • doc/generic_types/generic_types.tex

    r12d3187 r2055098  
    232232int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 :
    233233                                *(double *)t2 < *(double *)t1 ? 1 : 0; }
    234 double key = 5.0, vals[10] = { /* 10 floating-point values */ };
     234double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ };
    235235double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      $\C{// search sorted array}$
    236236\end{lstlisting}
     
    354354One of the known shortcomings of standard C is that it does not provide reusable type-safe abstractions for generic data structures and algorithms.
    355355Broadly speaking, there are three approaches to implement abstract data-structures in C.
    356 One approach is to write bespoke data structures for each context in which they are needed.
     356One approach is to write bespoke data-structures for each context in which they are needed.
    357357While this approach is flexible and supports integration with the C type-checker and tooling, it is also tedious and error-prone, especially for more complex data structures.
    358358A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@; an approach which does allow reuse of code for common functionality.
     
    542542\end{lstlisting}
    543543where the tuple variable-name serves the same purpose as the parameter name(s).
    544 Tuple variables can be composed of any types, except for array types, since array sizes are generally unknown.
     544Tuple variables can be composed of any types, except for array types, since array sizes are generally unknown in C.
    545545
    546546One way to access the tuple-variable components is with assignment or composition:
     
    552552\begin{lstlisting}
    553553[int, int] * p = &qr;                                           $\C{// tuple pointer}$
    554 int rem = qr.1;                                                         $\C{// access remainder}$
    555 int quo = div( 13, 5 ).0;                                       $\C{// access quotient}$
    556 p->0 = 5;                                                                       $\C{// change quotient}$
    557 bar( qr.1, qr );                                                        $\C{// pass remainder and quotient/remainder}$
    558 rem = [42, div( 13, 5 )].0.1;                           $\C{// access 2nd component of 1st component of tuple expression}$
     554int rem = qr`.1`;                                                       $\C{// access remainder}$
     555int quo = div( 13, 5 )`.0`;                                     $\C{// access quotient}$
     556p`->0` = 5;                                                                     $\C{// change quotient}$
     557bar( qr`.1`, qr );                                                      $\C{// pass remainder and quotient/remainder}$
     558rem = [42, div( 13, 5 )]`.0.1`;                         $\C{// access 2nd component of 1st component of tuple expression}$
    559559\end{lstlisting}
    560560
     
    616616This semantics means mass assignment differs from C cascading assignment (\eg @a = b = c@) in that conversions are applied in each individual assignment, which prevents data loss from the chain of conversions that can happen during a cascading assignment.
    617617For example, @[y, x] = 3.14@ performs the assignments @y = 3.14@ and @x = 3.14@, yielding @y == 3.14@ and @x == 3@;
    618 whereas C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@.
     618whereas, C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@.
    619619Finally, tuple assignment is an expression where the result type is the type of the left-hand side of the assignment, just like all other assignment expressions in C.
    620620This example shows mass, multiple, and cascading assignment used in one expression:
     
    742742\end{lstlisting}
    743743Hence, function parameter and return lists are flattened for the purposes of type unification allowing the example to pass expression resolution.
    744 This relaxation is possible by extending the thunk scheme described by \citet{Bilson03}.
     744This relaxation is possible by extending the thunk scheme described by~\citet{Bilson03}.
    745745Whenever a candidate's parameter structure does not exactly match the formal parameter's structure, a thunk is generated to specialize calls to the actual function:
    746746\begin{lstlisting}
     
    748748\end{lstlisting}
    749749so the thunk provides flattening and structuring conversions to inferred functions, improving the compatibility of tuples and polymorphism.
    750 These thunks take advantage of GCC C nested-functions to produce closures that have the usual function pointer signature.
     750These thunks take advantage of GCC C nested-functions to produce closures that have the usual function-pointer signature.
    751751
    752752
     
    829829\subsection{Implementation}
    830830
    831 Tuples are implemented in the \CFA translator via a transformation into generic types.
     831Tuples are implemented in the \CFA translator via a transformation into \emph{generic types}.
    832832For each $N$, the first time an $N$-tuple is seen in a scope a generic type with $N$ type parameters is generated, \eg:
    833833\begin{lstlisting}
     
    10861086Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    10871087
    1088 There is ongoing work on a wide range of \CFA feature extensions, including reference types, exceptions, concurrent primitives and modules.
     1088There is ongoing work on a wide range of \CFA feature extensions, including reference types, arrays with size, exceptions, concurrent primitives and modules.
    10891089(While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these additional extensions.)
    10901090In addition, there are interesting future directions for the polymorphism design.
     
    10921092\CFA polymorphic functions use dynamic virtual-dispatch;
    10931093the runtime overhead of this approach is low, but not as low as inlining, and it may be beneficial to provide a mechanism for performance-sensitive code.
    1094 Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types.
     1094Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types (\CC template specialization).
    10951095These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat.
    10961096In general, we believe separate compilation, producing smaller code, works well with loaded hardware-caches, which may offset the benefit of larger inlined-code.
     
    11171117Throughout, @/***/@ designates a counted redundant type annotation.
    11181118
    1119 \medskip\noindent
     1119\smallskip\noindent
    11201120\CFA
    11211121\begin{lstlisting}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
  • src/libcfa/concurrency/invoke.h

    r12d3187 r2055098  
    3838      };
    3939
    40       struct __thread_stack_t {
    41             struct thread_desc * top;
     40      struct __condition_stack_t {
     41            struct __condition_criterion_t * top;
    4242      };
    4343
     
    4848            struct thread_desc * pop_head( struct __thread_queue_t * );
    4949
    50             void ?{}( struct __thread_stack_t * );
    51             void push( struct __thread_stack_t *, struct thread_desc * );           
    52             struct thread_desc * pop( struct __thread_stack_t * );
     50            void ?{}( struct __condition_stack_t * );
     51            void push( struct __condition_stack_t *, struct __condition_criterion_t * );
     52            struct __condition_criterion_t * pop( struct __condition_stack_t * );
    5353
    5454            void ?{}(spinlock * this);
     
    8282            struct thread_desc * owner;               // current owner of the monitor
    8383            struct __thread_queue_t entry_queue;      // queue of threads that are blocked waiting for the monitor
    84             struct __thread_stack_t signal_stack;     // stack of threads to run next once we exit the monitor
     84            struct __condition_stack_t signal_stack;  // stack of conditions to run next once we exit the monitor
    8585            struct monitor_desc * stack_owner;        // if bulk acquiring was used we need to synchronize signals with an other monitor
    8686            unsigned int recursion;                   // monitor routines can be called recursively, we need to keep track of that
  • src/libcfa/concurrency/kernel

    r12d3187 r2055098  
    5555//-----------------------------------------------------------------------------
    5656// Processor
    57 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule };
     57enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };
     58
     59//TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
    5860struct FinishAction {
    5961        FinishOpCode action_code;
    6062        thread_desc * thrd;
    6163        spinlock * lock;
     64        spinlock ** locks;
     65        unsigned short lock_count;
     66        thread_desc ** thrds;
     67        unsigned short thrd_count;
    6268};
    6369static inline void ?{}(FinishAction * this) {
  • src/libcfa/concurrency/kernel.c

    r12d3187 r2055098  
    235235                ScheduleThread( this->finish.thrd );
    236236        }
     237        else if( this->finish.action_code == Release_Multi ) {
     238                for(int i = 0; i < this->finish.lock_count; i++) {
     239                        unlock( this->finish.locks[i] );
     240                }
     241        }
     242        else if( this->finish.action_code == Release_Multi_Schedule ) {
     243                for(int i = 0; i < this->finish.lock_count; i++) {
     244                        unlock( this->finish.locks[i] );
     245                }
     246                for(int i = 0; i < this->finish.thrd_count; i++) {
     247                        ScheduleThread( this->finish.thrds[i] );
     248                }
     249        }
    237250        else {
    238251                assert(this->finish.action_code == No_Action);
     
    335348        this_processor->finish.lock = lock;
    336349        this_processor->finish.thrd = thrd;
     350        suspend();
     351}
     352
     353void ScheduleInternal(spinlock ** locks, unsigned short count) {
     354        this_processor->finish.action_code = Release_Multi;
     355        this_processor->finish.locks = locks;
     356        this_processor->finish.lock_count = count;
     357        suspend();
     358}
     359
     360void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     361        this_processor->finish.action_code = Release_Multi_Schedule;
     362        this_processor->finish.locks = locks;
     363        this_processor->finish.lock_count = lock_count;
     364        this_processor->finish.thrds = thrds;
     365        this_processor->finish.thrd_count = thrd_count;
    337366        suspend();
    338367}
     
    529558}
    530559
    531 void ?{}( __thread_stack_t * this ) {
     560void ?{}( __condition_stack_t * this ) {
    532561        this->top = NULL;
    533562}
    534563
    535 void push( __thread_stack_t * this, thread_desc * t ) {
    536         assert(t->next != NULL);
     564void push( __condition_stack_t * this, __condition_criterion_t * t ) {
     565        assert( !t->next );
    537566        t->next = this->top;
    538567        this->top = t;
    539568}
    540569
    541 thread_desc * pop( __thread_stack_t * this ) {
    542         thread_desc * top = this->top;
     570__condition_criterion_t * pop( __condition_stack_t * this ) {
     571        __condition_criterion_t * top = this->top;
    543572        if( top ) {
    544573                this->top = top->next;
  • src/libcfa/concurrency/kernel_private.h

    r12d3187 r2055098  
    2626thread_desc * nextThread(cluster * this);
    2727
    28 void ScheduleInternal();
     28void ScheduleInternal(void);
    2929void ScheduleInternal(spinlock * lock);
    3030void ScheduleInternal(thread_desc * thrd);
    3131void ScheduleInternal(spinlock * lock, thread_desc * thrd);
     32void ScheduleInternal(spinlock ** locks, unsigned short count);
     33void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
    3234
    3335//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor

    r12d3187 r2055098  
    4646//-----------------------------------------------------------------------------
    4747// Internal scheduling
     48
     49struct __condition_criterion_t {
     50        bool ready;                                             //Whether or not the criterion is met (True if met)
     51        monitor_desc * target;                          //The monitor this criterion concerns
     52        struct __condition_node_t * owner;              //The parent node to which this criterion belongs
     53        __condition_criterion_t * next;         //Intrusive linked list Next field
     54};
     55
     56struct __condition_node_t {
     57        thread_desc * waiting_thread;                   //Thread that needs to be woken when all criteria are met
     58        __condition_criterion_t * criteria;     //Array of criteria (Criterions are contiguous in memory)
     59        unsigned short count;                           //Number of criterions in the criteria
     60        __condition_node_t * next;                      //Intrusive linked list Next field
     61};
     62
     63struct __condition_blocked_queue_t {
     64        __condition_node_t * head;
     65        __condition_node_t ** tail;
     66};
     67
     68void ?{}( __condition_blocked_queue_t * );
     69void append( __condition_blocked_queue_t *, __condition_node_t * );
     70__condition_node_t * pop_head( __condition_blocked_queue_t * );
     71
    4872struct condition {
    49         __thread_queue_t blocked;
    50         monitor_desc ** monitors;
    51         unsigned short monitor_count;
     73        __condition_blocked_queue_t blocked;    //Link list which contains the blocked threads as-well as the information needed to unblock them
     74        monitor_desc ** monitors;                       //Array of monitor pointers (Monitors are NOT contiguous in memory)
     75        unsigned short monitor_count;                   //Number of monitors in the array
    5276};
    5377
  • src/libcfa/concurrency/monitor.c

    r12d3187 r2055098  
    2020#include "libhdr.h"
    2121
    22 void set_owner( monitor_desc * this, thread_desc * owner ) {
    23         //Pass the monitor appropriately
    24         this->owner = owner;
    25 
    26         //We are passing the monitor to someone else, which means recursion level is not 0
    27         this->recursion = owner ? 1 : 0;
    28 }
     22//-----------------------------------------------------------------------------
     23// Forward declarations
     24static inline void set_owner( monitor_desc * this, thread_desc * owner );
     25static inline thread_desc * next_thread( monitor_desc * this );
     26
     27static inline void lock_all( spinlock ** locks, unsigned short count );
     28static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count );
     29static inline void unlock_all( spinlock ** locks, unsigned short count );
     30static inline void unlock_all( monitor_desc ** locks, unsigned short count );
     31
     32static inline void save_recursion   ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count );
     33static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count );
     34
     35static inline thread_desc * check_condition( __condition_criterion_t * );
     36static inline void brand_condition( condition * );
     37static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val );
     38
     39//-----------------------------------------------------------------------------
     40// Enter/Leave routines
     41
    2942
    3043extern "C" {
    31         void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) {
     44        void __enter_monitor_desc(monitor_desc * this) {
    3245                lock( &this->lock );
    3346                thread_desc * thrd = this_thread();
    3447
    35                 // //Update the stack owner
    36                 // this->stack_owner = leader;
    37 
    38                 LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
     48                LIB_DEBUG_PRINT_SAFE("%p Entering %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);
    3949
    4050                if( !this->owner ) {
     
    6171
    6272        // leave pseudo code :
    63         //      decrement level
    64         //      leve == 0 ?
    65         //              no : done
    66         //              yes :
    67         //                      signal stack empty ?
    68         //                              has leader :
    69         //                                      bulk acquiring means we don't own the signal stack
    70         //                                      ignore it but don't release the monitor
    71         //                              yes :
    72         //                                      next in entry queue is new owner
    73         //                              no :
    74         //                                      top of the signal stack is the owner
    75         //                                      context switch to him right away
    76         //
    77         void __leave_monitor_desc(monitor_desc * this, monitor_desc * leader) {
     73        //      TODO
     74        void __leave_monitor_desc(monitor_desc * this) {
    7875                lock( &this->lock );
    7976
    80                 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
    81 
    8277                thread_desc * thrd = this_thread();
    83                 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion );
     78
     79                LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);
     80                assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion );
    8481
    8582                //Leaving a recursion level, decrement the counter
     
    8986                //it means we don't need to do anything
    9087                if( this->recursion != 0) {
    91                         // this->stack_owner = leader;
    9288                        unlock( &this->lock );
    9389                        return;
    9490                }
    95                        
    96                 // //If we don't own the signal stack then just leave it to the owner
    97                 // if( this->stack_owner ) {
    98                 //      this->stack_owner = leader;
    99                 //      unlock( &this->lock );
    100                 //      return;
    101                 // }
    102 
    103                 //We are the stack owner and have left the last recursion level.
    104                 //We are in charge of passing the monitor
    105                 thread_desc * new_owner = 0;
    106 
    107                 //Check the signaller stack
    108                 new_owner = pop( &this->signal_stack );
    109                 if( new_owner ) {
    110                         //The signaller stack is not empty,
    111                         //transfer control immediately
    112                         set_owner( this, new_owner );
    113                         // this->stack_owner = leader;
    114                         ScheduleInternal( &this->lock, new_owner );
    115                         return;
    116                 }
    117                
    118                 // No signaller thread
    119                 // Get the next thread in the entry_queue
    120                 new_owner = pop_head( &this->entry_queue );
    121                 set_owner( this, new_owner );
    122 
    123                 // //Update the stack owner
    124                 // this->stack_owner = leader;
     91
     92                thread_desc * new_owner = next_thread( this );
    12593
    12694                //We can now let other threads in safely
     
    133101
    134102static inline void enter(monitor_desc ** monitors, int count) {
    135         __enter_monitor_desc( monitors[0], NULL );
    136         for(int i = 1; i < count; i++) {
    137                 __enter_monitor_desc( monitors[i], monitors[0] );
     103        for(int i = 0; i < count; i++) {
     104                __enter_monitor_desc( monitors[i] );
    138105        }
    139106}
    140107
    141108static inline void leave(monitor_desc ** monitors, int count) {
    142         __leave_monitor_desc( monitors[0], NULL );
    143         for(int i = count - 1; i >= 1; i--) {
    144                 __leave_monitor_desc( monitors[i], monitors[0] );
     109        for(int i = count - 1; i >= 0; i--) {
     110                __leave_monitor_desc( monitors[i] );
    145111        }
    146112}
     
    169135// Internal scheduling
    170136void wait( condition * this ) {
    171         assertf(false, "NO SUPPORTED");
    172         // LIB_DEBUG_FPRINTF("Waiting\n");
    173         thread_desc * this_thrd = this_thread();
    174 
    175         if( !this->monitors ) {
    176                 this->monitors = this_thrd->current_monitors;
    177                 this->monitor_count = this_thrd->current_monitor_count;
    178         }
     137        LIB_DEBUG_PRINT_SAFE("Waiting\n");
     138
     139        brand_condition( this );
     140
     141        //Check that everything is as expected
     142        assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors );
     143        assertf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
    179144
    180145        unsigned short count = this->monitor_count;
    181 
    182         //Check that everything is as expected
    183         assert( this->monitors != NULL );
    184         assert( this->monitor_count != 0 );
    185 
    186146        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    187147        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
    188148
    189         // LIB_DEBUG_FPRINTF("Getting ready to wait\n");
    190 
    191         //Loop on all the monitors and release the owner
    192         for( unsigned int i = 0; i < count; i++ ) {
    193                 monitor_desc * cur = this->monitors[i];
    194 
    195                 assert( cur );
    196 
    197                 // LIB_DEBUG_FPRINTF("cur %p lock %p\n", cur, &cur->lock);
    198 
    199                 //Store the locks for later
    200                 locks[i] = &cur->lock;
    201 
    202                 //Protect the monitors
    203                 lock( locks[i] );
    204                 {               
    205                         //Save the recursion levels
    206                         recursions[i] = cur->recursion;
    207 
    208                         //Release the owner
    209                         cur->recursion = 0;
    210                         cur->owner = NULL;
    211                 }
    212                 //Release the monitor
    213                 unlock( locks[i] );
    214         }
    215 
    216         // LIB_DEBUG_FPRINTF("Waiting now\n");
    217 
    218         //Everything is ready to go to sleep
    219         ScheduleInternal( locks, count );
     149        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
     150
     151        __condition_node_t waiter;
     152        waiter.waiting_thread = this_thread();
     153        waiter.count = count;
     154        waiter.next = NULL;
     155
     156        __condition_criterion_t criteria[count];
     157        for(int i = 0; i < count; i++) {
     158                criteria[i].ready  = false;
     159                criteria[i].target = this->monitors[i];
     160                criteria[i].owner  = &waiter;
     161                criteria[i].next   = NULL;
     162                LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );
     163        }
     164
     165        waiter.criteria = criteria;
     166        append( &this->blocked, &waiter );
     167
     168        lock_all( this->monitors, locks, count );
     169        save_recursion( this->monitors, recursions, count );
     170        //DON'T unlock, ask the kernel to do it
     171
     172        //Find the next thread(s) to run
     173        unsigned short thread_count = count;
     174        thread_desc * threads[ count ];
     175
     176        for( int i = 0; i < count; i++) {
     177                thread_desc * new_owner = next_thread( this->monitors[i] );
     178                thread_count = insert_unique( threads, i, new_owner );
     179        }
     180
     181        LIB_DEBUG_PRINT_SAFE("Will unblock: ");
     182        for(int i = 0; i < thread_count; i++) {
     183                LIB_DEBUG_PRINT_SAFE("%p ", threads[i]);
     184        }
     185        LIB_DEBUG_PRINT_SAFE("\n");
     186
     187        // Everything is ready to go to sleep
     188        ScheduleInternal( locks, count, threads, thread_count );
    220189
    221190
     
    224193
    225194        //We are back, restore the owners and recursions
    226         for( unsigned int i = 0; i < count; i++ ) {
    227                 monitor_desc * cur = this->monitors[i];
    228 
    229                 //Protect the monitors
    230                 lock( locks[i] );
    231                 {
    232                         //Release the owner
    233                         cur->owner = this_thrd;
    234                         cur->recursion = recursions[i];
    235                 }
    236                 //Release the monitor
    237                 unlock( locks[i] );
    238         }
    239 }
    240 
    241 static void __signal_internal( condition * this ) {
    242         assertf(false, "NO SUPPORTED");
    243         if( !this->blocked.head ) return;
     195        lock_all( locks, count );
     196        restore_recursion( this->monitors, recursions, count );
     197        unlock_all( locks, count );
     198}
     199
     200void signal( condition * this ) {
     201        if( !this->blocked.head ) {
     202                LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");
     203                return;
     204        }
    244205
    245206        //Check that everything is as expected
    246207        assert( this->monitors );
    247208        assert( this->monitor_count != 0 );
     209
     210        unsigned short count = this->monitor_count;
    248211       
    249212        LIB_DEBUG_DO(
    250                 if ( this->monitors != this_thread()->current_monitors ) {
    251                         abortf( "Signal on condition %p made outside of the correct monitor(s)", this );
     213                thread_desc * this_thrd = this_thread();
     214                if ( this->monitor_count != this_thrd->current_monitor_count ) {
     215                        abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->current_monitor_count );
    252216                } // if
     217
     218                for(int i = 0; i < this->monitor_count; i++) {
     219                        if ( this->monitors[i] != this_thrd->current_monitors[i] ) {
     220                                abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->current_monitors[i] );
     221                        } // if
     222                }
    253223        );
    254224
    255         monitor_desc * owner = this->monitors[0];
    256         lock( &owner->lock );
    257         {
    258                 thread_desc * unblock = pop_head( &this->blocked );
    259                 push( &owner->signal_stack, unblock );
    260         }
    261         unlock( &owner->lock );
    262 }
    263 
    264 void signal( condition * this ) {
    265         __signal_internal( this );
    266 }
     225        lock_all( this->monitors, NULL, count );
     226        LIB_DEBUG_PRINT_SAFE("Signalling");
     227
     228        __condition_node_t * node = pop_head( &this->blocked );
     229        for(int i = 0; i < count; i++) {
     230                __condition_criterion_t * crit = &node->criteria[i];
     231                LIB_DEBUG_PRINT_SAFE(" %p", crit->target);
     232                assert( !crit->ready );
     233                push( &crit->target->signal_stack, crit );
     234        }
     235
     236        LIB_DEBUG_PRINT_SAFE("\n");
     237
     238        unlock_all( this->monitors, count );
     239}
     240
     241//-----------------------------------------------------------------------------
     242// Utilities
     243
     244static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
     245        //Pass the monitor appropriately
     246        this->owner = owner;
     247
     248        //We are passing the monitor to someone else, which means recursion level is not 0
     249        this->recursion = owner ? 1 : 0;
     250}
     251
     252static inline thread_desc * next_thread( monitor_desc * this ) {
     253        //Check the signaller stack
     254        __condition_criterion_t * urgent = pop( &this->signal_stack );
     255        if( urgent ) {
     256                //The signaller stack is not empty,
     257                //regardless of if we are ready to baton pass,
     258                //we need to set the monitor as in use
     259                set_owner( this,  urgent->owner->waiting_thread );
     260
     261                return check_condition( urgent );
     262        }
     263
     264        // No signaller thread
     265        // Get the next thread in the entry_queue
     266        thread_desc * new_owner = pop_head( &this->entry_queue );
     267        set_owner( this, new_owner );
     268
     269        return new_owner;
     270}
     271
     272static inline void lock_all( spinlock ** locks, unsigned short count ) {
     273        for( int i = 0; i < count; i++ ) {
     274                lock( locks[i] );
     275        }
     276}
     277
     278static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count ) {
     279        for( int i = 0; i < count; i++ ) {
     280                spinlock * l = &source[i]->lock;
     281                lock( l );
     282                if(locks) locks[i] = l;
     283        }
     284}
     285
     286static inline void unlock_all( spinlock ** locks, unsigned short count ) {
     287        for( int i = 0; i < count; i++ ) {
     288                unlock( locks[i] );
     289        }
     290}
     291
     292static inline void unlock_all( monitor_desc ** locks, unsigned short count ) {
     293        for( int i = 0; i < count; i++ ) {
     294                unlock( &locks[i]->lock );
     295        }
     296}
     297
     298
     299static inline void save_recursion   ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count ) {
     300        for( int i = 0; i < count; i++ ) {
     301                recursions[i] = ctx[i]->recursion;
     302        }
     303}
     304
     305static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count ) {
     306        for( int i = 0; i < count; i++ ) {
     307                ctx[i]->recursion = recursions[i];
     308        }
     309}
     310
     311// Function has 2 different behavior
     312// 1 - Marks a monitors as being ready to run
     313// 2 - Checks if all the monitors are ready to run
     314//     if so return the thread to run
     315static inline thread_desc * check_condition( __condition_criterion_t * target ) {
     316        __condition_node_t * node = target->owner;
     317        unsigned short count = node->count;
     318        __condition_criterion_t * criteria = node->criteria;
     319
     320        bool ready2run = true;
     321
     322        for(    int i = 0; i < count; i++ ) {
     323                LIB_DEBUG_PRINT_SAFE( "Checking %p for %p\n", &criteria[i], target );
     324                if( &criteria[i] == target ) {
     325                        criteria[i].ready = true;
     326                        LIB_DEBUG_PRINT_SAFE( "True\n" );
     327                }
     328
     329                ready2run = criteria[i].ready && ready2run;
     330        }
     331
     332        LIB_DEBUG_PRINT_SAFE( "Runing %i\n", ready2run );
     333        return ready2run ? node->waiting_thread : NULL;
     334}
     335
     336static inline void brand_condition( condition * this ) {
     337        thread_desc * thrd = this_thread();
     338        if( !this->monitors ) {
     339                LIB_DEBUG_PRINT_SAFE("Branding\n");
     340                assertf( thrd->current_monitors != NULL, "No current monitor to brand condition", thrd->current_monitors );
     341                this->monitors = thrd->current_monitors;
     342                this->monitor_count = thrd->current_monitor_count;
     343        }
     344}
     345
     346static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ) {
     347        for(int i = 0; i < end; i++) {
     348                if( thrds[i] == val ) return end;
     349        }
     350
     351        thrds[end] = val;
     352        return end + 1;
     353}
     354
     355void ?{}( __condition_blocked_queue_t * this ) {
     356        this->head = NULL;
     357        this->tail = &this->head;
     358}
     359
     360void append( __condition_blocked_queue_t * this, __condition_node_t * c ) {
     361        assert(this->tail != NULL);
     362        *this->tail = c;
     363        this->tail = &c->next;
     364}
     365
     366__condition_node_t * pop_head( __condition_blocked_queue_t * this ) {
     367        __condition_node_t * head = this->head;
     368        if( head ) {
     369                this->head = head->next;
     370                if( !head->next ) {
     371                        this->tail = &this->head;
     372                }
     373                head->next = NULL;
     374        }
     375        return head;
     376}
  • src/libcfa/interpose.c

    r12d3187 r2055098  
    2626
    2727#include "libhdr/libdebug.h"
     28#include "libhdr/libtools.h"
    2829#include "startup.h"
    29 
    30 void abortf( const char *fmt, ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));
    3130
    3231void interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
     
    115114static char abort_text[ abort_text_size ];
    116115
    117 void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
    118         void * kernel_data = kernel_abort();
    119        
    120         int len;
    121        
    122         if( fmt ) {
    123                 va_list args;
    124                 va_start( args, fmt );
     116extern "C" {
     117        void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
     118                void * kernel_data = kernel_abort();
    125119
    126                 len = vsnprintf( abort_text, abort_text_size, fmt, args );
     120                int len;
    127121
    128                 va_end( args );
     122                if( fmt ) {
     123                        va_list args;
     124                        va_start( args, fmt );
    129125
     126                        len = vsnprintf( abort_text, abort_text_size, fmt, args );
     127
     128                        va_end( args );
     129
     130                        __lib_debug_write( STDERR_FILENO, abort_text, len );
     131                        __lib_debug_write( STDERR_FILENO, "\n", 1 );
     132                }
     133
     134                len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld)\n", (long int)getpid() ); // use UNIX pid (versus getPid)
    130135                __lib_debug_write( STDERR_FILENO, abort_text, len );
    131                 __lib_debug_write( STDERR_FILENO, "\n", 1 );
    132         }
    133 
    134         len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld)\n", (long int)getpid() ); // use UNIX pid (versus getPid)
    135         __lib_debug_write( STDERR_FILENO, abort_text, len );
    136136
    137137
    138         kernel_abort_msg( kernel_data, abort_text, abort_text_size );
     138                kernel_abort_msg( kernel_data, abort_text, abort_text_size );
    139139
    140         libc_abort();
     140                libc_abort();
     141        }
    141142}
  • src/libcfa/libhdr/libtools.h

    r12d3187 r2055098  
    2222// } // libAbort
    2323
    24 #define abortf(...) abort();
    25 
     24#ifdef __cforall
     25extern "C" {
     26#endif
     27void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));
     28#ifdef __cforall
     29}
     30#endif
    2631
    2732#endif //__LIB_TOOLS_H__
  • src/libcfa/rational

    r12d3187 r2055098  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Wed May  4 14:11:45 2016
    15 // Update Count     : 16
     14// Last Modified On : Mon May  1 08:25:06 2017
     15// Update Count     : 33
    1616//
     17
    1718#ifndef RATIONAL_H
    1819#define RATIONAL_H
     
    2122
    2223// implementation
     24typedef long int RationalImpl;
    2325struct Rational {
    24         long int numerator, denominator;                                        // invariant: denominator > 0
     26        RationalImpl numerator, denominator;                                    // invariant: denominator > 0
    2527}; // Rational
    2628
     
    3133// constructors
    3234void ?{}( Rational * r );
    33 void ?{}( Rational * r, long int n );
    34 void ?{}( Rational * r, long int n, long int d );
     35void ?{}( Rational * r, RationalImpl n );
     36void ?{}( Rational * r, RationalImpl n, RationalImpl d );
    3537
    36 // getter/setter for numerator/denominator
    37 long int numerator( Rational r );
    38 long int numerator( Rational r, long int n );
    39 long int denominator( Rational r );
    40 long int denominator( Rational r, long int d );
     38// getter for numerator/denominator
     39RationalImpl numerator( Rational r );
     40RationalImpl denominator( Rational r );
     41[ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational src );
     42// setter for numerator/denominator
     43RationalImpl numerator( Rational r, RationalImpl n );
     44RationalImpl denominator( Rational r, RationalImpl d );
    4145
    4246// comparison
     
    5761// conversion
    5862double widen( Rational r );
    59 Rational narrow( double f, long int md );
     63Rational narrow( double f, RationalImpl md );
    6064
    6165// I/O
  • src/libcfa/rational.c

    r12d3187 r2055098  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul  9 11:18:04 2016
    13 // Update Count     : 40
     12// Last Modified On : Thu Apr 27 17:05:06 2017
     13// Update Count     : 51
    1414//
    1515
     
    3030// Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce rationals.
    3131// alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
    32 static long int gcd( long int a, long int b ) {
     32static RationalImpl gcd( RationalImpl a, RationalImpl b ) {
    3333        for ( ;; ) {                                                                            // Euclid's algorithm
    34                 long int r = a % b;
     34                RationalImpl r = a % b;
    3535          if ( r == 0 ) break;
    3636                a = b;
     
    4040} // gcd
    4141
    42 static long int simplify( long int *n, long int *d ) {
     42static RationalImpl simplify( RationalImpl *n, RationalImpl *d ) {
    4343        if ( *d == 0 ) {
    4444                serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
     
    5656} // rational
    5757
    58 void ?{}( Rational * r, long int n ) {
     58void ?{}( Rational * r, RationalImpl n ) {
    5959        r{ n, 1 };
    6060} // rational
    6161
    62 void ?{}( Rational * r, long int n, long int d ) {
    63         long int t = simplify( &n, &d );                                        // simplify
     62void ?{}( Rational * r, RationalImpl n, RationalImpl d ) {
     63        RationalImpl t = simplify( &n, &d );                            // simplify
    6464        r->numerator = n / t;
    6565        r->denominator = d / t;
     
    6767
    6868
    69 // getter/setter for numerator/denominator
    70 
    71 long int numerator( Rational r ) {
     69// getter for numerator/denominator
     70
     71RationalImpl numerator( Rational r ) {
    7272        return r.numerator;
    7373} // numerator
    7474
    75 long int numerator( Rational r, long int n ) {
    76         long int prev = r.numerator;
    77         long int t = gcd( abs( n ), r.denominator );            // simplify
     75RationalImpl denominator( Rational r ) {
     76        return r.denominator;
     77} // denominator
     78
     79[ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational src ) {
     80        return *dest = src.[ numerator, denominator ];
     81}
     82
     83// setter for numerator/denominator
     84
     85RationalImpl numerator( Rational r, RationalImpl n ) {
     86        RationalImpl prev = r.numerator;
     87        RationalImpl t = gcd( abs( n ), r.denominator );                // simplify
    7888        r.numerator = n / t;
    7989        r.denominator = r.denominator / t;
     
    8191} // numerator
    8292
    83 long int denominator( Rational r ) {
    84         return r.denominator;
    85 } // denominator
    86 
    87 long int denominator( Rational r, long int d ) {
    88         long int prev = r.denominator;
    89         long int t = simplify( &r.numerator, &d );                      // simplify
     93RationalImpl denominator( Rational r, RationalImpl d ) {
     94        RationalImpl prev = r.denominator;
     95        RationalImpl t = simplify( &r.numerator, &d );                  // simplify
    9096        r.numerator = r.numerator / t;
    9197        r.denominator = d / t;
     
    170176
    171177// http://www.ics.uci.edu/~eppstein/numth/frap.c
    172 Rational narrow( double f, long int md ) {
     178Rational narrow( double f, RationalImpl md ) {
    173179        if ( md <= 1 ) {                                                                        // maximum fractional digits too small?
    174180                return (Rational){ f, 1};                                               // truncate fraction
     
    176182
    177183        // continued fraction coefficients
    178         long int m00 = 1, m11 = 1, m01 = 0, m10 = 0;
    179         long int ai, t;
     184        RationalImpl m00 = 1, m11 = 1, m01 = 0, m10 = 0;
     185        RationalImpl ai, t;
    180186
    181187        // find terms until denom gets too big
    182188        for ( ;; ) {
    183                 ai = (long int)f;
     189                ai = (RationalImpl)f;
    184190          if ( ! (m10 * ai + m11 <= md) ) break;
    185191                t = m00 * ai + m01;
     
    202208forall( dtype istype | istream( istype ) )
    203209istype * ?|?( istype *is, Rational *r ) {
    204         long int t;
     210        RationalImpl t;
    205211        is | &(r->numerator) | &(r->denominator);
    206212        t = simplify( &(r->numerator), &(r->denominator) );
  • src/tests/.expect/32/attributes.txt

    r12d3187 r2055098  
    1 attributes.c:74 error: cannot redefine typedef: ptrdiff_t
    2 attributes.c:75 error: cannot redefine typedef: size_t
    3 make: *** [attributes] Error 1
     1__attribute__ ((__nothrow__,__leaf__,__malloc__)) extern void *malloc(unsigned int __size);
     2__attribute__ ((__nothrow__,__leaf__)) extern void free(void *__ptr);
     3__attribute__ ((__nothrow__,__leaf__,__noreturn__)) extern void abort(void);
     4__attribute__ ((__nothrow__,__leaf__,__nonnull__(1))) extern int atexit(void (*__func)(void));
     5__attribute__ ((__nothrow__,__leaf__,__noreturn__)) extern void exit(int __status);
     6extern int printf(const char *__restrict __format, ...);
     7int __la__Fi___1(){
     8    int ___retval_la__i_1;
     9    L: __attribute__ ((unused)) ((void)1);
     10}
     11__attribute__ ((unused)) struct __anonymous0 {
     12};
     13static inline void ___constructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1);
     14static inline void ___constructor__F_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1);
     15static inline void ___destructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1);
     16static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1);
     17static inline void ___constructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
     18}
     19static inline void ___constructor__F_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
     20}
     21static inline void ___destructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1){
     22}
     23static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_P13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
     24    return ((struct __anonymous0 )___src__13s__anonymous0_1);
     25}
     26__attribute__ ((unused)) struct Agn1;
     27__attribute__ ((unused)) struct Agn2 {
     28};
     29static inline void ___constructor__F_P5sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1);
     30static inline void ___constructor__F_P5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1, struct Agn2 ___src__5sAgn2_1);
     31static inline void ___destructor__F_P5sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1);
     32static inline struct Agn2 ___operator_assign__F5sAgn2_P5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1, struct Agn2 ___src__5sAgn2_1);
     33static inline void ___constructor__F_P5sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1){
     34}
     35static inline void ___constructor__F_P5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1, struct Agn2 ___src__5sAgn2_1){
     36}
     37static inline void ___destructor__F_P5sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1){
     38}
     39static inline struct Agn2 ___operator_assign__F5sAgn2_P5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1, struct Agn2 ___src__5sAgn2_1){
     40    return ((struct Agn2 )___src__5sAgn2_1);
     41}
     42enum __attribute__ ((unused)) __anonymous1 {
     43    __E1__C13e__anonymous1_1,
     44};
     45enum __attribute__ ((unused)) Agn3;
     46enum __attribute__ ((packed)) Agn3 {
     47    __E2__C5eAgn3_1,
     48};
     49__attribute__ ((unused)) struct __anonymous2;
     50__attribute__ ((unused)) struct __anonymous3;
     51struct Fdl {
     52    __attribute__ ((unused)) int __f1__i_1;
     53    __attribute__ ((unused)) int __f2__i_1;
     54    __attribute__ ((unused,unused)) int __f3__i_1;
     55    __attribute__ ((unused)) int __f4__i_1;
     56    __attribute__ ((unused,unused)) int __f5__i_1;
     57    __attribute__ ((used,packed)) int __f6__i_1;
     58    __attribute__ ((used,unused,unused)) int __f7__i_1;
     59    __attribute__ ((used,used,unused)) int __f8__i_1;
     60    __attribute__ ((unused)) int __anonymous_object0;
     61    __attribute__ ((unused,unused)) int *__f9__Pi_1;
     62};
     63static inline void ___constructor__F_P4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1);
     64static inline void ___constructor__F_P4sFdl4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1, struct Fdl ___src__4sFdl_1);
     65static inline void ___destructor__F_P4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1);
     66static inline struct Fdl ___operator_assign__F4sFdl_P4sFdl4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1, struct Fdl ___src__4sFdl_1);
     67static inline void ___constructor__F_P4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1){
     68    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))) /* ?{} */);
     69    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))) /* ?{} */);
     70    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))) /* ?{} */);
     71    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))) /* ?{} */);
     72    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ?{} */);
     73    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     74    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     75    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     76    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     77}
     78static inline void ___constructor__F_P4sFdl4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1, struct Fdl ___src__4sFdl_1){
     79    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=___src__4sFdl_1.__f1__i_1) /* ?{} */);
     80    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=___src__4sFdl_1.__f2__i_1) /* ?{} */);
     81    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=___src__4sFdl_1.__f3__i_1) /* ?{} */);
     82    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=___src__4sFdl_1.__f4__i_1) /* ?{} */);
     83    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=___src__4sFdl_1.__f5__i_1) /* ?{} */);
     84    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))=___src__4sFdl_1.__f6__i_1) /* ?{} */);
     85    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))=___src__4sFdl_1.__f7__i_1) /* ?{} */);
     86    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))=___src__4sFdl_1.__f8__i_1) /* ?{} */);
     87    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))=___src__4sFdl_1.__f9__Pi_1) /* ?{} */);
     88}
     89static inline void ___destructor__F_P4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1){
     90    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ^?{} */);
     91    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ^?{} */);
     92    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ^?{} */);
     93    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ^?{} */);
     94    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ^?{} */);
     95    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))) /* ^?{} */);
     96    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))) /* ^?{} */);
     97    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))) /* ^?{} */);
     98    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))) /* ^?{} */);
     99}
     100static inline struct Fdl ___operator_assign__F4sFdl_P4sFdl4sFdl_autogen___1(struct Fdl *___dst__P4sFdl_1, struct Fdl ___src__4sFdl_1){
     101    ((void)((*___dst__P4sFdl_1).__f1__i_1=___src__4sFdl_1.__f1__i_1));
     102    ((void)((*___dst__P4sFdl_1).__f2__i_1=___src__4sFdl_1.__f2__i_1));
     103    ((void)((*___dst__P4sFdl_1).__f3__i_1=___src__4sFdl_1.__f3__i_1));
     104    ((void)((*___dst__P4sFdl_1).__f4__i_1=___src__4sFdl_1.__f4__i_1));
     105    ((void)((*___dst__P4sFdl_1).__f5__i_1=___src__4sFdl_1.__f5__i_1));
     106    ((void)((*___dst__P4sFdl_1).__f6__i_1=___src__4sFdl_1.__f6__i_1));
     107    ((void)((*___dst__P4sFdl_1).__f7__i_1=___src__4sFdl_1.__f7__i_1));
     108    ((void)((*___dst__P4sFdl_1).__f8__i_1=___src__4sFdl_1.__f8__i_1));
     109    ((void)((*___dst__P4sFdl_1).__f9__Pi_1=___src__4sFdl_1.__f9__Pi_1));
     110    return ((struct Fdl )___src__4sFdl_1);
     111}
     112static inline void ___constructor__F_P4sFdli_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1){
     113    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     114    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))) /* ?{} */);
     115    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))) /* ?{} */);
     116    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))) /* ?{} */);
     117    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ?{} */);
     118    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     119    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     120    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     121    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     122}
     123static inline void ___constructor__F_P4sFdlii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1){
     124    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     125    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     126    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))) /* ?{} */);
     127    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))) /* ?{} */);
     128    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ?{} */);
     129    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     130    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     131    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     132    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     133}
     134static inline void ___constructor__F_P4sFdliii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1){
     135    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     136    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     137    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     138    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))) /* ?{} */);
     139    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ?{} */);
     140    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     141    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     142    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     143    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     144}
     145static inline void ___constructor__F_P4sFdliiii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1){
     146    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     147    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     148    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     149    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     150    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))) /* ?{} */);
     151    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     152    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     153    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     154    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     155}
     156static inline void ___constructor__F_P4sFdliiiii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1, int __f5__i_1){
     157    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     158    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     159    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     160    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     161    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=__f5__i_1) /* ?{} */);
     162    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))) /* ?{} */);
     163    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     164    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     165    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     166}
     167static inline void ___constructor__F_P4sFdliiiiii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1, int __f5__i_1, int __f6__i_1){
     168    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     169    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     170    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     171    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     172    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=__f5__i_1) /* ?{} */);
     173    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))=__f6__i_1) /* ?{} */);
     174    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))) /* ?{} */);
     175    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     176    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     177}
     178static inline void ___constructor__F_P4sFdliiiiiii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1, int __f5__i_1, int __f6__i_1, int __f7__i_1){
     179    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     180    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     181    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     182    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     183    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=__f5__i_1) /* ?{} */);
     184    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))=__f6__i_1) /* ?{} */);
     185    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))=__f7__i_1) /* ?{} */);
     186    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))) /* ?{} */);
     187    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     188}
     189static inline void ___constructor__F_P4sFdliiiiiiii_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1, int __f5__i_1, int __f6__i_1, int __f7__i_1, int __f8__i_1){
     190    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     191    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     192    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     193    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     194    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=__f5__i_1) /* ?{} */);
     195    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))=__f6__i_1) /* ?{} */);
     196    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))=__f7__i_1) /* ?{} */);
     197    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))=__f8__i_1) /* ?{} */);
     198    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))) /* ?{} */);
     199}
     200static inline void ___constructor__F_P4sFdliiiiiiiiPi_autogen___1(struct Fdl *___dst__P4sFdl_1, int __f1__i_1, int __f2__i_1, int __f3__i_1, int __f4__i_1, int __f5__i_1, int __f6__i_1, int __f7__i_1, int __f8__i_1, int *__f9__Pi_1){
     201    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f1__i_1)))=__f1__i_1) /* ?{} */);
     202    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f2__i_1)))=__f2__i_1) /* ?{} */);
     203    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f3__i_1)))=__f3__i_1) /* ?{} */);
     204    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f4__i_1)))=__f4__i_1) /* ?{} */);
     205    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f5__i_1)))=__f5__i_1) /* ?{} */);
     206    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f6__i_1)))=__f6__i_1) /* ?{} */);
     207    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f7__i_1)))=__f7__i_1) /* ?{} */);
     208    ((void)((*((int *)(&(*___dst__P4sFdl_1).__f8__i_1)))=__f8__i_1) /* ?{} */);
     209    ((void)((*((int **)(&(*___dst__P4sFdl_1).__f9__Pi_1)))=__f9__Pi_1) /* ?{} */);
     210}
     211__attribute__ ((unused)) int __f__Fi___1() asm ( "xyz" );
     212__attribute__ ((used,used)) const int __vd1__Ci_1;
     213__attribute__ ((used,unused)) const int __vd2__Ci_1;
     214__attribute__ ((used,used,used,used)) const int *__vd3__PCi_1;
     215__attribute__ ((used,used,unused,used,unused)) const int *__vd4__PCi_1;
     216__attribute__ ((used,used,used)) const int __vd5__A0Ci_1[((unsigned int )5)];
     217__attribute__ ((used,used,unused,used)) const int __vd6__A0Ci_1[((unsigned int )5)];
     218__attribute__ ((used,used,used,used)) const int (*__vd7__PFCi___1)();
     219__attribute__ ((used,used,unused,used,used)) const int (*__vd8__PFCi___1)();
     220__attribute__ ((unused,used)) int __f1__Fi___1();
     221__attribute__ ((unused)) int __f1__Fi___1(){
     222    int ___retval_f1__i_1;
     223}
     224__attribute__ ((unused,unused,unused,used)) int **const __f2__FCPPi___1();
     225__attribute__ ((unused,unused,unused)) int **const __f2__FCPPi___1(){
     226    int **const ___retval_f2__CPPi_1;
     227}
     228__attribute__ ((unused,used,unused)) int (*__f3__FPA0i_i__1(int __anonymous_object1))[];
     229__attribute__ ((unused,unused)) int (*__f3__FPA0i_i__1(int __p__i_1))[]{
     230    int (*___retval_f3__PA0i_1)[];
     231}
     232__attribute__ ((unused,used,unused)) int (*__f4__FPFi_i____1())(int __anonymous_object2);
     233__attribute__ ((unused,unused)) int (*__f4__FPFi_i____1())(int __anonymous_object3){
     234    int (*___retval_f4__PFi_i__1)(int __anonymous_object4);
     235}
     236int __vtr__Fi___1(){
     237    int ___retval_vtr__i_1;
     238    __attribute__ ((unused,unused,used)) int __t1__i_2;
     239    __attribute__ ((unused,unused,unused,unused,unused)) int **__t2__PPi_2;
     240    __attribute__ ((unused,unused,unused)) int __t3__A0i_2[((unsigned int )5)];
     241    __attribute__ ((unused,unused,unused,unused,unused)) int **__t4__A0PPi_2[((unsigned int )5)];
     242    __attribute__ ((unused,unused,unused)) int __t5__Fi___2();
     243    __attribute__ ((unused,unused,unused,unused)) int *__t6__FPi___2();
     244}
     245int __ipd1__Fi_ii__1(__attribute__ ((unused,unused,unused)) int __p__i_1, __attribute__ ((unused,unused,unused)) int __q__i_1);
     246int __ipd1__Fi_ii__1(__attribute__ ((unused,unused,unused)) int __p__i_1, __attribute__ ((unused,unused,unused)) int __q__i_1){
     247    int ___retval_ipd1__i_1;
     248}
     249int __ipd2__Fi_PiPi__1(__attribute__ ((unused,unused,unused,unused)) int *__p__Pi_1, __attribute__ ((unused,unused,unused)) int *__q__Pi_1);
     250int __ipd2__Fi_PiPi__1(__attribute__ ((unused,unused,unused,unused)) int *__p__Pi_1, __attribute__ ((unused,unused,unused)) int *__q__Pi_1){
     251    int ___retval_ipd2__i_1;
     252}
     253int __ipd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__p__Pi_1, __attribute__ ((unused,unused,unused)) int *__q__Pi_1);
     254int __ipd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__p__Pi_1, __attribute__ ((unused,unused,unused)) int *__q__Pi_1){
     255    int ___retval_ipd3__i_1;
     256}
     257int __ipd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__p__PFi___1)(), __attribute__ ((unused,unused,unused)) int (*__q__PFi___1)());
     258int __ipd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__p__PFi___1)(), __attribute__ ((unused,unused,unused)) int (*__q__PFi___1)()){
     259    int ___retval_ipd4__i_1;
     260}
     261int __tpr1__Fi_i__1(__attribute__ ((unused,unused,unused)) int __Foo__i_1);
     262int __tpr2__Fi_PPi__1(__attribute__ ((unused,unused,unused,unused,unused,unused)) int **__Foo__PPi_1);
     263int __tpr3__Fi_Pi__1(__attribute__ ((unused,unused,unused)) int *__Foo__Pi_1);
     264int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) int (*__anonymous_object5)(__attribute__ ((unused,unused)) int __anonymous_object6[((unsigned int )5)]));
     265int __tpr5__Fi_PFi____1(__attribute__ ((unused,unused,unused)) int (*__Foo__PFi___1)());
     266int __tpr6__Fi_PFi____1(__attribute__ ((unused,unused,unused)) int (*__Foo__PFi___1)());
     267int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) int (*__anonymous_object7)(__attribute__ ((unused)) int (*__anonymous_object8)(__attribute__ ((unused,unused)) int __anonymous_object9)));
     268int __ad__Fi___1(){
     269    int ___retval_ad__i_1;
     270    __attribute__ ((used,unused)) int __ad1__i_2;
     271    __attribute__ ((unused,unused,unused)) int *__ad2__Pi_2;
     272    __attribute__ ((unused,unused,unused)) int __ad3__A0i_2[((unsigned int )5)];
     273    __attribute__ ((unused,unused,unused,unused,unused)) int (*__ad4__PA0i_2)[((unsigned int )10)];
     274    __attribute__ ((unused,unused,unused,unused,used)) int __ad5__i_2;
     275    __attribute__ ((unused,unused,unused,unused,unused)) int __ad6__Fi___2();
     276    ((void)sizeof(__attribute__ ((unused,unused)) int ));
     277    ((void)sizeof(__attribute__ ((unused,unused,unused,unused)) int **));
     278    ((void)sizeof(__attribute__ ((unused,unused,unused)) int [5]));
     279    ((void)sizeof(__attribute__ ((unused,unused,unused)) int (*)[10]));
     280    ((void)sizeof(__attribute__ ((unused,unused,unused)) int ()));
     281    __attribute__ ((unused)) struct __anonymous4 {
     282        int __i__i_2;
     283    };
     284    inline void ___constructor__F_P13s__anonymous4_autogen___2(struct __anonymous4 *___dst__P13s__anonymous4_2){
     285        ((void)((*((int *)(&(*___dst__P13s__anonymous4_2).__i__i_2)))) /* ?{} */);
     286    }
     287    inline void ___constructor__F_P13s__anonymous413s__anonymous4_autogen___2(struct __anonymous4 *___dst__P13s__anonymous4_2, struct __anonymous4 ___src__13s__anonymous4_2){
     288        ((void)((*((int *)(&(*___dst__P13s__anonymous4_2).__i__i_2)))=___src__13s__anonymous4_2.__i__i_2) /* ?{} */);
     289    }
     290    inline void ___destructor__F_P13s__anonymous4_autogen___2(struct __anonymous4 *___dst__P13s__anonymous4_2){
     291        ((void)((*((int *)(&(*___dst__P13s__anonymous4_2).__i__i_2)))) /* ^?{} */);
     292    }
     293    inline struct __anonymous4 ___operator_assign__F13s__anonymous4_P13s__anonymous413s__anonymous4_autogen___2(struct __anonymous4 *___dst__P13s__anonymous4_2, struct __anonymous4 ___src__13s__anonymous4_2){
     294        ((void)((*___dst__P13s__anonymous4_2).__i__i_2=___src__13s__anonymous4_2.__i__i_2));
     295        return ((struct __anonymous4 )___src__13s__anonymous4_2);
     296    }
     297    inline void ___constructor__F_P13s__anonymous4i_autogen___2(struct __anonymous4 *___dst__P13s__anonymous4_2, int __i__i_2){
     298        ((void)((*((int *)(&(*___dst__P13s__anonymous4_2).__i__i_2)))=__i__i_2) /* ?{} */);
     299    }
     300    ((void)sizeof(struct __anonymous4 ));
     301    enum __attribute__ ((unused)) __anonymous5 {
     302        __R__C13e__anonymous5_2,
     303    };
     304    inline void ___constructor__F_P13e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__P13e__anonymous5_2){
     305    }
     306    inline void ___constructor__F_P13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__P13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
     307        ((void)((*___dst__P13e__anonymous5_2)=___src__13e__anonymous5_2));
     308    }
     309    inline void ___destructor__F_P13e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__P13e__anonymous5_2){
     310    }
     311    inline enum __anonymous5 ___operator_assign__F13e__anonymous5_P13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__P13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
     312        return ((enum __anonymous5 )((*___dst__P13e__anonymous5_2)=___src__13e__anonymous5_2));
     313    }
     314    ((void)sizeof(enum __anonymous5 ));
     315}
     316int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object10, __attribute__ ((unused,unused,unused)) int *__anonymous_object11);
     317int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) int **__anonymous_object12, __attribute__ ((unused,unused,unused,unused)) int **__anonymous_object13);
     318int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object14, __attribute__ ((unused,unused,unused)) int *__anonymous_object15);
     319int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object16)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object17)());
     320int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object18)(__attribute__ ((unused)) int __anonymous_object19), __attribute__ ((unused,unused,unused)) int (*__anonymous_object20)(__attribute__ ((unused)) int __anonymous_object21));
     321int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object22)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object23)());
     322int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object24)(__attribute__ ((unused)) int __anonymous_object25), __attribute__ ((unused,unused,unused)) int (*__anonymous_object26)(__attribute__ ((unused)) int __anonymous_object27));
     323struct Vad {
     324    __attribute__ ((unused)) int __anonymous_object28;
     325    __attribute__ ((unused,unused)) int *__anonymous_object29;
     326    __attribute__ ((unused,unused)) int __anonymous_object30[((unsigned int )10)];
     327    __attribute__ ((unused,unused)) int (*__anonymous_object31)();
     328};
     329static inline void ___constructor__F_P4sVad_autogen___1(struct Vad *___dst__P4sVad_1);
     330static inline void ___constructor__F_P4sVad4sVad_autogen___1(struct Vad *___dst__P4sVad_1, struct Vad ___src__4sVad_1);
     331static inline void ___destructor__F_P4sVad_autogen___1(struct Vad *___dst__P4sVad_1);
     332static inline struct Vad ___operator_assign__F4sVad_P4sVad4sVad_autogen___1(struct Vad *___dst__P4sVad_1, struct Vad ___src__4sVad_1);
     333static inline void ___constructor__F_P4sVad_autogen___1(struct Vad *___dst__P4sVad_1){
     334}
     335static inline void ___constructor__F_P4sVad4sVad_autogen___1(struct Vad *___dst__P4sVad_1, struct Vad ___src__4sVad_1){
     336}
     337static inline void ___destructor__F_P4sVad_autogen___1(struct Vad *___dst__P4sVad_1){
     338}
     339static inline struct Vad ___operator_assign__F4sVad_P4sVad4sVad_autogen___1(struct Vad *___dst__P4sVad_1, struct Vad ___src__4sVad_1){
     340    return ((struct Vad )___src__4sVad_1);
     341}
  • src/tests/.expect/64/attributes.txt

    r12d3187 r2055098  
    99    L: __attribute__ ((unused)) ((void)1);
    1010}
    11 struct __attribute__ ((unused)) __anonymous0 {
     11__attribute__ ((unused)) struct __anonymous0 {
    1212};
    1313static inline void ___constructor__F_P13s__anonymous0_autogen___1(struct __anonymous0 *___dst__P13s__anonymous0_1);
     
    2424    return ((struct __anonymous0 )___src__13s__anonymous0_1);
    2525}
    26 struct __attribute__ ((unused)) Agn1;
    27 struct __attribute__ ((unused)) Agn2 {
     26__attribute__ ((unused)) struct Agn1;
     27__attribute__ ((unused)) struct Agn2 {
    2828};
    2929static inline void ___constructor__F_P5sAgn2_autogen___1(struct Agn2 *___dst__P5sAgn2_1);
     
    4747    __E2__C5eAgn3_1,
    4848};
    49 struct __attribute__ ((unused)) __anonymous2;
    50 struct __attribute__ ((unused)) __anonymous3;
     49__attribute__ ((unused)) struct __anonymous2;
     50__attribute__ ((unused)) struct __anonymous3;
    5151struct Fdl {
    5252    __attribute__ ((unused)) int __f1__i_1;
     
    234234    int (*___retval_f4__PFi_i__1)(int __anonymous_object4);
    235235}
    236 __attribute__ ((__nothrow__,__leaf__,__malloc__)) extern void *malloc(long unsigned int __size);
    237 __attribute__ ((__nothrow__,__leaf__)) extern void free(void *__ptr);
    238 __attribute__ ((__nothrow__,__leaf__,__noreturn__)) extern void abort(void);
    239 __attribute__ ((__nothrow__,__leaf__,__nonnull__(1))) extern int atexit0(void (*__func)(void), void *__anonymous_object5, void *__anonymous_object6);
    240 __attribute__ ((__nothrow__,__leaf__,__noreturn__)) extern void exit(int __status);
    241 __attribute__ ((format(printf, 1, 2))) extern int printf(const char *__restrict __format, ...);
    242236int __vtr__Fi___1(){
    243237    int ___retval_vtr__i_1;
     
    268262int __tpr2__Fi_PPi__1(__attribute__ ((unused,unused,unused,unused,unused,unused)) int **__Foo__PPi_1);
    269263int __tpr3__Fi_Pi__1(__attribute__ ((unused,unused,unused)) int *__Foo__Pi_1);
    270 int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) int (*__anonymous_object7)(__attribute__ ((unused,unused)) int __anonymous_object8[((long unsigned int )5)]));
     264int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) int (*__anonymous_object5)(__attribute__ ((unused,unused)) int __anonymous_object6[((long unsigned int )5)]));
    271265int __tpr5__Fi_PFi____1(__attribute__ ((unused,unused,unused)) int (*__Foo__PFi___1)());
    272266int __tpr6__Fi_PFi____1(__attribute__ ((unused,unused,unused)) int (*__Foo__PFi___1)());
    273 int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) int (*__anonymous_object9)(__attribute__ ((unused)) int (*__anonymous_object10)(__attribute__ ((unused,unused)) int __anonymous_object11)));
     267int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) int (*__anonymous_object7)(__attribute__ ((unused)) int (*__anonymous_object8)(__attribute__ ((unused,unused)) int __anonymous_object9)));
    274268int __ad__Fi___1(){
    275269    int ___retval_ad__i_1;
     
    285279    ((void)sizeof(__attribute__ ((unused,unused,unused)) int (*)[10]));
    286280    ((void)sizeof(__attribute__ ((unused,unused,unused)) int ()));
    287     struct __attribute__ ((unused)) __anonymous4 {
     281    __attribute__ ((unused)) struct __anonymous4 {
    288282        int __i__i_2;
    289283    };
     
    320314    ((void)sizeof(enum __anonymous5 ));
    321315}
    322 int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object12, __attribute__ ((unused,unused,unused)) int *__anonymous_object13);
    323 int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) int **__anonymous_object14, __attribute__ ((unused,unused,unused,unused)) int **__anonymous_object15);
    324 int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object16, __attribute__ ((unused,unused,unused)) int *__anonymous_object17);
    325 int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object18)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object19)());
    326 int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object20)(__attribute__ ((unused)) int __anonymous_object21), __attribute__ ((unused,unused,unused)) int (*__anonymous_object22)(__attribute__ ((unused)) int __anonymous_object23));
    327 int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object24)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object25)());
    328 int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object26)(__attribute__ ((unused)) int __anonymous_object27), __attribute__ ((unused,unused,unused)) int (*__anonymous_object28)(__attribute__ ((unused)) int __anonymous_object29));
     316int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object10, __attribute__ ((unused,unused,unused)) int *__anonymous_object11);
     317int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) int **__anonymous_object12, __attribute__ ((unused,unused,unused,unused)) int **__anonymous_object13);
     318int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) int *__anonymous_object14, __attribute__ ((unused,unused,unused)) int *__anonymous_object15);
     319int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object16)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object17)());
     320int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object18)(__attribute__ ((unused)) int __anonymous_object19), __attribute__ ((unused,unused,unused)) int (*__anonymous_object20)(__attribute__ ((unused)) int __anonymous_object21));
     321int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object22)(), __attribute__ ((unused,unused,unused)) int (*__anonymous_object23)());
     322int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) int (*__anonymous_object24)(__attribute__ ((unused)) int __anonymous_object25), __attribute__ ((unused,unused,unused)) int (*__anonymous_object26)(__attribute__ ((unused)) int __anonymous_object27));
    329323struct Vad {
    330     __attribute__ ((unused)) int __anonymous_object30;
    331     __attribute__ ((unused,unused)) int *__anonymous_object31;
    332     __attribute__ ((unused,unused)) int __anonymous_object32[((long unsigned int )10)];
    333     __attribute__ ((unused,unused)) int (*__anonymous_object33)();
     324    __attribute__ ((unused)) int __anonymous_object28;
     325    __attribute__ ((unused,unused)) int *__anonymous_object29;
     326    __attribute__ ((unused,unused)) int __anonymous_object30[((long unsigned int )10)];
     327    __attribute__ ((unused,unused)) int (*__anonymous_object31)();
    334328};
    335329static inline void ___constructor__F_P4sVad_autogen___1(struct Vad *___dst__P4sVad_1);
  • src/tests/.expect/castError.txt

    r12d3187 r2055098  
    3939
    4040
    41 make: *** [castError] Error 1
  • src/tests/.expect/completeTypeError.txt

    r12d3187 r2055098  
    4141
    4242
    43 make: *** [completeTypeError] Error 1
  • src/tests/.expect/constant0-1DP.txt

    r12d3187 r2055098  
    3131constant0-1.c:50 error: duplicate object definition for x: const pointer to pointer to signed int
    3232constant0-1.c:50 error: duplicate object definition for 0: pointer to pointer to signed int
    33 make: *** [constant0-1DP] Error 1
  • src/tests/.expect/constant0-1NDDP.txt

    r12d3187 r2055098  
    1515constant0-1.c:67 error: duplicate object definition for x: const pointer to signed int
    1616constant0-1.c:67 error: duplicate object definition for 0: const pointer to signed int
    17 make: *** [constant0-1NDDP] Error 1
  • src/tests/.expect/declarationErrors.txt

    r12d3187 r2055098  
    6767
    6868
    69 make: *** [declarationErrors] Error 1
  • src/tests/.expect/dtor-early-exit-ERR1.txt

    r12d3187 r2055098  
    11dtor-early-exit.c:142 error: jump to label 'L1' crosses initialization of y Branch (Goto)
    2 
    3 make: *** [dtor-early-exit-ERR1] Error 1
  • src/tests/.expect/dtor-early-exit-ERR2.txt

    r12d3187 r2055098  
    11dtor-early-exit.c:142 error: jump to label 'L2' crosses initialization of y Branch (Goto)
    2 
    3 make: *** [dtor-early-exit-ERR2] Error 1
  • src/tests/.expect/memberCtors-ERR1.txt

    r12d3187 r2055098  
    11memberCtors.c:62 error: in void ?{}(B *b), field a2 used before being constructed
    2 make: *** [memberCtors-ERR1] Error 1
  • src/tests/.expect/scopeErrors.txt

    r12d3187 r2055098  
    77  with body
    88    CompoundStmt
    9 
    10 make: *** [scopeErrors] Error 1
  • src/tests/.gitignore

    r12d3187 r2055098  
    11.out/
     2.err/
  • src/tests/Makefile.am

    r12d3187 r2055098  
    2222concurrent=yes
    2323quick_test+= coroutine thread monitor
     24concurrent_test=coroutine thread monitor multi-monitor sched-int sched-int-multi sched-int-multi2 sched-ext sched-ext-multi preempt
    2425else
    2526concurrent=no
     27concurrent_test=
    2628endif
    27 
    2829
    2930# applies to both programs
    3031EXTRA_FLAGS =
    31 CFLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ ${EXTRA_FLAGS}
     32BUILD_FLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ ${EXTRA_FLAGS}
     33TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )
     34CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS}
    3235CC = @CFA_BINDIR@/@CFA_NAME@
    3336
     
    5154        @+python test.py --list --concurrent=${concurrent}
    5255
     56concurrency :
     57        @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test}
     58
    5359.dummy : .dummy.c
    54         ${CC} ${CFLAGS} -XCFA -n ${<} -o ${@}
     60        ${CC} ${BUILD_FLAGS} -XCFA -n ${<} -o ${@}                              #don't use CFLAGS, this rule is not a real test
    5561
    5662constant0-1DP : constant0-1.c
  • src/tests/Makefile.in

    r12d3187 r2055098  
    125125CFA_NAME = @CFA_NAME@
    126126CFA_PREFIX = @CFA_PREFIX@
    127 CFLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ ${EXTRA_FLAGS}
     127CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS}
    128128CPP = @CPP@
    129129CPPFLAGS = @CPPFLAGS@
     
    229229@BUILD_CONCURRENCY_FALSE@concurrent = no
    230230@BUILD_CONCURRENCY_TRUE@concurrent = yes
     231@BUILD_CONCURRENCY_FALSE@concurrent_test =
     232@BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int sched-int-multi sched-int-multi2 sched-ext sched-ext-multi preempt
    231233
    232234# applies to both programs
    233235EXTRA_FLAGS =
     236BUILD_FLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ ${EXTRA_FLAGS}
     237TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )
    234238fstream_test_SOURCES = fstream_test.c
    235239vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c
     
    669673        @+python test.py --list --concurrent=${concurrent}
    670674
     675concurrency :
     676        @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test}
     677
    671678.dummy : .dummy.c
    672         ${CC} ${CFLAGS} -XCFA -n ${<} -o ${@}
     679        ${CC} ${BUILD_FLAGS} -XCFA -n ${<} -o ${@}                              #don't use CFLAGS, this rule is not a real test
    673680
    674681constant0-1DP : constant0-1.c
  • src/tests/attributes.c

    r12d3187 r2055098  
    6868__attribute__(( unused )) int (* __attribute__(( unused )) f4())(int) __attribute__(( used ));
    6969__attribute__(( unused )) int (* __attribute__(( unused )) f4())(int) {}
    70 
    71 #ifdef __CFA__
    72 extern "C" {
    73 #endif // __CFA__
    74 typedef long int ptrdiff_t;
    75 typedef long unsigned int size_t;
    76 extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
    77 extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__));
    78 extern void abort (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
    79 extern int atexit0 (void (*__func) (void), void *, void *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
    80 extern void exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
    81 extern int printf (__const char *__restrict __format, ...) __attribute__ ((format (printf, 1, 2)));
    82 #ifdef __CFA__
    83 }
    84 #endif // __CFA__
    8570
    8671
  • src/tests/rational.c

    r12d3187 r2055098  
    1010// Created On       : Mon Mar 28 08:43:12 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul  5 18:29:37 2016
    13 // Update Count     : 25
     12// Last Modified On : Thu Apr 27 17:05:19 2017
     13// Update Count     : 40
    1414//
    1515
     
    3636        b = (Rational){ -3, 2 };
    3737        sout | a | b | endl;
    38         sout | a == 1 | endl;
     38//      sout | a == 1 | endl; // FIX ME
    3939        sout | a != b | endl;
    4040        sout | a <  b | endl;
     
    6161        sout | narrow( 3.14159265358979, 256 ) | endl;
    6262
     63        sout | "decompose" | endl;
     64        RationalImpl n, d;
     65        [n, d] = a;
     66        sout | a | n | d | endl;
     67
     68        sout | "more tests" | endl;
    6369        Rational x = { 1, 2 }, y = { 2 };
    6470        sout | x - y | endl;
  • src/tests/sched-int.c

    r12d3187 r2055098  
     1#include <fstream>
    12#include <kernel>
    23#include <monitor>
     
    1516
    1617void step1( global_t * mutex this ) {
     18        sout | "Step 1" | endl;
    1719        this->value = 1;
    1820        wait( &cond );
     
    2224        if( this->value != 1) abort();
    2325
     26        sout | "Step 2" | endl;
    2427        this->value = 2;
    2528        signal( &cond );
     
    2932        if( this->value != 2) abort();
    3033
    31         this->value = 2;
     34        sout | "Step 3" | endl;
     35        this->value = 3;
    3236        signal( &cond );
    3337}
  • src/tests/test.py

    r12d3187 r2055098  
    66from os import listdir, environ
    77from os.path import isfile, join, splitext
    8 from subprocess import Popen, PIPE, STDOUT
     8from pybin.tools import *
    99
    1010import argparse
     11import multiprocessing
    1112import os
    1213import re
    13 import stat
     14import signal
    1415import sys
    1516
     
    2627def getMachineType():
    2728        sh('echo "void ?{}(int*a,int b){}int main(){return 0;}" > .dummy.c')
    28         sh("make .dummy", print2stdout=False)
     29        ret, out = sh("make .dummy -s", print2stdout=True)
     30       
     31        if ret != 0:
     32                print("Failed to identify architecture:")
     33                print(out)
     34                print("Stopping")
     35                rm( (".dummy.c",".dummy") )
     36                sys.exit(1)
     37
    2938        _, out = sh("file .dummy", print2stdout=False)
    30         sh("rm -f .dummy.c > /dev/null 2>&1")
    31         sh("rm -f .dummy > /dev/null 2>&1")
     39        rm( (".dummy.c",".dummy") )
     40
    3241        return re.search("ELF\s([0-9]+)-bit", out).group(1)
    3342
     
    5867        return generic_list + typed_list + concurrent_list;
    5968
    60 # helper functions to run terminal commands
    61 def sh(cmd, dry_run = False, print2stdout = True):
    62         if dry_run :    # if this is a dry_run, only print the commands that would be ran
    63                 print("cmd: %s" % cmd)
    64                 return 0, None
    65         else :                  # otherwise create a pipe and run the desired command
    66                 proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
    67                 out, err = proc.communicate()
    68                 return proc.returncode, out
    69 
    70 # helper function to replace patterns in a file
    71 def file_replace(fname, pat, s_after):
    72     # first, see if the pattern is even in the file.
    73     with open(fname) as f:
    74         if not any(re.search(pat, line) for line in f):
    75             return # pattern does not occur in file so we are done.
    76 
    77     # pattern is in the file, so perform replace operation.
    78     with open(fname) as f:
    79         out_fname = fname + ".tmp"
    80         out = open(out_fname, "w")
    81         for line in f:
    82             out.write(re.sub(pat, s_after, line))
    83         out.close()
    84         os.rename(out_fname, fname)
    85 
    86 # tests output may differ depending on the depth of the makefile
    87 def fix_MakeLevel(file) :
    88         if environ.get('MAKELEVEL') :
    89                 file_replace(file, "make\[%i\]" % int(environ.get('MAKELEVEL')), 'make' )
    90 
    91 # helper function to check if a files contains only a spacific string
    92 def fileContainsOnly(file, text) :
    93         with open(file) as f:
    94                 ff = f.read().strip()
    95                 result = ff == text.strip()
    96 
    97                 return result;
    98 
    99 # check whether or not a file is executable
    100 def fileIsExecutable(file) :
    101         try :
    102                 fileinfo = os.stat(file)
    103                 return bool(fileinfo.st_mode & stat.S_IXUSR)
    104         except Exception as inst:
    105                 print(type(inst))    # the exception instance
    106                 print(inst.args)     # arguments stored in .args
    107                 print(inst)
    108                 return False
     69# from the found tests, filter all the valid tests/desired tests
     70def validTests( options ):
     71        tests = []
     72
     73        # if we are regenerating the tests we need to find the information of the
     74        # already existing tests and create new info for the new tests
     75        if options.regenerate_expected :
     76                for testname in options.tests :
     77                        if testname.endswith( (".c", ".cc", ".cpp") ):
     78                                print('ERROR: "%s", tests are not allowed to end with a C/C++/CFA extension, ignoring it' % testname, file=sys.stderr)
     79                        else :
     80                                found = [test for test in allTests if test.name == testname]
     81                                tests.append( found[0] if len(found) == 1 else Test(testname, testname) )
     82
     83        else :
     84                # otherwise we only need to validate that all tests are present in the complete list
     85                for testname in options.tests:
     86                        test = [t for t in allTests if t.name == testname]
     87
     88                        if len(test) != 0 :
     89                                tests.append( test[0] )
     90                        else :
     91                                print('ERROR: No expected file for test %s, ignoring it' % testname, file=sys.stderr)
     92
     93        # make sure we have at least some test to run
     94        if len(tests) == 0 :
     95                print('ERROR: No valid test to run', file=sys.stderr)
     96                sys.exit(1)
     97
     98        return tests
     99
     100# parses the option
     101def getOptions():
     102        # create a parser with the arguments for the tests script
     103        parser = argparse.ArgumentParser(description='Script which runs cforall tests')
     104        parser.add_argument('--debug', help='Run all tests in debug or release', type=yes_no, default='no')
     105        parser.add_argument('--concurrent', help='Run concurrent tests', type=yes_no, default='yes')
     106        parser.add_argument('--dry-run', help='Don\'t run the tests, only output the commands', action='store_true')
     107        parser.add_argument('--list', help='List all test available', action='store_true')
     108        parser.add_argument('--all', help='Run all test available', action='store_true')
     109        parser.add_argument('--regenerate-expected', help='Regenerate the .expect by running the specified tets, can be used with --all option', action='store_true')
     110        parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int, default='8')
     111        parser.add_argument('--list-comp', help='List all valide arguments', action='store_true')
     112        parser.add_argument('tests', metavar='test', type=str, nargs='*', help='a list of tests to run')
     113
     114        options =  parser.parse_args()
     115
     116        # script must have at least some tests to run or be listing
     117        listing    = options.list or options.list_comp
     118        all_tests  = options.all
     119        some_tests = len(options.tests) > 0
     120
     121        # check that exactly one of the booleans is set to true
     122        if not sum( (listing, all_tests, some_tests) ) == 1 :
     123                print('ERROR: must have option \'--all\', \'--list\' or non-empty test list', file=sys.stderr)
     124                parser.print_help()
     125                sys.exit(1)
     126
     127        return options
     128
     129def jobCount( options ):
     130        # check if the user already passed in a number of jobs for multi-threading
     131        make_flags = environ.get('MAKEFLAGS')
     132        make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
     133        if make_jobs_fds :
     134                tokens = os.read(int(make_jobs_fds.group(2)), 1024)
     135                options.jobs = len(tokens)
     136                os.write(int(make_jobs_fds.group(3)), tokens)
     137        else :
     138                options.jobs = multiprocessing.cpu_count()
     139
     140        # make sure we have a valid number of jobs that corresponds to user input
     141        if options.jobs <= 0 :
     142                print('ERROR: Invalid number of jobs', file=sys.stderr)
     143                sys.exit(1)
     144
     145        return min( options.jobs, len(tests) ), True if make_flags else False
    109146
    110147################################################################################
    111148#               running test functions
    112149################################################################################
     150# logic to run a single test and return the result (No handling of printing or other test framework logic)
    113151def run_single_test(test, generate, dry_run, debug):
    114152
    115153        # find the output file based on the test name and options flag
    116154        out_file = (".out/%s.log" % test.name) if not generate else (".expect/%s.txt" % test.path)
     155        err_file = ".err/%s.log" % test.name
    117156
    118157        # remove any outputs from the previous tests to prevent side effects
    119         sh("rm -f %s" % out_file, dry_run)
    120         sh("rm -f %s > /dev/null 2>&1" % test.name, dry_run)
    121 
    122         options = "-debug" if debug else "-nodebug";
     158        rm( (out_file, test.name), dry_run )
     159
     160        options = "-debug" if debug else "-nodebug"
    123161
    124162        # build, skipping to next test on error
    125         make_ret, _ = sh("""%s EXTRA_FLAGS="-quiet %s" %s 2> %s 1> /dev/null""" % (make_cmd, options, test.name, out_file), dry_run)
     163        make_ret, _ = sh("""%s test=yes EXTRA_FLAGS="-quiet %s" %s 2> %s 1> /dev/null""" % (make_cmd, options, test.name, out_file), dry_run)
    126164
    127165        # if the make command succeds continue otherwise skip to diff
     
    137175                        sh("cat %s > %s" % (test.name, out_file), dry_run)
    138176
     177        else :
     178                # command failed save the log to less temporary file
     179                sh("mv %s %s" % (err_file, out_file), dry_run)
     180
    139181        retcode = 0
    140182        error = None
    141 
    142         # fix output to prevent make depth to cause issues
    143         fix_MakeLevel(out_file)
    144183
    145184        if generate :
     
    151190
    152191        else :
    153                 # diff the output of the files
    154                 diff_cmd = ("diff --old-group-format='\t\tmissing lines :\n"
    155                                         "%%<' \\\n"
    156                                         "--new-group-format='\t\tnew lines :\n"
    157                                         "%%>' \\\n"
    158                                         "--unchanged-group-format='%%=' \\"
    159                                         "--changed-group-format='\t\texpected :\n"
    160                                         "%%<\n"
    161                                         "\t\tgot :\n"
    162                                         "%%>' \\\n"
    163                                         "--new-line-format='\t\t%%dn\t%%L' \\\n"
    164                                         "--old-line-format='\t\t%%dn\t%%L' \\\n"
    165                                         "--unchanged-line-format='' \\\n"
    166                                         ".expect/%s.txt .out/%s.log")
    167 
    168192                # fetch return code and error from the diff command
    169                 retcode, error = sh(diff_cmd % (test.path, test.name), dry_run, False)
    170 
     193                retcode, error = diff(".expect/%s.txt" % test.path, ".out/%s.log" % test.name, dry_run)
     194       
    171195        # clean the executable
    172196        sh("rm -f %s > /dev/null 2>&1" % test.name, dry_run)
     
    174198        return retcode, error
    175199
    176 def run_test_instance(t, generate, dry_run, debug) :
    177         try :
    178                 # print formated name
    179                 name_txt = "%20s  " % t.name
    180 
    181                 #run the test instance and collect the result
    182                 test_failed, error = run_single_test(t, generate, dry_run, debug)
    183 
    184                 # update output based on current action
    185                 if generate :
    186                         failed_txt = "ERROR"
    187                         success_txt = "Done"
    188                 else :
    189                         failed_txt = "FAILED"
    190                         success_txt = "PASSED"
    191 
    192                 #print result with error if needed
    193                 text = name_txt + (failed_txt if test_failed else success_txt)
    194                 out = sys.stdout
    195                 if error :
    196                         text = text + "\n" + error
    197                         out = sys.stderr
    198 
    199                 print(text, file = out);
    200                 sys.stdout.flush()
    201                 sys.stderr.flush()
    202                 return test_failed
    203 
    204         except KeyboardInterrupt:
    205                 test_failed = True
    206 
     200# run a single test and handle the errors, outputs, printing, exception handling, etc.
     201def run_test_worker(t, generate, dry_run, debug) :
     202
     203        signal.signal(signal.SIGINT, signal.SIG_DFL)
     204        # print formated name
     205        name_txt = "%20s  " % t.name
     206
     207        #run the test instance and collect the result
     208        test_failed, error = run_single_test(t, generate, dry_run, debug)
     209
     210        # update output based on current action
     211        if generate :
     212                failed_txt = "ERROR"
     213                success_txt = "Done"
     214        else :
     215                failed_txt = "FAILED"
     216                success_txt = "PASSED"
     217
     218        #print result with error if needed
     219        text = name_txt + (failed_txt if test_failed else success_txt)
     220        out = sys.stdout
     221        if error :
     222                text = text + "\n" + error
     223                out = sys.stderr
     224
     225        print(text, file = out);
     226        sys.stdout.flush()
     227        sys.stderr.flush()
     228        signal.signal(signal.SIGINT, signal.SIG_IGN)
     229
     230        return test_failed
    207231
    208232# run the given list of tests with the given parameters
     
    211235        sh("%s clean > /dev/null 2>&1" % make_cmd, dry_run)
    212236
    213         #make sure the required folder are present
    214         sh('mkdir -p .out .expect', dry_run)
     237        # make sure the required folder are present
     238        sh('mkdir -p .out .expect .err', dry_run)
    215239
    216240        if generate :
    217241                print( "Regenerate tests for: " )
    218242
     243        # create the executor for our jobs and handle the signal properly
     244        original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
     245        pool = Pool(jobs)
     246        signal.signal(signal.SIGINT, original_sigint_handler)
     247
    219248        # for each test to run
    220         pool = Pool(jobs)
    221249        try :
    222                 results = pool.map_async(partial(run_test_instance, generate=generate, dry_run=dry_run, debug=debug), tests ).get(9999)
     250                results = pool.map_async(partial(run_test_worker, generate=generate, dry_run=dry_run, debug=debug), tests ).get(3600)
    223251        except KeyboardInterrupt:
    224252                pool.terminate()
     
    226254                sys.exit(1)
    227255
    228         #clean the workspace
     256        # clean the workspace
    229257        sh("%s clean > /dev/null 2>&1" % make_cmd, dry_run)
    230258
     
    235263        return 0
    236264
    237 def yes_no(string):
    238         if string == "yes" :
    239                 return True
    240         if string == "no" :
    241                 return False
    242         raise argparse.ArgumentTypeError(msg)
    243         return False
    244 
    245265
    246266################################################################################
    247267#               main loop
    248268################################################################################
    249 # create a parser with the arguments for the tests script
    250 parser = argparse.ArgumentParser(description='Script which runs cforall tests')
    251 parser.add_argument('--debug', help='Run all tests in debug or release', type=yes_no, default='no')
    252 parser.add_argument('--concurrent', help='Run concurrent tests', type=yes_no, default='yes')
    253 parser.add_argument('--dry-run', help='Don\'t run the tests, only output the commands', action='store_true')
    254 parser.add_argument('--list', help='List all test available', action='store_true')
    255 parser.add_argument('--all', help='Run all test available', action='store_true')
    256 parser.add_argument('--regenerate-expected', help='Regenerate the .expect by running the specified tets, can be used with --all option', action='store_true')
    257 parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int, default='8')
    258 parser.add_argument('tests', metavar='test', type=str, nargs='*', help='a list of tests to run')
    259 
    260 # parse the command line arguments
    261 options = parser.parse_args()
    262 
    263 # script must have at least some tests to run
    264 if (len(options.tests) > 0  and     options.all and not options.list) \
    265 or (len(options.tests) == 0 and not options.all and not options.list) :
    266         print('ERROR: must have option \'--all\' or non-empty test list', file=sys.stderr)
    267         parser.print_help()
    268         sys.exit(1)
    269 
    270 # fetch the liest of all valid tests
    271 allTests = listTests( options.concurrent )
    272 
    273 # if user wants all tests than no other treatement of the test list is required
    274 if options.all or options.list :
    275         tests = allTests
    276 
    277 else :
    278         #otherwise we need to validate that the test list that was entered is valid
    279         tests = []
    280 
    281         # if we are regenerating the tests we need to find the information of the
    282         # already existing tests and create new info for the new tests
    283         if options.regenerate_expected :
    284                 for testname in options.tests :
    285                         if testname.endswith(".c") or testname.endswith(".cc") or testname.endswith(".cpp") :
    286                                 print('ERROR: "%s", tests are not allowed to end with a C/C++/CFA extension, ignoring it' % testname, file=sys.stderr)
    287                         else :
    288                                 found = [test for test in allTests if test.name == testname]
    289                                 tests.append( found[0] if len(found) == 1 else Test(testname, testname) )
    290 
    291         else :
    292                 # otherwise we only need to validate that all tests are present in the complete list
    293                 for testname in options.tests:
    294                         test = [t for t in allTests if t.name == testname]
    295 
    296                         if len(test) != 0 :
    297                                 tests.append( test[0] )
    298                         else :
    299                                 print('ERROR: No expected file for test %s, ignoring it' % testname, file=sys.stderr)
    300 
    301         # make sure we have at least some test to run
    302         if len(tests) == 0 :
    303                 print('ERROR: No valid test to run', file=sys.stderr)
    304                 sys.exit(1)
    305 
    306 # sort the test alphabetically for convenience
    307 tests.sort(key=lambda t: t.name)
    308 
    309 # check if the user already passed in a number of jobs for multi-threading
    310 make_flags = environ.get('MAKEFLAGS')
    311 make_jobs_fds = re.search("--jobserver-fds=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
    312 if make_jobs_fds :
    313         tokens = os.read(int(make_jobs_fds.group(1)), 1024)
    314         options.jobs = len(tokens)
    315         os.write(int(make_jobs_fds.group(2)), tokens)
    316 
    317 # make sure we have a valid number of jobs that corresponds to user input
    318 if options.jobs <= 0 :
    319         print('ERROR: Invalid number of jobs', file=sys.stderr)
    320         sys.exit(1)
    321 
    322 print('Running (%s) on %i cores' % ("debug" if options.debug else "no debug", options.jobs))
    323 make_cmd = "make" if make_flags else ("make -j%i" % options.jobs)
    324 
    325 # users may want to simply list the tests
    326 if options.list :
    327         print("\n".join(map(lambda t: "%s (%s)" % (t.name, t.path), tests)))
    328 
    329 else :
    330         # otherwise run all tests and make sure to return the correct error code
    331         sys.exit( run_tests(tests, options.regenerate_expected, options.dry_run, options.jobs, options.debug) )
     269if __name__ == "__main__":
     270        #always run from same folder
     271        chdir()
     272       
     273        # parse the command line arguments
     274        options = getOptions()
     275
     276        # fetch the liest of all valid tests
     277        allTests = listTests( options.concurrent )
     278
     279        # if user wants all tests than no other treatement of the test list is required
     280        if options.all or options.list or options.list_comp :
     281                tests = allTests
     282
     283        else :
     284                #otherwise we need to validate that the test list that was entered is valid
     285                tests = validTests( options )
     286
     287        # sort the test alphabetically for convenience
     288        tests.sort(key=lambda t: t.name)
     289
     290        # users may want to simply list the tests
     291        if options.list_comp :
     292                print("-h --help --debug --concurrent --dry-run --list --all --regenerate-expected -j --jobs ", end='')
     293                print(" ".join(map(lambda t: "%s" % (t.name), tests)))
     294
     295        elif options.list :
     296                print("\n".join(map(lambda t: "%s (%s)" % (t.name, t.path), tests)))
     297
     298        else :
     299                options.jobs, forceJobs = jobCount( options )
     300
     301                print('Running (%s) on %i cores' % ("debug" if options.debug else "no debug", options.jobs))
     302                make_cmd = "make" if forceJobs else ("make -j%i" % options.jobs)
     303
     304                # otherwise run all tests and make sure to return the correct error code
     305                sys.exit( run_tests(tests, options.regenerate_expected, options.dry_run, options.jobs, options.debug) )
Note: See TracChangeset for help on using the changeset viewer.