Changeset 6a8ac0b
- Timestamp:
- Apr 25, 2017, 8:21:10 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 89a9be2
- Parents:
- b3d70eba
- Location:
- doc/generic_types
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/generic_types/evaluation/Makefile
rb3d70eba r6a8ac0b 1 CC = gcc 1 2 CFA = cfa 2 3 DEPFLAGS = -MMD -MP … … 6 7 endif 7 8 CXXFLAGS = $(CFLAGS) --std=c++14 9 MAKEFILE_NAME = ${firstword ${MAKEFILE_LIST}} 8 10 9 .PHONY : all clean distclean run-c run-cpp run-cfa run11 .PHONY : all clean run-c run-cpp run-cfa run 10 12 11 all : c-bench cpp-bench cfa-bench cpp-vbench13 all : c-bench cpp-bench cpp-vbench cfa-bench 12 14 13 15 # rewrite object generation to auto-determine deps … … 17 19 18 20 c-%.o : c-%.c 19 c-%.o : c-%.c c-%.d20 21 $(COMPILE.c) $(OUTPUT_OPTION) -c $< 21 22 22 23 cpp-%.o : cpp-%.cpp 23 cpp-%.o : cpp-%.cpp cpp-%.d24 24 $(COMPILE.cpp) $(OUTPUT_OPTION) -c $< 25 25 26 26 cfa-%.o : cfa-%.c 27 cfa-%.o : cfa-%.c cfa-%.d28 27 $(COMPILE.cfa) $(OUTPUT_OPTION) -c $< 29 28 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 29 COBJS = c-stack.o c-pair.o c-print.o c-bench.o 30 CPPOBJS = cpp-bench.o 31 CPPVOBJS = cpp-vstack.o cpp-vbench.o 32 CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o cfa-bench.o 34 33 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} 39 35 40 c-bench: c-bench.c c-bench.d $(COBJS) 41 $(COMPILE.c) -o $@ $< $(COBJS) $(LDFLAGS) 36 CFILES = bench.h $(patsubst c-bench.h,,$(COBJS:.o=.h)) $(COBJS:.o=.c) 37 CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp cpp-print.hpp $(CPPOBJS:.o=.cpp) 38 CPPVFILES = bench.hpp object.hpp cpp-vprint.hpp $(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp) 39 CFAFILES = bench.h $(patsubst cfa-bench.h,,$(CFAOBJS:.o=.h)) $(CFAOBJS:.o=.c) 42 40 43 c pp-bench: cpp-bench.cpp cpp-bench.d $(CPPOBJS)44 $(COMPILE.c pp) -o $@ $< $(CPPOBJS) $(LDFLAGS)41 c-bench : $(COBJS) c-bench.o 42 $(COMPILE.c) $(LDFLAGS) $^ -o $@ 45 43 46 cpp- vbench: cpp-vbench.cpp cpp-vbench.d $(CPPVOBJS)47 $(COMPILE.cpp) -o $@ $< $(CPPVOBJS) $(LDFLAGS)44 cpp-bench : $(CPPOBJS) cpp-bench.o 45 $(COMPILE.cpp) $(LDFLAGS) $^ -o $@ 48 46 49 c fa-bench: cfa-bench.c cfa-bench.d $(CFAOBJS)50 $(COMPILE.c fa) -o $@ $< $(CFAOBJS) $(LDFLAGS)47 cpp-vbench : $(CPPVOBJS) cpp-vbench.o 48 $(COMPILE.cpp) $(LDFLAGS) $^ -o $@ 51 49 52 clean: 53 -rm $(COBJS) c-bench 54 -rm $(CPPOBJS) cpp-bench 55 -rm $(CPPVOBJS) cpp-vbench 56 -rm $(CFAOBJS) cfa-bench 50 cfa-bench : $(CFAOBJS) cfa-bench.o 51 $(COMPILE.cfa) $(LDFLAGS) $^ -o $@ 57 52 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) 63 58 64 run-c: c-bench 59 clean : 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 65 run-c : c-bench 65 66 @echo 66 67 @echo '## C ##' 67 @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./ c-bench68 @/usr/bin/time -f 'max_memory:\t%M kilobytes' ./$< 68 69 @printf 'source_size:\t%8d lines\n' `cat $(CFILES) | wc -l` 69 70 @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 $<` 71 72 72 run-cfa: cfa-bench 73 run-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 81 run-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 89 run-cfa : cfa-bench 73 90 @echo 74 91 @echo '## Cforall ##' 75 @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./ cfa-bench92 @/usr/bin/time -f 'max_memory:\t %M kilobytes' ./$< 76 93 @printf 'source_size:\t%8d lines\n' `cat $(CFAFILES) | wc -l` 77 94 @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 $<` 79 96 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 97 run : run-c run-cfa run-cpp run-cppv -
doc/generic_types/evaluation/c-bench.c
rb3d70eba r6a8ac0b 39 39 40 40 int main(int argc, char** argv) { 41 FILE * out = fopen(" c-out.txt", "w");41 FILE * out = fopen("/dev/null", "w"); 42 42 int maxi = 0, vali = 42; 43 43 struct stack si = new_stack(), ti; -
doc/generic_types/evaluation/c-stack.c
rb3d70eba r6a8ac0b 11 11 void copy_stack(struct stack* s, const struct stack* t, void* (*copy)(const void*)) { 12 12 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 ) { 15 14 *crnt = malloc(sizeof(struct stack_node)); /***/ 16 15 **crnt = (struct stack_node){ copy(next->value) }; /***/ 17 16 crnt = &(*crnt)->next; 18 next = next->next;19 17 } 20 18 *crnt = 0; … … 22 20 23 21 void 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; ) { 26 23 struct stack_node* crnt = next; 27 24 next = crnt->next; -
doc/generic_types/evaluation/cfa-bench.c
rb3d70eba r6a8ac0b 6 6 7 7 int main( int argc, char *argv[] ) { 8 FILE * out = fopen( " cfa-out.txt", "w" );8 FILE * out = fopen( "/dev/null", "w" ); 9 9 int maxi = 0, vali = 42; 10 10 stack(int) si, ti; -
doc/generic_types/evaluation/cfa-stack.c
rb3d70eba r6a8ac0b 11 11 forall(otype T) void ?{}(stack(T)* s, stack(T) t) { 12 12 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 ) { 15 14 *crnt = ((stack_node(T)*)malloc()){ next->value }; /***/ 16 15 stack_node(T)* acrnt = *crnt; 17 16 crnt = &acrnt->next; 18 next = next->next;19 17 } 20 18 *crnt = 0; … … 46 44 47 45 forall(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; ) { 50 47 stack_node(T)* crnt = next; 51 48 next = crnt->next; -
doc/generic_types/evaluation/cpp-bench.cpp
rb3d70eba r6a8ac0b 7 7 8 8 int main(int argc, char** argv) { 9 std::ofstream out{" cpp-out.txt"};9 std::ofstream out{"/dev/null"}; 10 10 int maxi = 0, vali = 42; 11 11 stack<int> si, ti; -
doc/generic_types/evaluation/cpp-stack.hpp
rb3d70eba r6a8ac0b 13 13 void copy(const stack<T>& o) { 14 14 node** crnt = &head; 15 node* next = o.head; 16 while ( next ) { 15 for ( node* next = o.head; next; next = next->next ) { 17 16 *crnt = new node{ next->value }; /***/ 18 17 crnt = &(*crnt)->next; 19 next = next->next;20 18 } 21 19 *crnt = nullptr; … … 23 21 public: 24 22 void clear() { 25 node* next = head; 26 while ( next ) { 23 for ( node* next = head; next; ) { 27 24 node* crnt = next; 28 25 next = crnt->next; -
doc/generic_types/evaluation/cpp-vbench.cpp
rb3d70eba r6a8ac0b 7 7 8 8 int main(int argc, char** argv) { 9 std::ofstream out{" cpp-vout.txt"};9 std::ofstream out{"/dev/null"}; 10 10 integer maxi{ 0 }, vali{ 42 }; 11 11 stack si, ti; -
doc/generic_types/evaluation/cpp-vstack.cpp
rb3d70eba r6a8ac0b 6 6 void stack::copy(const stack& o) { 7 7 node** crnt = &head; 8 node* next = o.head; 9 while ( next ) { 8 for ( node* next = o.head; next; next = next->next ) { 10 9 *crnt = new node{ *next->value }; 11 10 crnt = &(*crnt)->next; 12 next = next->next;13 11 } 14 12 *crnt = nullptr; … … 35 33 36 34 void stack::clear() { 37 node* next = head; 38 while ( next ) { 35 for ( node* next = head; next; ) { 39 36 node* crnt = next; 40 37 next = crnt->next; -
doc/generic_types/generic_types.tex
rb3d70eba r6a8ac0b 232 232 int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 : 233 233 *(double *)t2 < *(double *)t1 ? 1 : 0; } 234 double key = 5.0, vals[10] = { /* 10 floating-point values */ };234 double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ }; 235 235 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ 236 236 \end{lstlisting} … … 354 354 One of the known shortcomings of standard C is that it does not provide reusable type-safe abstractions for generic data structures and algorithms. 355 355 Broadly speaking, there are three approaches to implement abstract data-structures in C. 356 One approach is to write bespoke data 356 One approach is to write bespoke data-structures for each context in which they are needed. 357 357 While 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. 358 358 A 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. … … 542 542 \end{lstlisting} 543 543 where 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 .544 Tuple variables can be composed of any types, except for array types, since array sizes are generally unknown in C. 545 545 546 546 One way to access the tuple-variable components is with assignment or composition: … … 552 552 \begin{lstlisting} 553 553 [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}$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}$ 559 559 \end{lstlisting} 560 560 … … 616 616 This 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. 617 617 For 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@.618 whereas, C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@. 619 619 Finally, 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. 620 620 This example shows mass, multiple, and cascading assignment used in one expression: … … 742 742 \end{lstlisting} 743 743 Hence, 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 744 This relaxation is possible by extending the thunk scheme described by~\citet{Bilson03}. 745 745 Whenever 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: 746 746 \begin{lstlisting} … … 748 748 \end{lstlisting} 749 749 so 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 750 These thunks take advantage of GCC C nested-functions to produce closures that have the usual function-pointer signature. 751 751 752 752 … … 829 829 \subsection{Implementation} 830 830 831 Tuples are implemented in the \CFA translator via a transformation into generic types.831 Tuples are implemented in the \CFA translator via a transformation into \emph{generic types}. 832 832 For each $N$, the first time an $N$-tuple is seen in a scope a generic type with $N$ type parameters is generated, \eg: 833 833 \begin{lstlisting} … … 1086 1086 Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable. 1087 1087 1088 There is ongoing work on a wide range of \CFA feature extensions, including reference types, exceptions, concurrent primitives and modules.1088 There is ongoing work on a wide range of \CFA feature extensions, including reference types, arrays with size, exceptions, concurrent primitives and modules. 1089 1089 (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.) 1090 1090 In addition, there are interesting future directions for the polymorphism design. … … 1092 1092 \CFA polymorphic functions use dynamic virtual-dispatch; 1093 1093 the 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 .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 (\CC template specialization). 1095 1095 These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat. 1096 1096 In general, we believe separate compilation, producing smaller code, works well with loaded hardware-caches, which may offset the benefit of larger inlined-code. … … 1117 1117 Throughout, @/***/@ designates a counted redundant type annotation. 1118 1118 1119 \ medskip\noindent1119 \smallskip\noindent 1120 1120 \CFA 1121 1121 \begin{lstlisting}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
Note: See TracChangeset
for help on using the changeset viewer.