Changes in / [34b4268:24d6572]
- Files:
-
- 744 added
- 156 deleted
- 239 edited
-
Jenkins/FullBuild (modified) (5 diffs)
-
Jenkins/Promote (modified) (2 diffs)
-
Jenkinsfile (modified) (4 diffs)
-
Makefile.am (modified) (3 diffs)
-
benchmark/Makefile.am (modified) (5 diffs)
-
benchmark/convoy/data/nasus_12_12_2022_0NCS (added)
-
benchmark/convoy/data/nasus_12_12_2022_1NCS (added)
-
benchmark/convoy/data/single_16_thd (added)
-
benchmark/convoy/genConvoyStats.py (added)
-
benchmark/mutexStmt/JavaThread.java (deleted)
-
configure.ac (modified) (3 diffs)
-
doc/LaTeXmacros/common.sty (modified) (7 diffs)
-
doc/LaTeXmacros/common.tex (modified) (5 diffs)
-
doc/LaTeXmacros/lstlang.sty (modified) (2 diffs)
-
doc/bibliography/pl.bib (modified) (71 diffs)
-
doc/papers/llheap/.gitignore (added)
-
doc/papers/llheap/AMA-stix_New.zip (added)
-
doc/papers/llheap/AMA-stix_New/Documents/.log (added)
-
doc/papers/llheap/AMA-stix_New/Documents/README.txt (added)
-
doc/papers/llheap/AMA-stix_New/Documents/wileyNJD-Doc.tex (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/STIXGeneral-Bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/STIXGeneral-BoldItalic.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/STIXGeneral-Italic.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/STIXGeneral-Regular.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/Windows-Stix-fontinstaller.exe (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/a_axxd65.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls1stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls1stixbb.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls1stixfrak.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls1stixscr.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls1stixsf.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls2stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls2stixcal.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls2stixex.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ls2stixtt.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ly1sti.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneral-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneral-bolditalic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneral-italic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneral.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneralsc-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneralsc-bold.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneralsc.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1-stixgeneralsc.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot1stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneral-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneral-bolditalic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneral-italic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneral.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneralsc-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneralsc-bold.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneralsc.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2-stixgeneralsc.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ot2stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra1.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra1.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra2.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra2.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra3.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-extra3.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbb-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbb-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbb.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbb.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbbit-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbbit-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbbit.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathbbit.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathcal-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathcal-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathcal.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathcal.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathex-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathex-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathex.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathex.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathfrak-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathfrak-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathfrak.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathfrak.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathit-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathit-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathit.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathit.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathrm-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathrm-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathrm.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathrm.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathscr-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathscr-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathscr.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathscr.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsf-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsf-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsf.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsf.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsfit-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsfit-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsfit.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathsfit.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathtt-bold.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathtt-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathtt.pfb (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-mathtt.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-ot1.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-ot2.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-t1.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix-ts1.enc (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix.dtx (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix.fdd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix.map (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/stix.sty (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneral-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneral-bolditalic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneral-italic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneral.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneralsc-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneralsc-bold.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneralsc.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1-stixgeneralsc.vf (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/t1stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ts1-stixgeneral-bold.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ts1-stixgeneral-bolditalic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ts1-stixgeneral-italic.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ts1-stixgeneral.tfm (added)
-
doc/papers/llheap/AMA-stix_New/Stix-fonts/ts1stix.fd (added)
-
doc/papers/llheap/AMA-stix_New/ama/NJDnatbib.sty (added)
-
doc/papers/llheap/AMA-stix_New/ama/WileyNJD-v2.cls (added)
-
doc/papers/llheap/AMA-stix_New/ama/empty.eps (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.aux (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.bbl (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.bib (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.blg (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.log (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.pag (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.synctex (added)
-
doc/papers/llheap/AMA-stix_New/ama/wileyNJD-AMA.tex (added)
-
doc/papers/llheap/Makefile (added)
-
doc/papers/llheap/Paper.tex (added)
-
doc/papers/llheap/WileyNJD-v2.cls (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/cache_scratch_0-scratch.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/cache_thrash_0-thrash.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/churn.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-dl.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-glc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-hrd.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-je.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-llh.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-pt3.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-rp.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-1-prod-1-cons-100-tbb.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-dl.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-glc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-hrd.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-je.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-llh.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-pt3.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-rp.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/mem-4-prod-4-cons-100-tbb.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-1-malloc-null.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-10-malloc-realloc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-11-calloc-realloc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-12-malloc-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-13-calloc-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-14-m-c-re-alloc-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-2-free-null.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-3-malloc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-4-realloc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-5-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-6-calloc.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-7-malloc-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-8-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/algol-perf-eps/speed-9-calloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/cache_scratch_0-scratch.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/cache_thrash_0-thrash.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/churn.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-dl.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-glc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-hrd.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-je.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-llh.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-pt3.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-rp.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-1-prod-1-cons-100-tbb.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-dl.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-glc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-hrd.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-je.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-llh.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-pt3.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-rp.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/mem-4-prod-4-cons-100-tbb.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-1-malloc-null.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-10-malloc-realloc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-11-calloc-realloc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-12-malloc-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-13-calloc-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-14-m-c-re-alloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-2-free-null.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-3-malloc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-4-realloc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-5-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-6-calloc.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-7-malloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-8-realloc-free.eps (added)
-
doc/papers/llheap/evaluations/nasus-perf-eps/speed-9-calloc-free.eps (added)
-
doc/papers/llheap/examples/C++Cor-ts.cpp (added)
-
doc/papers/llheap/examples/DatingServiceThread.cfa (added)
-
doc/papers/llheap/examples/Fib.c (added)
-
doc/papers/llheap/examples/Fib.cfa (added)
-
doc/papers/llheap/examples/Fib.cpp (added)
-
doc/papers/llheap/examples/Fib.js (added)
-
doc/papers/llheap/examples/Fib.py (added)
-
doc/papers/llheap/examples/Fib.sim (added)
-
doc/papers/llheap/examples/Fib1.c (added)
-
doc/papers/llheap/examples/Fib2.c (added)
-
doc/papers/llheap/examples/Fib2.cfa (added)
-
doc/papers/llheap/examples/Fib2.cpp (added)
-
doc/papers/llheap/examples/Fib2.py (added)
-
doc/papers/llheap/examples/Fib3.c (added)
-
doc/papers/llheap/examples/Fib3.cc (added)
-
doc/papers/llheap/examples/FibRefactor.py (added)
-
doc/papers/llheap/examples/Fmt.sim (added)
-
doc/papers/llheap/examples/Format.c (added)
-
doc/papers/llheap/examples/Format.cc (added)
-
doc/papers/llheap/examples/Format.cfa (added)
-
doc/papers/llheap/examples/Format.cpp (added)
-
doc/papers/llheap/examples/Format.data (added)
-
doc/papers/llheap/examples/Format.js (added)
-
doc/papers/llheap/examples/Format.py (added)
-
doc/papers/llheap/examples/Format.sim (added)
-
doc/papers/llheap/examples/Format1.c (added)
-
doc/papers/llheap/examples/PingPong.c (added)
-
doc/papers/llheap/examples/PingPong.cc (added)
-
doc/papers/llheap/examples/Pingpong.cc (added)
-
doc/papers/llheap/examples/Pingpong.cfa (added)
-
doc/papers/llheap/examples/Pingpong.py (added)
-
doc/papers/llheap/examples/Pingpong2.cfa (added)
-
doc/papers/llheap/examples/ProdCons.cfa (added)
-
doc/papers/llheap/examples/ProdCons.cpp (added)
-
doc/papers/llheap/examples/ProdCons.py (added)
-
doc/papers/llheap/examples/ProdCons.sim (added)
-
doc/papers/llheap/examples/RWMonitorEXT.cfa (added)
-
doc/papers/llheap/examples/RWMonitorINT.cfa (added)
-
doc/papers/llheap/examples/Refactor.py (added)
-
doc/papers/llheap/examples/channels.go (added)
-
doc/papers/llheap/examples/channels.rs (added)
-
doc/papers/llheap/examples/counter.cpp (added)
-
doc/papers/llheap/examples/future.rs (added)
-
doc/papers/llheap/figures/AddressSpace.fig (added)
-
doc/papers/llheap/figures/Alignment1.fig (added)
-
doc/papers/llheap/figures/Alignment2.fig (added)
-
doc/papers/llheap/figures/Alignment2Impl.fig (added)
-
doc/papers/llheap/figures/AllocDS1.fig (added)
-
doc/papers/llheap/figures/AllocDS2.fig (added)
-
doc/papers/llheap/figures/AllocInducedActiveFalseSharing.fig (added)
-
doc/papers/llheap/figures/AllocInducedPassiveFalseSharing.fig (added)
-
doc/papers/llheap/figures/AllocatedObject.fig (added)
-
doc/papers/llheap/figures/AllocatorComponents.fig (added)
-
doc/papers/llheap/figures/AllocatorComponents.fig.bak (added)
-
doc/papers/llheap/figures/CoalesceAllocated.fig (added)
-
doc/papers/llheap/figures/CoalesceFree.fig (added)
-
doc/papers/llheap/figures/CondSigWait.fig (added)
-
doc/papers/llheap/figures/Container.fig (added)
-
doc/papers/llheap/figures/ContainerFalseSharing1.fig (added)
-
doc/papers/llheap/figures/ContainerFalseSharing2.fig (added)
-
doc/papers/llheap/figures/ContainerNoOwnership.fig (added)
-
doc/papers/llheap/figures/ContainerNoOwnershipFreelist.fig (added)
-
doc/papers/llheap/figures/ContainerOwnership.fig (added)
-
doc/papers/llheap/figures/ContainerOwnershipFreelist.fig (added)
-
doc/papers/llheap/figures/ContigFragmentation.fig (added)
-
doc/papers/llheap/figures/FakeHeader.fig (added)
-
doc/papers/llheap/figures/FreeListAmongContainers.fig (added)
-
doc/papers/llheap/figures/FreeListWithinContainers.fig (added)
-
doc/papers/llheap/figures/FullCoroutinePhases.fig (added)
-
doc/papers/llheap/figures/FullProdConsStack.fig (added)
-
doc/papers/llheap/figures/Header.fig (added)
-
doc/papers/llheap/figures/HeapStructure.fig (added)
-
doc/papers/llheap/figures/IntExtFragmentation.fig (added)
-
doc/papers/llheap/figures/MemoryFragmentation.fig (added)
-
doc/papers/llheap/figures/MultipleHeapsNoOwnership.fig (added)
-
doc/papers/llheap/figures/MultipleHeapsOwnership.fig (added)
-
doc/papers/llheap/figures/MultipleHeapsOwnershipStorage.fig (added)
-
doc/papers/llheap/figures/MultipleHeapsStorage.fig (added)
-
doc/papers/llheap/figures/NewHeapStructure.eps (added)
-
doc/papers/llheap/figures/NonContigFragmentation.fig (added)
-
doc/papers/llheap/figures/ObjectHeaders.fig (added)
-
doc/papers/llheap/figures/PerThreadHeap.fig (added)
-
doc/papers/llheap/figures/PrivatePublicHeaps.fig (added)
-
doc/papers/llheap/figures/ProgramFalseSharing.fig (added)
-
doc/papers/llheap/figures/RemoteFreeList.fig (added)
-
doc/papers/llheap/figures/RunTimeStructure.fig (added)
-
doc/papers/llheap/figures/SharedHeaps.fig (added)
-
doc/papers/llheap/figures/SingleHeap.fig (added)
-
doc/papers/llheap/figures/SuperContainers.fig (added)
-
doc/papers/llheap/figures/UserKernelHeaps.fig (added)
-
doc/papers/llheap/figures/llheap.fig (added)
-
doc/papers/llheap/local.bib (added)
-
doc/proposals/alt-enums.md (added)
-
doc/theses/colby_parsons_MMAth/.gitignore (added)
-
doc/theses/colby_parsons_MMAth/Makefile (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/AkkaExecutor.scala (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/build.sbt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/AkkaMatrix.scala (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/build.sbt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/AkkaRepeat.scala (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/build.sbt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/AkkaSendDynamic.scala (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/build.sbt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/AkkaSendStatic.scala (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/build.sbt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFExecutor.cpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFMatrix.cpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFRepeat.cpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFSendDynamic.cpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFSendStatic.cpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/caf-application.conf (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/balance.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/bench.hfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/dynamic.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/executor.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/matrix.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/repeat.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/static.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasusSendDynamic (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasusSendStatic (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_ALL.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_CFA.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_SEND.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pykeSendDynamic (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pykeSendStatic (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_ALL.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_CFA.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_SEND.txt (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/genPlots (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/plotData.py (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/GoExecutor.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/go.sum (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/INSTALL (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/GoMatrix.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/go.sum (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/GoRepeat.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/go.sum (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/GoSendDynamic.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/go.sum (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/GoSendStatic.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/go.sum (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/run (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Executor.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Matrix.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Repeat.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++SendDynamic.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++SendStatic.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/barrier.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/churn.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/contend.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/daisy_chain.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/hot_potato.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/ping_pong.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/pub_sub.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/barrier/barrier.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/barrier/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/churn/churn.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/churn/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/contend/contend.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/contend/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/daisy_chain/daisy_chain.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/daisy_chain/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/hot_potato/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/hot_potato/hot_potato.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/ping_pong/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/ping_pong/ping_pong.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/pub_sub/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/pub_sub/pub_sub.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/plotData.py (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/run (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/bench.h (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/baseline.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/order.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/rand.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/baseline.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/cppLock.hpp (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/order.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/rand.cc (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/plotData.py (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/run (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/cfa/contend.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/cfa/future.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/cfa/sidechan.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/cfa/spin.cfa (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend/contend.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend2/contend.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend2/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend4/contend.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend4/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend8/contend.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/contend8/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/sidechan/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/sidechan/sidechan.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin/spin.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin2/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin2/spin.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin4/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin4/spin.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin8/go.mod (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/go/spin8/spin.go (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/run (added)
-
doc/theses/colby_parsons_MMAth/benchmarks/waituntil/ucpp/future.cc (added)
-
doc/theses/colby_parsons_MMAth/code/basic_actor_example.cfa (added)
-
doc/theses/colby_parsons_MMAth/code/swap_queues.cfa (added)
-
doc/theses/colby_parsons_MMAth/data/nasusExecutorMem (added)
-
doc/theses/colby_parsons_MMAth/data/nasusSendDynamic (added)
-
doc/theses/colby_parsons_MMAth/data/nasusSendStatic (added)
-
doc/theses/colby_parsons_MMAth/data/pykeExecutorMem (added)
-
doc/theses/colby_parsons_MMAth/data/pykeSendDynamic (added)
-
doc/theses/colby_parsons_MMAth/data/pykeSendStatic (added)
-
doc/theses/colby_parsons_MMAth/diagrams/M_to_one_swap.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/acyclic_swap.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/chain_swap.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/cyclic_swap.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/gulp.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/inverted_actor.tikz (added)
-
doc/theses/colby_parsons_MMAth/diagrams/standard_actor.tikz (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFABalance-Multi.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFABalance-One.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFAExecutor.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFAMatrix.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFARepeat.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusExecutor.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusMatrix.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasusRepeat.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_2.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_4.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_8.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Channel_Contention.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFABalance-Multi.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFABalance-One.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFAExecutor.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFAMatrix.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFARepeat.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeExecutor.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeMatrix.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pykeRepeat.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_2.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_4.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_8.pgf (added)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Channel_Contention.pgf (added)
-
doc/theses/colby_parsons_MMAth/glossary.tex (added)
-
doc/theses/colby_parsons_MMAth/local.bib (added)
-
doc/theses/colby_parsons_MMAth/style/style.tex (added)
-
doc/theses/colby_parsons_MMAth/text/CFA_concurrency.tex (added)
-
doc/theses/colby_parsons_MMAth/text/CFA_intro.tex (added)
-
doc/theses/colby_parsons_MMAth/text/actors.tex (added)
-
doc/theses/colby_parsons_MMAth/text/channels.tex (added)
-
doc/theses/colby_parsons_MMAth/text/frontpgs.tex (added)
-
doc/theses/colby_parsons_MMAth/text/intro.tex (added)
-
doc/theses/colby_parsons_MMAth/text/mutex_stmt.tex (added)
-
doc/theses/colby_parsons_MMAth/text/waituntil.tex (added)
-
doc/theses/colby_parsons_MMAth/thesis.tex (added)
-
doc/theses/mike_brooks_MMath/Makefile (modified) (5 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/.gitignore (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/Makefile (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/driver.c (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.queue-insfirst.txt (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.queue-inslast.txt (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.stack-insfirst.txt (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.stack-inslast.txt (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-cfa-cfa.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-cpp-stlref.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-lq-list.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-lq-tailq.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-upp-upp.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.c (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-allhead.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-inselem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-remelem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-allhead.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-inselem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-remelem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-allhead.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-inselem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-remelem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-allhead.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-inselem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-remelem.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/proglang.h (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-baseline.csv (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-sizing.csv (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/tailq-bug.c (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/test-correctness-regenerate-expected.sh (added)
-
doc/theses/mike_brooks_MMath/benchmarks/list/test-correctness.sh (added)
-
doc/theses/mike_brooks_MMath/list.tex (added)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-attach.pdf (added)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-attach.vsdx (added)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-direct.pdf (added)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-direct.vsdx (added)
-
doc/theses/mike_brooks_MMath/programs/lst-features-intro.run.cfa (added)
-
doc/theses/mike_brooks_MMath/programs/lst-features-multidir.run.cfa (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction-byref.run.cpp (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction-emplaced.run.cpp (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction.hpp (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-intrusive.run.c (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-multi-static.run.c (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-wrapped-byref.run.cpp (added)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-wrapped-emplaced.run.cpp (added)
-
doc/theses/mike_brooks_MMath/uw-ethesis.bib (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/uw-ethesis.tex (modified) (6 diffs)
-
driver/cfa.cc (modified) (6 diffs)
-
libcfa/configure.ac (modified) (2 diffs)
-
libcfa/prelude/builtins.c (modified) (4 diffs)
-
libcfa/prelude/prelude-gen.cc (modified) (2 diffs)
-
libcfa/src/Makefile.am (modified) (5 diffs)
-
libcfa/src/algorithms/range_iterator.hfa (modified) (1 diff)
-
libcfa/src/bitmanip.hfa (modified) (1 diff)
-
libcfa/src/bits/containers.hfa (modified) (2 diffs)
-
libcfa/src/bits/random.hfa (modified) (17 diffs)
-
libcfa/src/bits/weakso_locks.cfa (modified) (2 diffs)
-
libcfa/src/bits/weakso_locks.hfa (modified) (4 diffs)
-
libcfa/src/common.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/actor.hfa (added)
-
libcfa/src/concurrency/atomic.hfa (added)
-
libcfa/src/concurrency/channel.hfa (added)
-
libcfa/src/concurrency/clib/cfathread.cfa (modified) (8 diffs)
-
libcfa/src/concurrency/clib/cfathread.h (modified) (3 diffs)
-
libcfa/src/concurrency/coroutine.cfa (modified) (1 diff)
-
libcfa/src/concurrency/coroutine.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/future.hfa (modified) (5 diffs)
-
libcfa/src/concurrency/invoke.h (modified) (2 diffs)
-
libcfa/src/concurrency/io.cfa (modified) (28 diffs)
-
libcfa/src/concurrency/io/call.cfa.in (modified) (11 diffs)
-
libcfa/src/concurrency/io/setup.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/io/types.hfa (modified) (5 diffs)
-
libcfa/src/concurrency/iofwd.hfa (modified) (5 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel/cluster.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/kernel/cluster.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel/private.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/locks.cfa (modified) (16 diffs)
-
libcfa/src/concurrency/locks.hfa (modified) (31 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (1 diff)
-
libcfa/src/concurrency/monitor.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/mutex.cfa (modified) (1 diff)
-
libcfa/src/concurrency/mutex.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/mutex_stmt.hfa (modified) (4 diffs)
-
libcfa/src/concurrency/preemption.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/pthread.cfa (modified) (37 diffs)
-
libcfa/src/concurrency/ready_queue.cfa (modified) (1 diff)
-
libcfa/src/concurrency/select.cfa (added)
-
libcfa/src/concurrency/select.hfa (added)
-
libcfa/src/concurrency/thread.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (2 diffs)
-
libcfa/src/containers/array.hfa (modified) (1 diff)
-
libcfa/src/containers/list.hfa (modified) (3 diffs)
-
libcfa/src/containers/vector.hfa (modified) (2 diffs)
-
libcfa/src/containers/vector2.hfa (modified) (1 diff)
-
libcfa/src/exception.h (modified) (3 diffs)
-
libcfa/src/heap.cfa (modified) (21 diffs)
-
libcfa/src/interpose.cfa (modified) (5 diffs)
-
libcfa/src/interpose_thread.cfa (modified) (3 diffs)
-
libcfa/src/iostream.cfa (modified) (2 diffs)
-
libcfa/src/iostream.hfa (modified) (7 diffs)
-
libcfa/src/iterator.hfa (modified) (3 diffs)
-
libcfa/src/limits.cfa (modified) (1 diff)
-
libcfa/src/math.trait.hfa (modified) (6 diffs)
-
libcfa/src/stdlib.cfa (modified) (2 diffs)
-
libcfa/src/stdlib.hfa (modified) (3 diffs)
-
libcfa/src/vec/vec.hfa (modified) (1 diff)
-
libcfa/src/virtual_dtor.hfa (added)
-
src/AST/Attribute.hpp (modified) (1 diff)
-
src/AST/Convert.cpp (modified) (8 diffs)
-
src/AST/Create.cpp (modified) (1 diff)
-
src/AST/Decl.cpp (modified) (3 diffs)
-
src/AST/Decl.hpp (modified) (6 diffs)
-
src/AST/Expr.cpp (modified) (1 diff)
-
src/AST/Expr.hpp (modified) (4 diffs)
-
src/AST/Fwd.hpp (modified) (3 diffs)
-
src/AST/Init.hpp (modified) (1 diff)
-
src/AST/Inspect.cpp (modified) (2 diffs)
-
src/AST/Inspect.hpp (modified) (2 diffs)
-
src/AST/Node.cpp (modified) (1 diff)
-
src/AST/Node.hpp (modified) (2 diffs)
-
src/AST/ParseNode.hpp (modified) (1 diff)
-
src/AST/Pass.hpp (modified) (4 diffs)
-
src/AST/Pass.impl.hpp (modified) (10 diffs)
-
src/AST/Pass.proto.hpp (modified) (1 diff)
-
src/AST/Print.cpp (modified) (16 diffs)
-
src/AST/Print.hpp (modified) (2 diffs)
-
src/AST/Stmt.hpp (modified) (8 diffs)
-
src/AST/SymbolTable.cpp (modified) (10 diffs)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/TranslationUnit.hpp (modified) (3 diffs)
-
src/AST/Type.cpp (modified) (2 diffs)
-
src/AST/Type.hpp (modified) (3 diffs)
-
src/AST/TypeEnvironment.cpp (modified) (10 diffs)
-
src/AST/TypeEnvironment.hpp (modified) (5 diffs)
-
src/AST/TypeSubstitution.cpp (modified) (3 diffs)
-
src/AST/TypeSubstitution.hpp (modified) (4 diffs)
-
src/AST/Visitor.hpp (modified) (1 diff)
-
src/AST/porting.md (modified) (3 diffs)
-
src/CodeGen/CodeGenerator.cc (modified) (2 diffs)
-
src/CodeGen/GenType.cc (modified) (1 diff)
-
src/Common/CodeLocationTools.cpp (modified) (3 diffs)
-
src/Common/CompilerError.h (deleted)
-
src/Common/Debug.h (deleted)
-
src/Common/DeclStats.cpp (modified) (1 diff)
-
src/Common/Eval.cc (modified) (2 diffs)
-
src/Common/Eval.h (added)
-
src/Common/Iterate.hpp (added)
-
src/Common/ResolvProtoDump.cpp (modified) (2 diffs)
-
src/Common/ScopedMap.h (modified) (6 diffs)
-
src/Common/SemanticError.h (modified) (3 diffs)
-
src/Common/ToString.hpp (added)
-
src/Common/UnimplementedError.h (deleted)
-
src/Common/module.mk (modified) (3 diffs)
-
src/Common/utility.h (modified) (7 diffs)
-
src/CompilationState.cc (modified) (3 diffs)
-
src/CompilationState.h (modified) (3 diffs)
-
src/Concurrency/Actors.cpp (added)
-
src/Concurrency/Actors.hpp (added)
-
src/Concurrency/KeywordsNew.cpp (modified) (1 diff)
-
src/Concurrency/WaitforNew.cpp (modified) (2 diffs)
-
src/Concurrency/Waituntil.cpp (added)
-
src/Concurrency/Waituntil.hpp (added)
-
src/Concurrency/module.mk (modified) (2 diffs)
-
src/ControlStruct/ExceptDeclNew.cpp (modified) (1 diff)
-
src/ControlStruct/ExceptTranslateNew.cpp (modified) (1 diff)
-
src/ControlStruct/MLEMutator.cc (modified) (1 diff)
-
src/GenPoly/Box.cc (modified) (44 diffs)
-
src/GenPoly/ErasableScopedMap.h (modified) (4 diffs)
-
src/GenPoly/FindFunction.cc (modified) (3 diffs)
-
src/GenPoly/FindFunction.h (modified) (2 diffs)
-
src/GenPoly/GenPoly.cc (modified) (10 diffs)
-
src/GenPoly/GenPoly.h (modified) (1 diff)
-
src/GenPoly/InstantiateGeneric.cc (modified) (1 diff)
-
src/GenPoly/InstantiateGenericNew.cpp (modified) (2 diffs)
-
src/GenPoly/Lvalue.cc (modified) (1 diff)
-
src/GenPoly/LvalueNew.cpp (modified) (5 diffs)
-
src/GenPoly/ScopedSet.h (modified) (1 diff)
-
src/GenPoly/ScrubTyVars.cc (modified) (5 diffs)
-
src/GenPoly/ScrubTyVars.h (modified) (5 diffs)
-
src/GenPoly/SpecializeNew.cpp (modified) (1 diff)
-
src/InitTweak/FixInit.cc (modified) (3 diffs)
-
src/InitTweak/FixInitNew.cpp (modified) (12 diffs)
-
src/InitTweak/GenInit.cc (modified) (2 diffs)
-
src/InitTweak/InitTweak.cc (modified) (2 diffs)
-
src/MakeLibCfaNew.cpp (modified) (1 diff)
-
src/Parser/DeclarationNode.cc (modified) (45 diffs)
-
src/Parser/DeclarationNode.h (added)
-
src/Parser/ExpressionNode.cc (modified) (19 diffs)
-
src/Parser/ExpressionNode.h (added)
-
src/Parser/InitializerNode.cc (modified) (4 diffs)
-
src/Parser/InitializerNode.h (added)
-
src/Parser/ParseNode.h (modified) (5 diffs)
-
src/Parser/ParserTypes.h (modified) (1 diff)
-
src/Parser/RunParser.cpp (added)
-
src/Parser/RunParser.hpp (added)
-
src/Parser/StatementNode.cc (modified) (8 diffs)
-
src/Parser/StatementNode.h (added)
-
src/Parser/TypeData.cc (modified) (47 diffs)
-
src/Parser/TypeData.h (modified) (5 diffs)
-
src/Parser/TypedefTable.cc (modified) (2 diffs)
-
src/Parser/TypedefTable.h (modified) (2 diffs)
-
src/Parser/lex.ll (modified) (7 diffs)
-
src/Parser/module.mk (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (150 diffs)
-
src/Parser/parserutility.cc (modified) (3 diffs)
-
src/Parser/parserutility.h (modified) (1 diff)
-
src/ResolvExpr/AdjustExprType.hpp (added)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (3 diffs)
-
src/ResolvExpr/AlternativeFinder.h (modified) (1 diff)
-
src/ResolvExpr/Candidate.cpp (modified) (2 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (11 diffs)
-
src/ResolvExpr/CandidateFinder.hpp (modified) (1 diff)
-
src/ResolvExpr/CastCost.cc (modified) (4 diffs)
-
src/ResolvExpr/CastCost.hpp (added)
-
src/ResolvExpr/CommonType.cc (modified) (22 diffs)
-
src/ResolvExpr/CommonType.hpp (added)
-
src/ResolvExpr/ConversionCost.cc (modified) (5 diffs)
-
src/ResolvExpr/ConversionCost.h (modified) (3 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (9 diffs)
-
src/ResolvExpr/CurrentObject.h (modified) (2 diffs)
-
src/ResolvExpr/ExplodedArg.hpp (modified) (1 diff)
-
src/ResolvExpr/PolyCost.cc (modified) (1 diff)
-
src/ResolvExpr/PolyCost.hpp (added)
-
src/ResolvExpr/PtrsAssignable.cc (modified) (1 diff)
-
src/ResolvExpr/PtrsAssignable.hpp (added)
-
src/ResolvExpr/PtrsCastable.cc (modified) (4 diffs)
-
src/ResolvExpr/PtrsCastable.hpp (added)
-
src/ResolvExpr/RenameVars.cc (modified) (2 diffs)
-
src/ResolvExpr/ResolveAssertions.cc (modified) (1 diff)
-
src/ResolvExpr/Resolver.cc (modified) (6 diffs)
-
src/ResolvExpr/Resolver.h (modified) (1 diff)
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (5 diffs)
-
src/ResolvExpr/SpecCost.hpp (added)
-
src/ResolvExpr/Unify.cc (modified) (37 diffs)
-
src/ResolvExpr/Unify.h (modified) (2 diffs)
-
src/ResolvExpr/WidenMode.h (modified) (2 diffs)
-
src/ResolvExpr/module.mk (modified) (4 diffs)
-
src/ResolvExpr/typeops.h (modified) (7 diffs)
-
src/SymTab/Autogen.cc (modified) (4 diffs)
-
src/SymTab/Autogen.h (modified) (8 diffs)
-
src/SymTab/FixFunction.cc (modified) (1 diff)
-
src/SymTab/GenImplicitCall.cpp (added)
-
src/SymTab/GenImplicitCall.hpp (added)
-
src/SymTab/Indexer.cc (modified) (1 diff)
-
src/SymTab/Mangler.cc (modified) (6 diffs)
-
src/SymTab/Validate.cc (modified) (3 diffs)
-
src/SymTab/ValidateType.cc (modified) (1 diff)
-
src/SymTab/module.mk (modified) (1 diff)
-
src/SynTree/AggregateDecl.cc (modified) (1 diff)
-
src/SynTree/ApplicationExpr.cc (modified) (2 diffs)
-
src/SynTree/BasicType.cc (modified) (1 diff)
-
src/SynTree/FunctionDecl.cc (modified) (1 diff)
-
src/SynTree/Type.cc (modified) (2 diffs)
-
src/SynTree/Type.h (modified) (39 diffs)
-
src/Tuples/Explode.cc (modified) (1 diff)
-
src/Validate/Autogen.cpp (modified) (10 diffs)
-
src/Validate/FixQualifiedTypes.cpp (modified) (1 diff)
-
src/Validate/FixReturnTypes.cpp (modified) (1 diff)
-
src/Validate/ForallPointerDecay.cpp (modified) (1 diff)
-
src/Validate/GenericParameter.cpp (modified) (1 diff)
-
src/Validate/HandleAttributes.cc (modified) (1 diff)
-
src/Validate/HoistStruct.cpp (modified) (1 diff)
-
src/Validate/ReplaceTypedef.cpp (modified) (3 diffs)
-
src/Virtual/ExpandCasts.cc (modified) (1 diff)
-
src/Virtual/VirtualDtor.cpp (added)
-
src/Virtual/VirtualDtor.hpp (added)
-
src/Virtual/module.mk (modified) (1 diff)
-
src/include/cassert (modified) (1 diff)
-
src/main.cc (modified) (22 diffs)
-
tests/.expect/PRNG.x64.txt (modified) (1 diff)
-
tests/.expect/PRNG.x86.txt (modified) (1 diff)
-
tests/.expect/alloc.txt.old (deleted)
-
tests/.expect/array-ERR1.txt (added)
-
tests/.expect/array-ERR2.txt (added)
-
tests/.expect/array-ERR3.txt (added)
-
tests/.expect/array.txt (modified) (1 diff)
-
tests/.expect/attributes.arm64.txt (modified) (2 diffs)
-
tests/.expect/attributes.x64.txt (modified) (2 diffs)
-
tests/.expect/attributes.x86.txt (modified) (2 diffs)
-
tests/.expect/declarationSpecifier.arm64.txt (modified) (18 diffs)
-
tests/.expect/declarationSpecifier.x64.txt (modified) (18 diffs)
-
tests/.expect/declarationSpecifier.x86.txt (modified) (18 diffs)
-
tests/.expect/forall.txt (modified) (1 diff)
-
tests/.expect/nested_function.x64.txt (modified) (1 diff)
-
tests/.expect/nested_function.x86.txt (modified) (1 diff)
-
tests/Makefile.am (modified) (14 diffs)
-
tests/PRNG.cfa (modified) (19 diffs)
-
tests/array.cfa (modified) (1 diff)
-
tests/attributes.cfa (modified) (2 diffs)
-
tests/avltree/avl.h (modified) (1 diff)
-
tests/collections/vector-demo.cfa (modified) (1 diff)
-
tests/concurrency/.expect/clib.txt (added)
-
tests/concurrency/.expect/clib_tls.txt (added)
-
tests/concurrency/.expect/cluster.txt (added)
-
tests/concurrency/.expect/coroutineYield.txt (added)
-
tests/concurrency/.expect/ctor-check.txt (added)
-
tests/concurrency/.expect/join.txt (added)
-
tests/concurrency/.expect/joinerror.sed (added)
-
tests/concurrency/.expect/keywordErrors.txt (added)
-
tests/concurrency/.expect/lockfree_stack.txt (added)
-
tests/concurrency/.expect/mainError.txt (added)
-
tests/concurrency/.expect/migrate.txt (added)
-
tests/concurrency/.expect/monitor.txt (added)
-
tests/concurrency/.expect/multi-monitor.txt (added)
-
tests/concurrency/.expect/once.txt (added)
-
tests/concurrency/.expect/preempt.txt (added)
-
tests/concurrency/.expect/preempt2.txt (added)
-
tests/concurrency/.expect/sleep.txt (added)
-
tests/concurrency/.expect/suspend_then.txt (added)
-
tests/concurrency/.expect/thread.txt (added)
-
tests/concurrency/actors/.expect/dynamic.txt (added)
-
tests/concurrency/actors/.expect/executor.txt (added)
-
tests/concurrency/actors/.expect/inherit.txt (added)
-
tests/concurrency/actors/.expect/matrix.txt (added)
-
tests/concurrency/actors/.expect/pingpong.txt (added)
-
tests/concurrency/actors/.expect/poison.txt (added)
-
tests/concurrency/actors/.expect/static.txt (added)
-
tests/concurrency/actors/.expect/types.txt (added)
-
tests/concurrency/actors/dynamic.cfa (added)
-
tests/concurrency/actors/executor.cfa (added)
-
tests/concurrency/actors/inherit.cfa (added)
-
tests/concurrency/actors/matrix.cfa (added)
-
tests/concurrency/actors/pingpong.cfa (added)
-
tests/concurrency/actors/poison.cfa (added)
-
tests/concurrency/actors/static.cfa (added)
-
tests/concurrency/actors/types.cfa (added)
-
tests/concurrency/barrier/.expect/generation.txt (added)
-
tests/concurrency/barrier/.expect/last.txt (added)
-
tests/concurrency/barrier/.expect/order.txt (added)
-
tests/concurrency/barrier/gen_generation_expect.cfa (added)
-
tests/concurrency/barrier/generation.cfa (added)
-
tests/concurrency/barrier/last.cfa (added)
-
tests/concurrency/barrier/order.cfa (added)
-
tests/concurrency/channels/.expect/big_elems.txt (added)
-
tests/concurrency/channels/.expect/churn.txt (added)
-
tests/concurrency/channels/.expect/contend.txt (added)
-
tests/concurrency/channels/.expect/daisy_chain.txt (added)
-
tests/concurrency/channels/.expect/hot_potato.txt (added)
-
tests/concurrency/channels/.expect/ping_pong.txt (added)
-
tests/concurrency/channels/.expect/pub_sub.txt (added)
-
tests/concurrency/channels/.expect/zero_size.txt (added)
-
tests/concurrency/channels/barrier.cfa (added)
-
tests/concurrency/channels/big_elems.cfa (added)
-
tests/concurrency/channels/churn.cfa (added)
-
tests/concurrency/channels/contend.cfa (added)
-
tests/concurrency/channels/daisy_chain.cfa (added)
-
tests/concurrency/channels/hot_potato.cfa (added)
-
tests/concurrency/channels/parallel_harness.hfa (added)
-
tests/concurrency/channels/ping_pong.cfa (added)
-
tests/concurrency/channels/pub_sub.cfa (added)
-
tests/concurrency/channels/zero_size.cfa (added)
-
tests/concurrency/clib.c (added)
-
tests/concurrency/clib_tls.c (added)
-
tests/concurrency/cluster.cfa (added)
-
tests/concurrency/coroutineYield.cfa (added)
-
tests/concurrency/ctor-check.cfa (added)
-
tests/concurrency/examples/.expect/boundedBufferEXT.txt (added)
-
tests/concurrency/examples/.expect/boundedBufferINT.txt (added)
-
tests/concurrency/examples/.expect/datingService.txt (added)
-
tests/concurrency/examples/.expect/gortn.txt (added)
-
tests/concurrency/examples/.expect/matrixSum.txt (added)
-
tests/concurrency/examples/.expect/quickSort.txt (added)
-
tests/concurrency/examples/.in/quickSort.txt (added)
-
tests/concurrency/examples/boundedBufferEXT.cfa (added)
-
tests/concurrency/examples/boundedBufferINT.cfa (added)
-
tests/concurrency/examples/boundedBufferTHREAD.cfa (added)
-
tests/concurrency/examples/datingService.cfa (added)
-
tests/concurrency/examples/gortn.cfa (added)
-
tests/concurrency/examples/matrixSum.cfa (added)
-
tests/concurrency/examples/multiSort.cfa (added)
-
tests/concurrency/examples/quickSort.cfa (added)
-
tests/concurrency/examples/quickSort.generic.cfa (added)
-
tests/concurrency/futures/.expect/abandon.txt (added)
-
tests/concurrency/futures/.expect/basic.txt (added)
-
tests/concurrency/futures/.expect/multi.txt (added)
-
tests/concurrency/futures/.expect/select_future.txt (added)
-
tests/concurrency/futures/.expect/typed.txt (added)
-
tests/concurrency/futures/.expect/wait_any.txt (added)
-
tests/concurrency/futures/abandon.cfa (added)
-
tests/concurrency/futures/basic.cfa (added)
-
tests/concurrency/futures/multi.cfa (added)
-
tests/concurrency/futures/select_future.cfa (added)
-
tests/concurrency/futures/typed.cfa (added)
-
tests/concurrency/futures/wait_any.cfa (added)
-
tests/concurrency/join.cfa (added)
-
tests/concurrency/joinerror.cfa (added)
-
tests/concurrency/keywordErrors.cfa (added)
-
tests/concurrency/lockfree_stack.cfa (added)
-
tests/concurrency/mainError.cfa (added)
-
tests/concurrency/migrate.cfa (added)
-
tests/concurrency/monitor.cfa (added)
-
tests/concurrency/multi-monitor.cfa (added)
-
tests/concurrency/mutexstmt/.expect/locks.txt (added)
-
tests/concurrency/mutexstmt/.expect/monitors.txt (added)
-
tests/concurrency/mutexstmt/locks.cfa (added)
-
tests/concurrency/mutexstmt/monitors.cfa (added)
-
tests/concurrency/once.cfa (added)
-
tests/concurrency/park/.expect/contention.txt (added)
-
tests/concurrency/park/.expect/force_preempt.txt (added)
-
tests/concurrency/park/.expect/start_parked.txt (added)
-
tests/concurrency/park/contention.cfa (added)
-
tests/concurrency/park/force_preempt.cfa (added)
-
tests/concurrency/park/start_parked.cfa (added)
-
tests/concurrency/preempt.cfa (added)
-
tests/concurrency/preempt2.cfa (added)
-
tests/concurrency/pthread/.expect/bounded_buffer.x64.txt (added)
-
tests/concurrency/pthread/.expect/bounded_buffer.x86.txt (added)
-
tests/concurrency/pthread/.expect/pthread_attr_test.txt (added)
-
tests/concurrency/pthread/.expect/pthread_cond_test.txt (added)
-
tests/concurrency/pthread/.expect/pthread_demo_create_join.txt (added)
-
tests/concurrency/pthread/.expect/pthread_demo_lock.txt (added)
-
tests/concurrency/pthread/.expect/pthread_key_test.txt (added)
-
tests/concurrency/pthread/.expect/pthread_once_test.txt (added)
-
tests/concurrency/pthread/bounded_buffer.cfa (added)
-
tests/concurrency/pthread/pthread_attr_test.cfa (added)
-
tests/concurrency/pthread/pthread_cond_test.cfa (added)
-
tests/concurrency/pthread/pthread_demo_create_join.cfa (added)
-
tests/concurrency/pthread/pthread_demo_lock.cfa (added)
-
tests/concurrency/pthread/pthread_key_test.cfa (added)
-
tests/concurrency/pthread/pthread_once_test.cfa (added)
-
tests/concurrency/readyQ/.expect/barrier_sleeper.txt (added)
-
tests/concurrency/readyQ/.expect/leader_spin.txt (added)
-
tests/concurrency/readyQ/barrier_sleeper.cfa (added)
-
tests/concurrency/readyQ/leader_spin.cfa (added)
-
tests/concurrency/signal/.expect/block.txt (added)
-
tests/concurrency/signal/.expect/disjoint.txt (added)
-
tests/concurrency/signal/.expect/wait.txt (added)
-
tests/concurrency/signal/block.cfa (added)
-
tests/concurrency/signal/disjoint.cfa (added)
-
tests/concurrency/signal/wait.cfa (added)
-
tests/concurrency/sleep.cfa (added)
-
tests/concurrency/suspend_then.cfa (added)
-
tests/concurrency/thread.cfa (added)
-
tests/concurrency/unified_locking/.expect/block_spin_lock.txt (added)
-
tests/concurrency/unified_locking/.expect/exp_backoff.txt (added)
-
tests/concurrency/unified_locking/.expect/fast_block_lock.txt (added)
-
tests/concurrency/unified_locking/.expect/futex_mutex.txt (added)
-
tests/concurrency/unified_locking/.expect/locks.txt (added)
-
tests/concurrency/unified_locking/.expect/mcs.txt (added)
-
tests/concurrency/unified_locking/.expect/mcs_block_spin_lock.txt (added)
-
tests/concurrency/unified_locking/.expect/mcs_spin.txt (added)
-
tests/concurrency/unified_locking/.expect/pthread_locks.txt (added)
-
tests/concurrency/unified_locking/.expect/simple_owner_lock.txt (added)
-
tests/concurrency/unified_locking/.expect/spin_queue_lock.txt (added)
-
tests/concurrency/unified_locking/.expect/timeout_lock.txt (added)
-
tests/concurrency/unified_locking/block_spin_lock.cfa (added)
-
tests/concurrency/unified_locking/exp_backoff.cfa (added)
-
tests/concurrency/unified_locking/fast_block_lock.cfa (added)
-
tests/concurrency/unified_locking/futex_mutex.cfa (added)
-
tests/concurrency/unified_locking/locks.cfa (added)
-
tests/concurrency/unified_locking/mcs.cfa (added)
-
tests/concurrency/unified_locking/mcs_block_spin_lock.cfa (added)
-
tests/concurrency/unified_locking/mcs_spin.cfa (added)
-
tests/concurrency/unified_locking/mutex_test.hfa (added)
-
tests/concurrency/unified_locking/pthread_locks.cfa (added)
-
tests/concurrency/unified_locking/simple_owner_lock.cfa (added)
-
tests/concurrency/unified_locking/spin_queue_lock.cfa (added)
-
tests/concurrency/unified_locking/spintest.cfa (added)
-
tests/concurrency/unified_locking/test_debug.cfa (added)
-
tests/concurrency/unified_locking/thread_test.cfa (added)
-
tests/concurrency/unified_locking/timeout_lock.cfa (added)
-
tests/concurrency/waitfor/.expect/barge.txt (added)
-
tests/concurrency/waitfor/.expect/dtor.txt (added)
-
tests/concurrency/waitfor/.expect/else.txt (added)
-
tests/concurrency/waitfor/.expect/parse.txt (added)
-
tests/concurrency/waitfor/.expect/recurse.txt (added)
-
tests/concurrency/waitfor/.expect/statment.txt (added)
-
tests/concurrency/waitfor/.expect/when.txt (added)
-
tests/concurrency/waitfor/barge.cfa (added)
-
tests/concurrency/waitfor/dtor.cfa (added)
-
tests/concurrency/waitfor/else.cfa (added)
-
tests/concurrency/waitfor/parse.cfa (added)
-
tests/concurrency/waitfor/recurse.cfa (added)
-
tests/concurrency/waitfor/simple.cfa (added)
-
tests/concurrency/waitfor/statment.cfa (added)
-
tests/concurrency/waitfor/when.cfa (added)
-
tests/concurrency/waituntil/.expect/all_types.txt (added)
-
tests/concurrency/waituntil/.expect/basic_else.txt (added)
-
tests/concurrency/waituntil/.expect/channel_close.txt (added)
-
tests/concurrency/waituntil/.expect/channel_zero_size.txt (added)
-
tests/concurrency/waituntil/.expect/channels.txt (added)
-
tests/concurrency/waituntil/.expect/futures.txt (added)
-
tests/concurrency/waituntil/.expect/locks.txt (added)
-
tests/concurrency/waituntil/.expect/one_chan.txt (added)
-
tests/concurrency/waituntil/.expect/timeout.txt (added)
-
tests/concurrency/waituntil/all_types.cfa (added)
-
tests/concurrency/waituntil/basic_else.cfa (added)
-
tests/concurrency/waituntil/channel_close.cfa (added)
-
tests/concurrency/waituntil/channel_zero_size.cfa (added)
-
tests/concurrency/waituntil/channels.cfa (added)
-
tests/concurrency/waituntil/futures.cfa (added)
-
tests/concurrency/waituntil/locks.cfa (added)
-
tests/concurrency/waituntil/one_chan.cfa (added)
-
tests/concurrency/waituntil/timeout.cfa (added)
-
tests/concurrent/.expect/clib.txt (deleted)
-
tests/concurrent/.expect/clib_tls.txt (deleted)
-
tests/concurrent/.expect/cluster.txt (deleted)
-
tests/concurrent/.expect/coroutineYield.txt (deleted)
-
tests/concurrent/.expect/ctor-check.txt (deleted)
-
tests/concurrent/.expect/join.txt (deleted)
-
tests/concurrent/.expect/joinerror.sed (deleted)
-
tests/concurrent/.expect/keywordErrors.txt (deleted)
-
tests/concurrent/.expect/mainError.txt (deleted)
-
tests/concurrent/.expect/migrate.txt (deleted)
-
tests/concurrent/.expect/monitor.txt (deleted)
-
tests/concurrent/.expect/multi-monitor.txt (deleted)
-
tests/concurrent/.expect/once.txt (deleted)
-
tests/concurrent/.expect/preempt.txt (deleted)
-
tests/concurrent/.expect/preempt2.txt (deleted)
-
tests/concurrent/.expect/sleep.txt (deleted)
-
tests/concurrent/.expect/suspend_then.txt (deleted)
-
tests/concurrent/.expect/thread.txt (deleted)
-
tests/concurrent/barrier/.expect/generation.txt (deleted)
-
tests/concurrent/barrier/.expect/last.txt (deleted)
-
tests/concurrent/barrier/.expect/order.txt (deleted)
-
tests/concurrent/barrier/gen_generation_expect.cfa (deleted)
-
tests/concurrent/barrier/generation.cfa (deleted)
-
tests/concurrent/barrier/last.cfa (deleted)
-
tests/concurrent/barrier/order.cfa (deleted)
-
tests/concurrent/clib.c (deleted)
-
tests/concurrent/clib_tls.c (deleted)
-
tests/concurrent/cluster.cfa (deleted)
-
tests/concurrent/coroutineYield.cfa (deleted)
-
tests/concurrent/ctor-check.cfa (deleted)
-
tests/concurrent/examples/.expect/boundedBufferEXT.txt (deleted)
-
tests/concurrent/examples/.expect/boundedBufferINT.txt (deleted)
-
tests/concurrent/examples/.expect/datingService.txt (deleted)
-
tests/concurrent/examples/.expect/gortn.txt (deleted)
-
tests/concurrent/examples/.expect/matrixSum.txt (deleted)
-
tests/concurrent/examples/.expect/quickSort.txt (deleted)
-
tests/concurrent/examples/.in/quickSort.txt (deleted)
-
tests/concurrent/examples/boundedBufferEXT.cfa (deleted)
-
tests/concurrent/examples/boundedBufferINT.cfa (deleted)
-
tests/concurrent/examples/boundedBufferTHREAD.cfa (deleted)
-
tests/concurrent/examples/datingService.cfa (deleted)
-
tests/concurrent/examples/gortn.cfa (deleted)
-
tests/concurrent/examples/matrixSum.cfa (deleted)
-
tests/concurrent/examples/multiSort.cfa (deleted)
-
tests/concurrent/examples/quickSort.cfa (deleted)
-
tests/concurrent/examples/quickSort.generic.cfa (deleted)
-
tests/concurrent/futures/.expect/abandon.txt (deleted)
-
tests/concurrent/futures/.expect/basic.txt (deleted)
-
tests/concurrent/futures/.expect/multi.txt (deleted)
-
tests/concurrent/futures/.expect/typed.txt (deleted)
-
tests/concurrent/futures/.expect/wait_any.txt (deleted)
-
tests/concurrent/futures/abandon.cfa (deleted)
-
tests/concurrent/futures/basic.cfa (deleted)
-
tests/concurrent/futures/multi.cfa (deleted)
-
tests/concurrent/futures/typed.cfa (deleted)
-
tests/concurrent/futures/wait_any.cfa (deleted)
-
tests/concurrent/join.cfa (deleted)
-
tests/concurrent/joinerror.cfa (deleted)
-
tests/concurrent/keywordErrors.cfa (deleted)
-
tests/concurrent/mainError.cfa (deleted)
-
tests/concurrent/migrate.cfa (deleted)
-
tests/concurrent/monitor.cfa (deleted)
-
tests/concurrent/multi-monitor.cfa (deleted)
-
tests/concurrent/mutexstmt/.expect/locks.txt (deleted)
-
tests/concurrent/mutexstmt/.expect/monitors.txt (deleted)
-
tests/concurrent/mutexstmt/.expect/scoped_lock.txt (deleted)
-
tests/concurrent/mutexstmt/locks.cfa (deleted)
-
tests/concurrent/mutexstmt/monitors.cfa (deleted)
-
tests/concurrent/mutexstmt/scoped_lock.cfa (deleted)
-
tests/concurrent/once.cfa (deleted)
-
tests/concurrent/park/.expect/contention.txt (deleted)
-
tests/concurrent/park/.expect/force_preempt.txt (deleted)
-
tests/concurrent/park/.expect/start_parked.txt (deleted)
-
tests/concurrent/park/contention.cfa (deleted)
-
tests/concurrent/park/force_preempt.cfa (deleted)
-
tests/concurrent/park/start_parked.cfa (deleted)
-
tests/concurrent/preempt.cfa (deleted)
-
tests/concurrent/preempt2.cfa (deleted)
-
tests/concurrent/pthread/.expect/bounded_buffer.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_attr_test.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_cond_test.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_demo_create_join.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_demo_lock.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_key_test.txt (deleted)
-
tests/concurrent/pthread/.expect/pthread_once_test.txt (deleted)
-
tests/concurrent/pthread/bounded_buffer.cfa (deleted)
-
tests/concurrent/pthread/pthread_attr_test.cfa (deleted)
-
tests/concurrent/pthread/pthread_cond_test.cfa (deleted)
-
tests/concurrent/pthread/pthread_demo_create_join.cfa (deleted)
-
tests/concurrent/pthread/pthread_demo_lock.cfa (deleted)
-
tests/concurrent/pthread/pthread_key_test.cfa (deleted)
-
tests/concurrent/pthread/pthread_once_test.cfa (deleted)
-
tests/concurrent/readyQ/.expect/barrier_sleeper.txt (deleted)
-
tests/concurrent/readyQ/.expect/leader_spin.txt (deleted)
-
tests/concurrent/readyQ/barrier_sleeper.cfa (deleted)
-
tests/concurrent/readyQ/leader_spin.cfa (deleted)
-
tests/concurrent/signal/.expect/block.txt (deleted)
-
tests/concurrent/signal/.expect/disjoint.txt (deleted)
-
tests/concurrent/signal/.expect/wait.txt (deleted)
-
tests/concurrent/signal/block.cfa (deleted)
-
tests/concurrent/signal/disjoint.cfa (deleted)
-
tests/concurrent/signal/wait.cfa (deleted)
-
tests/concurrent/sleep.cfa (deleted)
-
tests/concurrent/suspend_then.cfa (deleted)
-
tests/concurrent/thread.cfa (deleted)
-
tests/concurrent/waitfor/.expect/barge.txt (deleted)
-
tests/concurrent/waitfor/.expect/dtor.txt (deleted)
-
tests/concurrent/waitfor/.expect/else.txt (deleted)
-
tests/concurrent/waitfor/.expect/recurse.txt (deleted)
-
tests/concurrent/waitfor/.expect/statment.txt (deleted)
-
tests/concurrent/waitfor/.expect/when.txt (deleted)
-
tests/concurrent/waitfor/barge.cfa (deleted)
-
tests/concurrent/waitfor/dtor.cfa (deleted)
-
tests/concurrent/waitfor/else.cfa (deleted)
-
tests/concurrent/waitfor/parse.cfa (deleted)
-
tests/concurrent/waitfor/parse2.cfa (deleted)
-
tests/concurrent/waitfor/recurse.cfa (deleted)
-
tests/concurrent/waitfor/simple.cfa (deleted)
-
tests/concurrent/waitfor/statment.cfa (deleted)
-
tests/concurrent/waitfor/when.cfa (deleted)
-
tests/declarationSpecifier.cfa (modified) (3 diffs)
-
tests/enum_tests/.expect/pointerEnum.cfa (deleted)
-
tests/enum_tests/.expect/qualifiedEnum.cfa (deleted)
-
tests/enum_tests/.expect/typedIntEnum.txt (modified) (1 diff)
-
tests/enum_tests/pointerEnum.cfa (modified) (1 diff)
-
tests/enum_tests/typedIntEnum.cfa (modified) (1 diff)
-
tests/errors/.expect/declaration.txt (modified) (3 diffs)
-
tests/forall.cfa (modified) (11 diffs)
-
tests/function-operator.cfa (modified) (2 diffs)
-
tests/include/includes.cfa (modified) (5 diffs)
-
tests/io/comp_basic.cfa (modified) (1 diff)
-
tests/io/comp_fair.cfa (modified) (1 diff)
-
tests/linking/mangling/.expect/anon.txt (added)
-
tests/linking/mangling/header.hfa (modified) (1 diff)
-
tests/linking/mangling/lib.cfa (modified) (1 diff)
-
tests/linking/mangling/main.cfa (modified) (2 diffs)
-
tests/pybin/settings.py (modified) (2 diffs)
-
tests/quotedKeyword.cfa (modified) (1 diff)
-
tests/sum.cfa (modified) (2 diffs)
-
tests/test.py (modified) (3 diffs)
-
tests/unified_locking/.expect/block_spin_lock.txt (deleted)
-
tests/unified_locking/.expect/clh.txt (deleted)
-
tests/unified_locking/.expect/fast_block_lock.txt (deleted)
-
tests/unified_locking/.expect/futex_mutex.txt (deleted)
-
tests/unified_locking/.expect/lin_backoff.txt (deleted)
-
tests/unified_locking/.expect/locks.txt (deleted)
-
tests/unified_locking/.expect/mcs.txt (deleted)
-
tests/unified_locking/.expect/mcs_block_spin_lock.txt (deleted)
-
tests/unified_locking/.expect/mcs_spin.txt (deleted)
-
tests/unified_locking/.expect/pthread_locks.txt (deleted)
-
tests/unified_locking/.expect/simple_owner_lock.txt (deleted)
-
tests/unified_locking/.expect/spin_queue_lock.txt (deleted)
-
tests/unified_locking/.expect/timeout_lock.txt (deleted)
-
tests/unified_locking/block_spin_lock.cfa (deleted)
-
tests/unified_locking/clh.cfa (deleted)
-
tests/unified_locking/fast_block_lock.cfa (deleted)
-
tests/unified_locking/futex_mutex.cfa (deleted)
-
tests/unified_locking/lin_backoff.cfa (deleted)
-
tests/unified_locking/locks.cfa (deleted)
-
tests/unified_locking/mcs.cfa (deleted)
-
tests/unified_locking/mcs_block_spin_lock.cfa (deleted)
-
tests/unified_locking/mcs_spin.cfa (deleted)
-
tests/unified_locking/mutex_test.hfa (deleted)
-
tests/unified_locking/pthread_locks.cfa (deleted)
-
tests/unified_locking/simple_owner_lock.cfa (deleted)
-
tests/unified_locking/spin_queue_lock.cfa (deleted)
-
tests/unified_locking/thread_test.cfa (deleted)
-
tests/unified_locking/timeout_lock.cfa (deleted)
-
tests/zombies/prolog.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/FullBuild
r34b4268 r24d6572 20 20 gcc_08_x86_new: { trigger_build( 'gcc-10', 'x86', false ) }, 21 21 gcc_07_x86_new: { trigger_build( 'gcc-9', 'x86', false ) }, 22 gcc_11_x64_new: { trigger_build( 'gcc-11', 'x64', false ) }, 22 23 gcc_10_x64_new: { trigger_build( 'gcc-10', 'x64', false ) }, 23 24 gcc_09_x64_new: { trigger_build( 'gcc-9', 'x64', false ) }, 24 25 gcc_08_x64_new: { trigger_build( 'gcc-8', 'x64', false ) }, 25 26 gcc_07_x64_new: { trigger_build( 'gcc-7', 'x64', false ) }, 26 gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) },27 // gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) }, 27 28 clang_x64_new: { trigger_build( 'clang', 'x64', true ) }, 28 29 ) … … 41 42 } 42 43 43 // If an exception is caught we need to change the status and remember to44 // attach the build log to the email44 // If an exception is caught we need to change the status and remember to 45 // attach the build log to the email 45 46 catch (Exception caughtError) { 46 47 echo('error caught') … … 73 74 // Run the build 74 75 // Don't propagate, it doesn't play nice with our email setup 75 def result = build job: 'Cforall/master', \76 def result = build job: 'Cforall/master', \ 76 77 parameters: [ \ 77 78 [$class: 'StringParameterValue', \ … … 83 84 [$class: 'BooleanParameterValue', \ 84 85 name: 'NewAST', \ 85 value: true], \86 value: true], \ 86 87 [$class: 'BooleanParameterValue', \ 87 88 name: 'RunAllTests', \ 88 value: true], \89 value: true], \ 89 90 [$class: 'BooleanParameterValue', \ 90 91 name: 'RunBenchmark', \ 91 value: true], \92 value: true], \ 92 93 [$class: 'BooleanParameterValue', \ 93 name: 'BuildDocumentation', \94 name: 'BuildDocumentation', \ 94 95 value: doc], \ 95 96 [$class: 'BooleanParameterValue', \ 96 97 name: 'Publish', \ 97 value: true], \98 value: true], \ 98 99 [$class: 'BooleanParameterValue', \ 99 100 name: 'Silent', \ 100 value: true], \101 ], \101 value: true], \ 102 ], \ 102 103 propagate: false 103 104 … … 111 112 112 113 def trigger_dist(String commitId, String buildNum) { 113 def result = build job: 'Cforall_Distribute_Ref', \114 def result = build job: 'Cforall_Distribute_Ref', \ 114 115 parameters: [ \ 115 116 string(name: 'GitRef', value: commitId), \ 116 string(name: 'Build' , value: buildNum) \117 ], \117 string(name: 'Build' , value: buildNum) \ 118 ], \ 118 119 propagate: false 119 120 -
Jenkins/Promote
r34b4268 r24d6572 36 36 dir (BuildDir) { 37 37 sh 'rm -rf *' 38 sshagent (credentials: ['git hub_key_jun1']) {38 sshagent (credentials: ['git_key_mar27']) { 39 39 sh "git clone --bare ${RemoteRepo} repo" 40 40 } … … 69 69 sh "git status" 70 70 sh "git diff-index --quiet HEAD || git commit -m 'Push from build machine: ${name}'" 71 sshagent (credentials: ['git hub_key_jun1']) {71 sshagent (credentials: ['git_key_mar27']) { 72 72 sh "git push origin master" 73 73 } -
Jenkinsfile
r34b4268 r24d6572 155 155 dir (BuildDir) { 156 156 //Run the tests from the tests directory 157 sh """make ${jopt} --no-print-directory -C tests timeout s="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""157 sh """make ${jopt} --no-print-directory -C tests timeout=600 global-timeout=14400 tests debug=yes archive-errors=${BuildDir}/tests/crashes/full-debug""" 158 158 } 159 159 } … … 162 162 dir (BuildDir) { 163 163 //Run the tests from the tests directory 164 sh """make ${jopt} --no-print-directory -C tests timeout s="--timeout=600 --global-timeout=14400" all-tests debug=no archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""164 sh """make ${jopt} --no-print-directory -C tests timeout=600 global-timeout=14400 tests debug=no archive-errors=${BuildDir}/tests/crashes/full-nodebug""" 165 165 } 166 166 } … … 305 305 this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto') 306 306 break 307 case 'gcc-6':308 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')309 break310 case 'gcc-5':311 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')312 break313 case 'gcc-4.9':314 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')315 break307 // case 'gcc-6': 308 // this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto') 309 // break 310 // case 'gcc-5': 311 // this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto') 312 // break 313 // case 'gcc-4.9': 314 // this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto') 315 // break 316 316 case 'clang': 317 317 this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-10', '-flto=thin -flto-jobs=0') … … 359 359 def prepare_build() { 360 360 // prepare the properties 361 properties ([ \362 buildDiscarder(logRotator( \363 artifactDaysToKeepStr: '', \364 artifactNumToKeepStr: '', \365 daysToKeepStr: '730', \366 numToKeepStr: '1000' \367 )), \368 [$class: 'ParametersDefinitionProperty', \369 parameterDefinitions: [ \370 [$class: 'ChoiceParameterDefinition', \371 description: 'Which compiler to use', \372 name: 'Compiler', \373 choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\n gcc-6\ngcc-5\ngcc-4.9\nclang', \374 defaultValue: 'gcc- 8',\375 ], \376 [$class: 'ChoiceParameterDefinition', \377 description: 'The target architecture', \378 name: 'Architecture', \379 choices: 'x64\nx86', \380 defaultValue: 'x64', \381 ], \382 [$class: 'BooleanParameterDefinition', \361 properties ([ \ 362 buildDiscarder(logRotator( \ 363 artifactDaysToKeepStr: '', \ 364 artifactNumToKeepStr: '', \ 365 daysToKeepStr: '730', \ 366 numToKeepStr: '1000' \ 367 )), \ 368 [$class: 'ParametersDefinitionProperty', \ 369 parameterDefinitions: [ \ 370 [$class: 'ChoiceParameterDefinition', \ 371 description: 'Which compiler to use', \ 372 name: 'Compiler', \ 373 choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\nclang', \ 374 defaultValue: 'gcc-9', \ 375 ], \ 376 [$class: 'ChoiceParameterDefinition', \ 377 description: 'The target architecture', \ 378 name: 'Architecture', \ 379 choices: 'x64\nx86', \ 380 defaultValue: 'x64', \ 381 ], \ 382 [$class: 'BooleanParameterDefinition', \ 383 383 description: 'If false, the test suite is only ran in debug', \ 384 name: 'RunAllTests', \385 defaultValue: false, \386 ], \387 [$class: 'BooleanParameterDefinition', \388 description: 'If true, jenkins also runs benchmarks', \389 name: 'RunBenchmark', \390 defaultValue: false, \391 ], \392 [$class: 'BooleanParameterDefinition', \393 description: 'If true, jenkins also builds documentation', \394 name: 'BuildDocumentation', \395 defaultValue: true, \396 ], \397 [$class: 'BooleanParameterDefinition', \398 description: 'If true, jenkins also publishes results', \399 name: 'Publish', \400 defaultValue: false, \401 ], \402 [$class: 'BooleanParameterDefinition', \403 description: 'If true, jenkins will not send emails', \404 name: 'Silent', \405 defaultValue: false, \406 ], \384 name: 'RunAllTests', \ 385 defaultValue: false, \ 386 ], \ 387 [$class: 'BooleanParameterDefinition', \ 388 description: 'If true, jenkins also runs benchmarks', \ 389 name: 'RunBenchmark', \ 390 defaultValue: false, \ 391 ], \ 392 [$class: 'BooleanParameterDefinition', \ 393 description: 'If true, jenkins also builds documentation', \ 394 name: 'BuildDocumentation', \ 395 defaultValue: true, \ 396 ], \ 397 [$class: 'BooleanParameterDefinition', \ 398 description: 'If true, jenkins also publishes results', \ 399 name: 'Publish', \ 400 defaultValue: false, \ 401 ], \ 402 [$class: 'BooleanParameterDefinition', \ 403 description: 'If true, jenkins will not send emails', \ 404 name: 'Silent', \ 405 defaultValue: false, \ 406 ], \ 407 407 ], 408 408 ]]) 409 // choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', 410 // defaultValue: 'gcc-8', 409 411 410 412 // It's unfortunate but it looks like we need to checkout the entire repo just to get -
Makefile.am
r34b4268 r24d6572 11 11 ## Created On : Sun May 31 22:14:18 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Sat Feb 2 16:54:42 201914 ## Update Count : 2113 ## Last Modified On : Wed May 17 11:02:34 2023 14 ## Update Count : 56 15 15 ############################################################################### 16 16 … … 24 24 DIST_SUBDIRS = driver src . libcfa tests 25 25 26 @LIBCFA_TARGET_MAKEFILES@ : Makefile $ (srcdir)/libcfa/configure27 @$ (eval config_file = $(dir $@)config.data)28 @ls $ (config_file)|| (echo "Missing config.data, re-run configure script again" && false)29 @$ (eval config_data = $(shell cat $(config_file)))30 @echo "Configuring libcfa ($ (abs_top_srcdir)/libcfa/configure) with '$(config_data)' from $(shell pwd) / $(dir $@)"31 @cd $ (dir $@) && $(abs_top_srcdir)/libcfa/configure $(config_data)26 @LIBCFA_TARGET_MAKEFILES@ : Makefile ${srcdir}/libcfa/configure 27 @${eval config_file = ${dir ${@}}config.data} 28 @ls ${config_file} || (echo "Missing config.data, re-run configure script again" && false) 29 @${eval config_data = ${shell cat ${config_file}}} 30 @echo "Configuring libcfa (${abs_top_srcdir}/libcfa/configure) with '${config_data}' from ${shell pwd} / ${dir ${@}}" 31 @cd ${dir ${@}} && ${abs_top_srcdir}/libcfa/configure ${config_data} 32 32 33 33 noinst_DATA = @LIBCFA_TARGET_MAKEFILES@ … … 37 37 EXTRA_DIST = LICENSE doc/man/cfa.1 libcfa/configure libcfa/Makefile.dist.am libcfa/Makefile.dist.in tools/build/distcc_hash tools/build/push2dist.sh 38 38 39 debug=yes 40 check: 41 $(MAKE) -C tests all-tests installed=no debug=${debug} 39 debug ?= yes 40 installed ?= no 41 ARCH = ${if ${arch},"arch=${arch}"} 42 arch_support = "x86/x64/arm" 42 43 43 installcheck: 44 $(MAKE) -C tests all-tests installed=yes debug=${debug} 44 # target "all" created by automake 45 45 46 c onfigure-libcfa: @LIBCFA_TARGET_MAKEFILES@47 @true46 check : 47 ${MAKE} -C tests tests installed=${installed} debug=${debug} ${ARCH} 48 48 49 status: @LIBCFA_TARGET_MAKEFILES@ 49 tests : check # synonym 50 51 installcheck : 52 ${MAKE} -C tests tests installed=yes debug=${debug} ${ARCH} 53 54 installtest : installcheck # synonym 55 56 status : @LIBCFA_TARGET_MAKEFILES@ 50 57 @echo -ne "translator\n\t" 51 58 @./config.status --config | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g" 52 59 @find libcfa -name config.status -printf "\n%h\n\t" -exec {} --config \; | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g" 53 60 54 @LIBCFA_TARGET_DIRS@:: 55 $(MAKE) -C $@ $(MAKECMDGOALS) 61 help : 62 @echo "user targets:" 63 @echo " Compile compiler/runtime." 64 @echo " $$ make (null) / all" 65 @echo "" 66 @echo " Compile compiler/runtime and run test suite." 67 @echo " $$ make check / tests [debug=yes/no] [installed=yes/no] [arch=${arch_support}]" 68 @echo "" 69 @echo " Compile compiler/runtime, install, and run test suite on installed system." 70 @echo " $$ make installcheck / installtests [debug=yes/no] installed=yes [arch=${arch_support}]" 71 @echo "" 72 @echo " Print configuration parameters and system build information." 73 @echo " $$ make status" 56 74 57 mostlyclean clean distclean maintainer-clean: @LIBCFA_TARGET_DIRS@ 75 configure-libcfa : @LIBCFA_TARGET_MAKEFILES@ 76 @true 77 78 @LIBCFA_TARGET_DIRS@ :: 79 ${MAKE} -C ${@} ${MAKECMDGOALS} 80 81 mostlyclean clean distclean maintainer-clean : @LIBCFA_TARGET_DIRS@ -
benchmark/Makefile.am
r34b4268 r24d6572 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Tue Mar 10 11:41:18 202014 ## Update Count : 2 5813 ## Last Modified On : Fri May 26 12:13:48 2023 14 ## Update Count : 260 15 15 ############################################################################### 16 16 … … 374 374 ## ========================================================================================================= 375 375 376 mutexStmt$(EXEEXT) : \377 mutexStmt-cpp1.run \378 mutexStmt-cpp2.run \379 mutexStmt-cpp4.run \380 mutexStmt-cpp8.run \381 mutexStmt-java.run \382 mutexStmt-lock1.run \383 mutexStmt-lock2.run \384 mutexStmt-lock4.run \385 mutexStmt-lock8.run \386 mutexStmt-no-stmt-lock1.run \387 mutexStmt-no-stmt-lock2.run \388 mutexStmt-no-stmt-lock4.run \389 mutexStmt-no-stmt-lock8.run \390 mutexStmt-monitor1.run \391 mutexStmt-monitor2.run \376 mutexStmt$(EXEEXT) : \ 377 mutexStmt-cpp1.run \ 378 mutexStmt-cpp2.run \ 379 mutexStmt-cpp4.run \ 380 mutexStmt-cpp8.run \ 381 mutexStmt-java.run \ 382 mutexStmt-lock1.run \ 383 mutexStmt-lock2.run \ 384 mutexStmt-lock4.run \ 385 mutexStmt-lock8.run \ 386 mutexStmt-no-stmt-lock1.run \ 387 mutexStmt-no-stmt-lock2.run \ 388 mutexStmt-no-stmt-lock4.run \ 389 mutexStmt-no-stmt-lock8.run \ 390 mutexStmt-monitor1.run \ 391 mutexStmt-monitor2.run \ 392 392 mutexStmt-monitor4.run 393 393 … … 567 567 compile-array.make \ 568 568 compile-attributes.make \ 569 compile-empty.make \569 compile-empty.make \ 570 570 compile-expression.make \ 571 571 compile-io.make \ … … 592 592 593 593 compile-monitor$(EXEEXT): 594 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurren t/monitor.cfa594 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrency/monitor.cfa 595 595 596 596 compile-operators$(EXEEXT): … … 598 598 599 599 compile-thread$(EXEEXT): 600 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurren t/thread.cfa600 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrency/thread.cfa 601 601 602 602 compile-typeof$(EXEEXT): -
configure.ac
r34b4268 r24d6572 47 47 48 48 #============================================================================== 49 # HACK to be able to use condition nals inside makefiles49 # HACK to be able to use conditionals inside makefiles 50 50 DOifskipcompile='ifeq ($(skipcompile),yes) 51 51 else' … … 226 226 AC_PROG_YACC 227 227 if test "${YACC}" = "yacc" ; then echo "Error: bison required." ; exit 1 ; fi 228 AC_PROG_LEX 228 AC_PROG_LEX(yywrap) 229 229 if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi 230 AC_PROG_LIBTOOL 230 LT_INIT 231 231 AC_PROG_INSTALL 232 232 … … 284 284 tools/Makefile 285 285 tools/prettyprinter/Makefile 286 benchmark/Cargo.toml 286 287 ]) 287 288 AC_OUTPUT(benchmark/Cargo.toml)289 288 ]) 290 289 291 290 AC_CONFIG_LINKS([tests/test.py:tests/test.py]) 292 293 AC_OUTPUT(tests/config.py) 291 AC_CONFIG_FILES([tests/config.py]) 292 293 AC_OUTPUT 294 294 295 295 # Final text -
doc/LaTeXmacros/common.sty
r34b4268 r24d6572 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sat Apr 2 17:35:23 202214 %% Update Count : 5 7013 %% Last Modified On : Tue Apr 4 12:03:19 2023 14 %% Update Count : 585 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \setlist[itemize,1]{label=\textbullet}% local 31 31 %\renewcommand{\labelitemi}{{\raisebox{0.25ex}{\footnotesize$\bullet$}}} 32 \setlist[enumerate]{ listparindent=\parindent}% global32 \setlist[enumerate]{topsep=0.5ex,parsep=0.25ex,itemsep=0.25ex,listparindent=\parindent}% global 33 33 \setlist[enumerate,2]{leftmargin=\parindent,labelsep=*,align=parleft,label=\alph*.}% local 34 34 \setlist[description]{topsep=0.5ex,itemsep=0pt,listparindent=\parindent,leftmargin=\parindent,labelsep=1.5ex} … … 49 49 \newcommand{\CCseventeen}{\protect\CCIcon{17}\xspace} % C++17 symbolic name 50 50 \newcommand{\CCtwenty}{\protect\CCIcon{20}\xspace} % C++20 symbolic name 51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\ Large$^\sharp$}\xspace} % C# symbolic name51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\relsize{2}$^\sharp$}\xspace} % C# symbolic name 52 52 53 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 54 55 \usepackage{pslatex} % reduce size of san serif font 55 \usepackage[scaled=0.85]{helvet} % descent Helvetica font and scale to times size 56 \usepackage[T1]{fontenc} 56 57 \usepackage{relsize} % must be after change to small or selects old size 57 58 \usepackage{rotating} … … 195 196 \newcommand{\viz}{\VIZ\CheckPeriod} 196 197 198 \newcommand{\VS}{\abbrevFont{vs}} 199 \newcommand{\vs}{\VS\CheckPeriod} 200 197 201 \newenvironment{cquote}{% 198 202 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}% … … 244 248 \renewcommand{\reftextpagerange}[2]{\unskip, pp.~\pageref{#1}--\pageref{#2}} 245 249 \newcommand{\VRef}[2][Section]{\ifx#1\@empty\else{#1}\nobreakspace\fi\vref{#2}} 250 \newcommand{\VRefrange}[3][Sections]{\ifx#1\@empty\else{#1}\nobreakspace\fi\vrefrange{#2}{#3}} 246 251 \newcommand{\VPageref}[2][page]{\ifx#1\@empty\else{#1}\nobreakspace\fi\pageref{#2}} 252 \newcommand{\VPagerefrange}[3][pages]{\ifx#1\@empty\else{#1}\nobreakspace\fi\pageref{#2}{#3}} 247 253 248 254 \let\Oldthebibliography\thebibliography … … 260 266 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 261 267 \newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}} 268 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}} 262 269 263 270 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly … … 280 287 columns=fullflexible, 281 288 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font 282 stringstyle=\ tt,% use typewriter font289 stringstyle=\small\tt, % use typewriter font 283 290 tabsize=5, % N space tabbing 284 291 xleftmargin=\parindentlnth, % indent code to paragraph indentation -
doc/LaTeXmacros/common.tex
r34b4268 r24d6572 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Apr 26 16:02:48 202214 %% Update Count : 5 5813 %% Last Modified On : Tue Apr 4 12:03:18 2023 14 %% Update Count : 567 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 49 49 \newcommand{\CCseventeen}{\protect\CCIcon{17}\xspace} % C++17 symbolic name 50 50 \newcommand{\CCtwenty}{\protect\CCIcon{20}\xspace} % C++20 symbolic name 51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\ Large$^\sharp$}\xspace} % C# symbolic name51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\relsize{2}$^\sharp$}\xspace} % C# symbolic name 52 52 53 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 54 55 \usepackage{pslatex} % reduce size of san serif font 55 \usepackage[scaled=0.85]{helvet} % descent Helvetica font and scale to times size 56 \usepackage[T1]{fontenc} 56 57 \usepackage{relsize} % must be after change to small or selects old size 57 58 \usepackage{rotating} … … 196 197 \newcommand{\viz}{\VIZ\CheckPeriod} 197 198 199 \newcommand{\VS}{\abbrevFont{vs}} 200 \newcommand{\vs}{\VS\CheckPeriod} 198 201 \makeatother 199 202 … … 266 269 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 267 270 \newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}} 271 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}} 268 272 269 273 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly … … 287 291 columns=fullflexible, 288 292 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font 289 stringstyle=\ tt,% use typewriter font293 stringstyle=\small\tt, % use typewriter font 290 294 tabsize=5, % N space tabbing 291 295 xleftmargin=\parindentlnth, % indent code to paragraph indentation -
doc/LaTeXmacros/lstlang.sty
r34b4268 r24d6572 8 8 %% Created On : Sat May 13 16:34:42 2017 9 9 %% Last Modified By : Peter A. Buhr 10 %% Last Modified On : Mon May 31 08:20:41 202111 %% Update Count : 2810 %% Last Modified On : Tue May 2 08:52:35 2023 11 %% Update Count : 30 12 12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 13 … … 112 112 \lstdefinelanguage{CFA}[ANSI]{C}{ 113 113 morekeywords={ 114 _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, __attribute, __attribute__, 115 auto, basetypeof, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__, 116 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, fixup, 117 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__, 118 inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or, 119 otype, restrict, __restrict, __restrict__, recover, report, __signed, __signed__, _Static_assert, suspend, 120 thread, __thread, _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__, 121 virtual, __volatile, __volatile__, waitfor, when, with, zero_t, 114 _Alignas, _Alignof, __alignof, __alignof__, and, asm, __asm, __asm__, _Atomic, __attribute, __attribute__, 115 __auto_type, basetypeof, _Bool, catch, catchResume, choose, coerce, _Complex, __complex, __complex__, __const, __const__, 116 coroutine, _Decimal32, _Decimal64, _Decimal128, disable, enable, exception, __extension__, fallthrough, fallthru, finally, fixup, 117 __float80, float80, __float128, float128, _Float16, _Float32, _Float32x, _Float64, _Float64x, _Float128, _Float128x, 118 forall, fortran, generator, _Generic, _Imaginary, __imag, __imag__, inline, __inline, __inline__, int128, __int128, __int128_t, 119 __label__, monitor, mutex, _Noreturn, __builtin_offsetof, one_t, or, recover, report, restrict, __restrict, __restrict__, 120 __signed, __signed__, _Static_assert, suspend, thread, __thread, _Thread_local, throw, throwResume, timeout, trait, try, 121 typeof, __typeof, __typeof__, typeid, __uint128_t, __builtin_va_arg, __builtin_va_list, virtual, __volatile, __volatile__, 122 vtable, waitfor, waituntil, when, with, zero_t, 122 123 }, 123 124 moredirectives={defined,include_next}% -
doc/bibliography/pl.bib
r34b4268 r24d6572 147 147 author = {Zhang, Yizhou and Salvaneschi, Guido and Beightol, Quinn and Liskov, Barbara and Myers, Andrew C.}, 148 148 title = {Accepting Blame for Safe Tunneled Exceptions}, 149 booktitle= {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation},149 organization= {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation}, 150 150 series = {PLDI'16}, 151 151 year = {2016}, … … 198 198 } 199 199 200 @inproceedings{Koster16, 201 keywords = {Actor Model, Concurrency}, 202 contributer = {pabuhr@plg}, 203 author = {De Koster, Joeri and Van Cutsem, Tom and De Meuter, Wolfgang}, 204 title = {43 Years of Actors: A Taxonomy of Actor Models and Their Key Properties}, 205 publisher = {ACM}, 206 address = {New York, NY, USA}, 207 organization= {Proceedings of the 6th International Workshop on Programming Based on Actors, Agents, and Decentralized Control}, 208 pages = {31-40}, 209 numpages = {10}, 210 year = {2016}, 211 location = {Amsterdam, Netherlands}, 212 series = {AGERE 2016} 213 } 214 215 @misc{ActorBenchmarks, 216 keywords = {Actors, microbenchmarks, uC++. CAF, ProtoActor, AkkaC, AkkaT}, 217 contributer = {pabuhr@plg}, 218 key = {ActorBenchmarks}, 219 title = {Actor Benchmarks}, 220 author = {Peter A. Buhr and Colby A. Parsons}, 221 howpublished= {\href{https://github.com/pabuhr/ActorExperiments}{https://\-github.com/\-pabuhr/\-ActorExperiments}}, 222 year = 2022, 223 } 224 200 225 @book{Actors, 201 226 keywords = {actors, concurrency}, … … 205 230 publisher = {MIT Press, Cambridge}, 206 231 year = 1986 232 } 233 234 @inproceedings{Srinivasan08, 235 author = {Srinivasan, Sriram and Mycroft, Alan}, 236 editor = {Vitek, Jan}, 237 title = {Kilim: Isolation-Typed Actors for Java}, 238 organization= {ECOOP 2008 -- Object-Oriented Programming}, 239 year = {2008}, 240 publisher = {Springer Berlin Heidelberg}, 241 address = {Berlin, Heidelberg}, 242 pages = {104--128}, 243 } 244 245 @inproceedings{Haller07, 246 author = {Haller, Philipp and Odersky, Martin}, 247 editor = {Murphy, Amy L. and Vitek, Jan}, 248 title = {Actors That Unify Threads and Events}, 249 organization= {Coordination Models and Languages}, 250 year = 2007, 251 publisher = {Springer Berlin Heidelberg}, 252 address = {Berlin, Heidelberg}, 253 pages = {171-190}, 207 254 } 208 255 … … 245 292 } 246 293 294 @manual{Ada95, 295 keywords = {Ada}, 296 contributer = {pabuhr@plg}, 297 title = {{A}da Reference Manual}, 298 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}}, 299 organization= {Intermetrics, Inc.}, 300 month = dec, 301 year = 1995, 302 note = {Language and Standards Libraries} 303 } 304 305 @manual{Ada12, 306 keywords = {ISO/IEC Ada}, 307 contributer = {pabuhr@plg}, 308 author = {Ada12}, 309 title = {Programming languages -- {Ada} ISO/IEC 8652:2012}, 310 edition = {3rd}, 311 organization= {International Standard Organization}, 312 address = {Geneva, Switzerland}, 313 year = 2012, 314 note = {\href{https://www.iso.org/standard/61507.html}{https://\-www.iso.org/\-standard/\-61507.html}}, 315 } 316 317 @manual{Ada95:annotated, 318 keywords = {Ada}, 319 contributer = {pabuhr@plg}, 320 title = {Annotated {A}da Reference Manual}, 321 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}}, 322 organization= {Intermetrics, Inc.}, 323 month = dec, 324 year = 1995, 325 note = {Language and Standards Libraries} 326 } 327 247 328 @article{dim:ada, 248 329 keywords = {Dimensional Analysis, Ada}, … … 256 337 number = 2, 257 338 pages = {189-203}, 339 } 340 341 @article{Agrawal08, 342 keywords = {Adaptive scheduling, multiprocessing, processor allocation, randomized algorithm, space sharing, thread scheduling, two-level scheduling, work-stealing}, 343 author = {Agrawal, Kunal and Leiserson, Charles E. and He, Yuxiong and Hsu, Wen Jing}, 344 title = {Adaptive Work-stealing with Parallelism Feedback}, 345 journal = {ACM Trans. Comput. Syst.}, 346 issue_date = {September 2008}, 347 volume = {26}, 348 number = {3}, 349 month = sep, 350 year = {2008}, 351 pages = {7:1-7:32}, 352 publisher = {ACM}, 353 address = {New York, NY, USA}, 258 354 } 259 355 … … 376 472 month = sep, 377 473 year = 2016, 378 note = {\href{http://doc.akka.io/docs/akka/2.4/AkkaScala.pdf}{http://\-doc.akka.io/\-docs/\-akka/\-2.4/\-AkkaScala.pdf}}, 474 note = {\url{http://doc.akka.io/docs/akka/2.4/AkkaScala.pdf}}, 475 } 476 477 @misc{AkkaClassic, 478 contributer = {pabuhr@plg}, 479 key = {AkkaClassic}, 480 title = {Akka Classic Actors}, 481 author = {{Lightbend}}, 482 howpublished= {\url{https://doc.akka.io/docs/akka/current/index-classic.html}}, 483 year = 2023, 484 } 485 486 @misc{AkkaFuture, 487 contributer = {pabuhr@plg}, 488 key = {AkkaFuture}, 489 title = {Akka Futures}, 490 author = {{Lightbend}}, 491 howpublished= {\url{https://doc.akka.io/docs/akka/2.5/futures.html}}, 492 year = 2022, 493 } 494 495 @misc{AkkaTyped, 496 contributer = {pabuhr@plg}, 497 key = {AkkaTyped}, 498 title = {Akka Typed Actors}, 499 author = {{Lightbend}}, 500 howpublished= {\url{https://doc.akka.io/docs/akka/2.5/typed-actors.html}}, 501 year = 2022, 379 502 } 380 503 … … 548 671 } 549 672 673 @inproceedings{Mitzenmacher98, 674 author = {Mitzenmacher, Michael}, 675 title = {Analyses of Load Stealing Models Based on Differential Equations}, 676 organization= {Proceedings of the Tenth Annual ACM Symposium on Parallel Algorithms and Architectures}, 677 series = {SPAA '98}, 678 year = {1998}, 679 isbn = {0-89791-989-0}, 680 location = {Puerto Vallarta, Mexico}, 681 pages = {212-221}, 682 publisher = {ACM}, 683 address = {New York, NY, USA}, 684 } 685 686 @inproceedings{Squillante91, 687 author = {Squillante, Mark S. and Nelson, Randolph D.}, 688 title = {Analysis of Task Migration in Shared-memory Multiprocessor Scheduling}, 689 organization= {Proceedings of the 1991 ACM SIGMETRICS Conference on Measurement and Modeling of Computer Systems}, 690 series = {SIGMETRICS '91}, 691 year = {1991}, 692 isbn = {0-89791-392-2}, 693 location = {San Diego, California, USA}, 694 pages = {143-155}, 695 publisher = {ACM}, 696 address = {New York, NY, USA}, 697 } 698 550 699 @article{Sinha00, 551 700 author = {Saurabh Sinha and Mary Jean Harrold}, … … 562 711 author = {Martin P. Robillard and Gail C. Murphy}, 563 712 title = {Analyzing Exception Flow in {J}ava Programs}, 564 booktitle= {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly713 organization= {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly 565 714 with the 7th ACM SIGSOFT International Symposium on Foundations of Software Engineering}, 566 715 year = 1999, … … 604 753 author = {Henry Qin and Qian Li and Jacqueline Speiser and Peter Kraft and John Ousterhout}, 605 754 title = {Arachne: Core-Aware Thread Management}, 606 booktitle= {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)},755 organization= {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)}, 607 756 year = {2018}, 608 757 address = {Carlsbad, CA}, … … 661 810 author = {Jaewoong Chung and Luke Yen and Stephan Diestelhorst and Martin Pohlack and Michael Hohmuth and David Christie and Dan Grossman}, 662 811 title = {ASF: AMD64 Extension for Lock-Free Data Structures and Transactional Memory}, 663 booktitle= {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture},812 organization= {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture}, 664 813 series = {MICRO '43}, 665 814 year = 2010, … … 682 831 } 683 832 833 @misc{AsyncAwait, 834 contributer = {pabuhr@plg}, 835 key = {AsyncAwait}, 836 title = {Async Await}, 837 author = {{WikipediA}}, 838 howpublished= {\href{https://en.wikipedia.org/wiki/Async/await}{https://\-en.wikipedia.org/\-wiki/\-Async/\-await}}, 839 year = 2022, 840 } 841 684 842 @inproceedings{Krischer08, 685 843 keywords = {exception handling, asynchronous, blocked tasks}, … … 687 845 author = {Roy Krischer and Peter A. Buhr}, 688 846 title = {Asynchronous Exception Propagation in Blocked Tasks}, 689 booktitle= {4th International Workshop on Exception Handling (WEH.08)},847 organization= {4th International Workshop on Exception Handling (WEH.08)}, 690 848 optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)}, 691 849 address = {Atlanta, U.S.A}, … … 696 854 697 855 @article{Joung00, 856 keywords = {group mutual exclusion, congenial talking philosophers, resource allocation, shared-memory algorithms}, 698 857 author = {Joung, Yuh-Jzer}, 699 858 title = {Asynchronous group mutual exclusion}, … … 759 918 publisher = {ACM}, 760 919 address = {New York, NY, USA}, 920 } 921 922 @techreport{Neill09, 923 author = {Daniel Neill and Adam Wierman}, 924 title = {On the Benefits of Work Stealing in Shared-Memory Multiprocessors}, 925 institution = {Carnegie Mellon University}, 926 address = {California Institute of Technology, Pasadena, CA, USA}, 927 note = {\href{http://www.cs.cmu.edu/~acw/15740/paper.pdf}{http://\-www.cs.cmu.edu/\-$\sim$acw/\-15740/\-paper.pdf}, Accessed May 2014}, 928 year = 2009, 761 929 } 762 930 … … 916 1084 } 917 1085 1086 @inproceedings{Ding12, 1087 keywords = {fairness, multicore, time sharing, work stealing}, 1088 author = {Ding, Xiaoning and Wang, Kaibo and Gibbons, Phillip B. and Zhang, Xiaodong}, 1089 title = {BWS: Balanced Work Stealing for Time-sharing Multicores}, 1090 organization= {Proceedings of the 7th ACM European Conference on Computer Systems}, 1091 series = {EuroSys '12}, 1092 year = {2012}, 1093 location = {Bern, Switzerland}, 1094 pages = {365-378}, 1095 publisher = {ACM}, 1096 address = {New York, NY, USA}, 1097 } 1098 918 1099 % C 919 1100 … … 990 1171 } 991 1172 1173 @inproceedings{CAF, 1174 keywords = {performance measurement, actor model, c++, message-oriented middleware, distributed debugging}, 1175 contributer = {pabuhr@plg}, 1176 author = {Charousset, Dominik and Hiesgen, Raphael and Schmidt, Thomas C.}, 1177 title = {{CAF} -- the {C}++ Actor Framework for Scalable and Resource-Efficient Applications}, 1178 publisher = {ACM}, 1179 address = {New York, NY, USA}, 1180 organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control}, 1181 pages = {15-28}, 1182 numpages = 14, 1183 location = {Portland, Oregon, USA}, 1184 series = {AGERE'14}, 1185 year = 2014, 1186 } 1187 992 1188 @techreport{cfa-cc, 993 1189 keywords = {Cforall, cfa-cc, transpiler}, … … 1013 1209 year = 2018, 1014 1210 pages = {2111-2146}, 1015 note = {\href{http://dx.doi.org/10.1002/spe.2624}{http://\-dx.doi.org/\-10.1002/\-spe.2624}},1211 optnote = {\href{http://dx.doi.org/10.1002/spe.2624}{http://\-dx.doi.org/\-10.1002/\-spe.2624}}, 1016 1212 } 1017 1213 … … 1172 1368 @techreport{Prokopec11, 1173 1369 keywords = {ctrie, concurrent map}, 1174 contributer = {a3moss@uwaterloo.ca},1370 contributer = {a3moss@uwaterloo.ca}, 1175 1371 title = {Cache-aware lock-free concurrent hash tries}, 1176 1372 author = {Prokopec, Aleksandar and Bagwell, Phil and Odersky, Martin}, … … 1496 1692 author = {Emery D. Berger and Benjamin G. Zorn and Kathryn S. McKinley}, 1497 1693 title = {Composing High-Performance Memory Allocators}, 1498 booktitle= {{SIGPLAN} Conference on Programming Language Design and Implementation},1694 organization= {{SIGPLAN} Conference on Programming Language Design and Implementation}, 1499 1695 pages = {114-124}, 1500 1696 year = 2001, … … 1674 1870 month = sep, 1675 1871 year = 2020, 1676 note = {\ href{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uC++.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-pub/\-uSystem/uC++.pdf}},1872 note = {\url{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uC++.pdf}}, 1677 1873 } 1678 1874 … … 1808 2004 number = 5, 1809 2005 pages = {1005-1042}, 1810 note = {\href{https://onlinelibrary.wiley.com/doi/10.1002/spe.2925}{https://\-onlinelibrary.wiley.com/\-doi/\-10.1002/\-spe.2925}},2006 optnote = {\href{https://onlinelibrary.wiley.com/doi/10.1002/spe.2925}{https://\-onlinelibrary.wiley.com/\-doi/\-10.1002/\-spe.2925}}, 1811 2007 } 1812 2008 … … 1996 2192 address = {Eindhoven, Neth.}, 1997 2193 year = 1965, 1998 note = {Reprinted in \cite{Genuys68} pp. 43--112.} 2194 optnote = {Reprinted in \cite{Genuys68} pp. 43--112.}, 2195 note = {\url{https://pure.tue.nl/ws/files/4279816/344354178746665.pdf}}, 1999 2196 } 2000 2197 … … 2003 2200 author = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.}, 2004 2201 title = {Cooperative Task Management Without Manual Stack Management}, 2005 booktitle= {Proc. of the General Track USENIX Tech. Conf.},2202 organization= {Proc. of the General Track USENIX Tech. Conf.}, 2006 2203 series = {ATEC '02}, 2007 2204 year = {2002}, … … 2111 2308 year = 2016, 2112 2309 note = {\href{http://dlang.org/spec/spec.html}{http://\-dlang.org/\-spec/\-spec.html}}, 2310 } 2311 2312 @article{Acar02, 2313 author = {Acar, Umut A. and Blelloch, Guy E. and Blumofe, Robert D.}, 2314 title = {The Data Locality of Work Stealing}, 2315 journal = {Theory of Computing Systems}, 2316 volume = {35}, 2317 number = {3}, 2318 year = {2002}, 2319 publisher = {Springer-Verlag}, 2320 pages = {321-347}, 2113 2321 } 2114 2322 … … 2370 2578 editor = {R. E. A. Mason}, 2371 2579 organization= {IFIP}, 2372 publisher = {North-Holland},2373 summary = {2580 publisher = {North-Holland}, 2581 summary = { 2374 2582 Packages group related declarations or subprograms, and encapsulate 2375 2583 data types. Separate interfaces and bodies promotes information … … 2598 2806 address = {Waterview Corporate Center, 20 Waterview Boulevard, Parsippany, NJ 07054}, 2599 2807 year = {1993} 2808 } 2809 2810 @inproceedings{Chen14, 2811 keywords = {Core allocation, Multi-programmed, Work-stealing}, 2812 author = {Chen, Quan and Zheng, Long and Guo, Minyi}, 2813 title = {DWS: Demand-aware Work-Stealing in Multi-programmed Multi-core Architectures}, 2814 organization= {Proceedings of Programming Models and Applications on Multicores and Manycores}, 2815 series = {PMAM'14}, 2816 year = {2007}, 2817 location = {Orlando, FL, USA}, 2818 pages = {131:131-131:139}, 2819 articleno = {131}, 2820 numpages = {9}, 2821 publisher = {ACM}, 2822 address = {New York, NY, USA}, 2600 2823 } 2601 2824 … … 2631 2854 year = 2003, 2632 2855 pages = {29-35}, 2856 } 2857 2858 @inproceedings{Hamidzadeh96, 2859 keywords = {processor scheduling, resource allocation, shared memory systems, average memory referencing delay}, 2860 author = {Hamidzadeh, B. and Lilja, D.J.}, 2861 booktitle = {Distributed Computing Systems, 1996., Proceedings of the 16th International Conference on}, 2862 title = {Dynamic scheduling strategies for shared-memory multiprocessors}, 2863 year = {1996}, 2864 month = {May}, 2865 pages = {208-215}, 2866 } 2867 2868 @article{Hendler06, 2869 keywords = {Concurrent programming; Load balancing; Work stealing; Lock-free; Data structures}, 2870 author = {Hendler, Danny and Lev, Yossi and Moir, Mark and Shavit, Nir}, 2871 title = {A dynamic-sized nonblocking work stealing deque}, 2872 journal = {Distributed Computing}, 2873 volume = {18}, 2874 number = {3}, 2875 year = {2006}, 2876 publisher = {Springer-Verlag}, 2877 pages = {189-207}, 2633 2878 } 2634 2879 … … 2734 2979 } 2735 2980 2981 @inproceedings{Blelloch04, 2982 keywords = {chip multiprocessors, multithreaded architectures, scheduling algorithms, shared cache}, 2983 author = {Blelloch, Guy E. and Gibbons, Phillip B.}, 2984 title = {Effectively Sharing a Cache Among Threads}, 2985 organization= {Proceedings of the Sixteenth Annual ACM Symposium on Parallelism in Algorithms and Architectures}, 2986 series = {SPAA '04}, 2987 year = {2004}, 2988 location = {Barcelona, Spain}, 2989 pages = {235-244}, 2990 publisher = {ACM}, 2991 address = {New York, NY, USA}, 2992 } 2993 2736 2994 @techreport{Habermann80, 2737 2995 keywords = {Ada, threads}, … … 2808 3066 title = {Encapsulation and Inheritance in Object-Oriented Programming Languages}, 2809 3067 journal = sigplan, 2810 volume = {21}, number = {11}, 3068 volume = {21}, 3069 number = {11}, 2811 3070 pages = {38-45}, 2812 month = nov, year = 1986, 3071 month = nov, 3072 year = 1986, 2813 3073 comment = { 2814 3074 Client, child interfaces should be distinct. Child interface … … 2866 3126 } 2867 3127 3128 @inproceedings{Ribic14, 3129 keywords = {dvfs, energy efficiency, language runtimes, thread management, work stealing}, 3130 author = {Ribic, Haris and Liu, Yu David}, 3131 title = {Energy-efficient Work-stealing Language Runtimes}, 3132 organization= {Proceedings of the 19th International Conference on Architectural Support for Programming Languages and Operating Systems}, 3133 series = {ASPLOS '14}, 3134 year = {2014}, 3135 location = {Salt Lake City, Utah, USA}, 3136 pages = {513-528}, 3137 publisher = {ACM}, 3138 address = {New York, NY, USA}, 3139 } 3140 2868 3141 @manual{EPT, 2869 3142 keywords = {concurrency, light-weight threads}, … … 2887 3160 } 2888 3161 3162 @misc{Soleimani16, 3163 keywords = {Erlang, scheduler, history}, 3164 contributer = {pabuhr@plg}, 3165 author = {Hamidreza Soleimani}, 3166 title = {Erlang Scheduler Details and Why It Matters}, 3167 month = feb, 3168 year = 2016, 3169 howpublished= {\url{https://hamidreza-s.github.io/erlang/scheduling/real-time/preemptive/migration/2016/02/09/erlang-scheduler-details.html}}, 3170 } 3171 2889 3172 @inproceedings{MH88, 2890 3173 keywords = {modules, general sums, general products}, … … 2903 3186 publisher = {North Oxford Academic}, 2904 3187 year = 1985 3188 } 3189 3190 @article{Torrellas95, 3191 author = {J. Torrellas and A. Tucker and A. Gupta}, 3192 title = {Evaluating the Performance of Cache-Affinity Scheduling in Shared-Memory Multiprocessors}, 3193 journal = {Journal of Parallel and Distributed Computing}, 3194 volume = {24}, 3195 number = {2}, 3196 pages = {139-151}, 3197 year = {1995}, 2905 3198 } 2906 3199 … … 3614 3907 author = {Robert Griesemer and Rob Pike and Ken Thompson}, 3615 3908 title = {{Go} Programming Language}, 3909 address = {Mountain View, CA, USA}, 3616 3910 organization= {Google}, 3617 3911 year = 2009, … … 3725 4019 @article{Michael04a, 3726 4020 keywords = {Lock-free, synchronization, concurrent programming, memory management, multiprogramming, dynamic data structures}, 4021 contributer = {pabuhr@plg}, 3727 4022 author = {Maged M. Michael}, 3728 4023 title = {Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects}, … … 3735 4030 publisher = {IEEE Press}, 3736 4031 address = {Piscataway, NJ, USA}, 4032 } 4033 4034 @inproceedings{Johansson02, 4035 keywords = {concurrent languages, erlang, garbage collection, message passing, runtime systems}, 4036 contributer = {pabuhr@plg}, 4037 author = {Erik Johansson and Konstantinos Sagonas and Jesper Wilhelmsson}, 4038 title = {Heap Architectures for Concurrent Languages Using Message Passing}, 4039 year = {2002}, 4040 isbn = {1581135394}, 4041 publisher = {ACM}, 4042 address = {New York, NY, USA}, 4043 organization= {Proceedings of the 3rd International Symposium on Memory Management}, 4044 pages = {88-99}, 4045 location = {Berlin, Germany}, 3737 4046 } 3738 4047 … … 3914 4223 title = {Implementing Lock-Free Queues}, 3915 4224 booktitle = {Seventh International Conference on Parallel and Distributed Computing Systems}, 4225 organization= {International Society for Computers and Their Applications}, 3916 4226 address = {Las Vegas, Nevada, U.S.A.}, 3917 4227 year = {1994}, 3918 4228 pages = {64-69}, 4229 } 4230 4231 @inproceedings{Halstead84, 4232 author = {Halstead,Jr., Robert H.}, 4233 title = {Implementation of Multilisp: Lisp on a Multiprocessor}, 4234 organization= {Proceedings of the 1984 ACM Symposium on LISP and Functional Programming}, 4235 series = {LFP '84}, 4236 year = {1984}, 4237 location = {Austin, Texas, USA}, 4238 pages = {9-17}, 4239 publisher = {ACM}, 4240 address = {New York, NY, USA}, 3919 4241 } 3920 4242 … … 4695 5017 contributer = {pabuhr@plg}, 4696 5018 author = {Lua}, 4697 title = {Lua 5.3 Reference Manual}, 4698 address = {\href{https://www.lua.org/manual/5.3}{https://\-www.lua.org/\-manual/\-5.3}}, 4699 year = 2018, 5019 title = {Lua 5.4 Reference Manual}, 5020 organization= {Pontifical Catholic University}, 5021 address = {\href{https://www.lua.org/manual/5.4}{https://\-www.lua.org/\-manual/\-5.4}}, 5022 year = 2020, 4700 5023 } 4701 5024 … … 4764 5087 } 4765 5088 4766 @m anual{MMTk,5089 @misc{MMTk, 4767 5090 keywords = {Java memory management}, 4768 5091 contributer = {pabuhr@plg}, … … 4771 5094 month = sep, 4772 5095 year = 2006, 4773 note = {\href{http://cs.anu.edu.au/~Robin.Garner/mmtk-guide.pdf} 4774 {http://cs.anu.edu.au/\-$\sim$Robin.Garner/\-mmtk-guide.pdf}}, 5096 howpublished= {\url{http://cs.anu.edu.au/~Robin.Garner/mmtk-guide.pdf}}, 4775 5097 } 4776 5098 … … 5078 5400 year = 2015, 5079 5401 note = {\href{http://www.mpi-forum.org/docs/mpi-3.1/mpi31-report.pdf}{http://www.mpi-forum.org/\-docs/\-mpi-3.1/\-mpi31-report.pdf}}, 5402 } 5403 5404 @article{Lombardo19, 5405 contributer = {pabuhr@plg}, 5406 author = {Lombardo, Gianfranco and Fornacciari, Paolo and Mordonini, Monica and Tomaiuolo, Michele and Poggi, Agostino}, 5407 title = {A Multi-Agent Architecture for Data Analysis}, 5408 journal = {Future Internet}, 5409 volume = 11, 5410 year = 2019, 5411 number = 2, 5080 5412 } 5081 5413 … … 5277 5609 Programming Language}, 5278 5610 year = 1980, 5279 month = dec, pages = {139-145}, 5611 month = dec, 5612 pages = {139-145}, 5280 5613 note = {SIGPLAN Notices, v. 15, n. 11}, 5281 5614 abstract = { … … 5398 5731 year = 2005, 5399 5732 pages = {146-196}, 5733 publisher = {ACM}, 5734 address = {New York, NY, USA}, 5735 } 5736 5737 @inproceedings{Hendler02, 5738 author = {Hendler, Danny and Shavit, Nir}, 5739 title = {Non-blocking Steal-half Work Queues}, 5740 organization= {Proceedings of the Twenty-first Annual Symposium on Principles of Distributed Computing}, 5741 series = {PODC '02}, 5742 year = {2002}, 5743 location = {Monterey, California}, 5744 pages = {280-289}, 5400 5745 publisher = {ACM}, 5401 5746 address = {New York, NY, USA}, … … 5646 5991 } 5647 5992 5993 @misc{OpenTelemetry, 5994 contributer = {pabuhr@plg}, 5995 key = {OpenTelemetry}, 5996 title = {OpenTelemetry}, 5997 author = {{Asynkron AB}}, 5998 howpublished= {\href{https://proto.actor/docs/tracing}{https://\-proto.actor/\-docs/\-tracing}}, 5999 year = 2022, 6000 } 6001 5648 6002 @inproceedings{Krebbers14, 5649 6003 keywords = {c formalization}, … … 5883 6237 } 5884 6238 6239 @article{Nigro21, 6240 keywords = {Actors, Asynchronous messages, Reflective control on message passing, Lock-free parallel computing, Java, Scalable multi-agent systems, Parallel matrix multiplication, Iterated Prisoner's Dilemma}, 6241 contributer = {pabuhr@plg}, 6242 author = {Libero Nigro}, 6243 title = {Parallel Theatre: An actor framework in {Java} for high performance computing}, 6244 journal = {Simulation Modelling Practice and Theory}, 6245 volume = {106}, 6246 number = {102189}, 6247 year = {2021}, 6248 } 6249 5885 6250 @incollection{Stroustrup96, 5886 6251 keywords = {concurrency, C++}, … … 5917 6282 journal = ieeese, 5918 6283 year = 1984, 5919 month = sep, volume = "SE-10", number = 5, pages = {528-543}, 6284 month = sep, 6285 volume = "SE-10", 6286 number = 5, 6287 pages = {528-543}, 5920 6288 abstract = { 5921 6289 Parameterized programming is a powerful technique for the reliable … … 5949 6317 booktitle = {USENIX {C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Conference}, 5950 6318 organization= {USENIX Association}, 5951 year = 1988, pages = {1-18} 6319 year = 1988, 6320 pages = {1-18}, 5952 6321 } 5953 6322 … … 6037 6406 } 6038 6407 6408 @incollection{Kazempour08, 6409 keywords = {multicore processors; cache affinity; performance evaluation; scheduling}, 6410 author = {Kazempour, Vahid and Fedorova, Alexandra and Alagheband, Pouya}, 6411 title = {Performance Implications of Cache Affinity on Multicore Processors}, 6412 organization= {Euro-Par 2008 -- Parallel Processing}, 6413 series = {Lecture Notes in Computer Science}, 6414 editor = {Luque, Emilio and Margalef, Tomas and Benitez, Domingo}, 6415 year = {2008}, 6416 volume = {5168}, 6417 pages = {151-161}, 6418 publisher = {Springer Berlin Heidelberg}, 6419 } 6420 6421 @article{Anderson89, 6422 keywords = {data structures, multiprocessing systems, operating systems (computers), performance evaluation, critical resource waiting}, 6423 author = {Anderson, T.E. and Lazowska, E.D. and Levy, H.M.}, 6424 journal = {Computers, IEEE Transactions on}, 6425 title = {The Performance Implications of Thread Management Alternatives for Shared-Memory Multiprocessors}, 6426 year = {1989}, 6427 month = {Dec}, 6428 volume = {38}, 6429 number = {12}, 6430 pages = {1631-1644}, 6431 } 6432 6039 6433 @article{Anderson90, 6040 6434 keywords = {spin locks, back off, performance}, … … 6048 6442 number = 1, 6049 6443 pages = {6-16}, 6444 } 6445 6446 @article{Blumofe98, 6447 author = {Blumofe, Robert D. and Papadopoulos, Dionisios}, 6448 title = {The Performance of Work Stealing in Multiprogrammed Environments (Extended Abstract)}, 6449 journal = {SIGMETRICS Perform. Eval. Rev.}, 6450 volume = {26}, 6451 number = {1}, 6452 month = jun, 6453 year = {1998}, 6454 issn = {0163-5999}, 6455 pages = {266-267}, 6456 publisher = {ACM}, 6457 address = {New York, NY, USA}, 6050 6458 } 6051 6459 … … 6286 6694 } 6287 6695 6696 @article{Varela01, 6697 keywords = {programming languages, SALSA, continuations, actors, java, internet, network computing, open systems, mobile computing}, 6698 contributer = {pabuhr@plg}, 6699 author = {Varela, Carlos and Agha, Gul}, 6700 title = {Programming Dynamically Reconfigurable Open Systems with SALSA}, 6701 issue_date = {December 2001}, 6702 publisher = {Association for Computing Machinery}, 6703 address = {New York, NY, USA}, 6704 volume = 36, 6705 number = 12, 6706 journal = {SIGPLAN Not.}, 6707 year = 2001, 6708 month = dec, 6709 pages = {20-34}, 6710 } 6711 6288 6712 @book{PowerPC, 6289 6713 key = {PowerPC processor}, … … 6347 6771 title = {Programming Languages -- {C}}, 6348 6772 organization= {International Standard ISO/IEC 9899:1999 (E)}, 6349 publisher = {American National Standards Institute},6773 publisher = {American National Standards Institute}, 6350 6774 address = {www.ansi.org}, 6351 6775 year = 1999, … … 6358 6782 title = {{C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Programming Language ISO/IEC 14882:1998}, 6359 6783 edition = {1st}, 6360 organization = {International Standard Organization},6784 organization= {International Standard Organization}, 6361 6785 address = {Geneva, Switzerland}, 6362 6786 year = 1998, … … 6649 7073 } 6650 7074 7075 @misc{protoactor, 7076 contributer = {pabuhr@plg}, 7077 key = {Protoactor}, 7078 author = {{proto.actor}}, 7079 title = {Asynkron AB}, 7080 year = 2023, 7081 howpublished= {\url{https://proto.actor}}, 7082 } 7083 6651 7084 @misc{Pthreads, 6652 7085 keywords = {pthreads, C concurrency}, … … 6760 7193 } 6761 7194 6762 @manual{Ada95, 6763 keywords = {Ada}, 6764 contributer = {pabuhr@plg}, 6765 title = {{A}da Reference Manual}, 6766 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}}, 6767 organization= {Intermetrics, Inc.}, 6768 month = dec, 6769 year = 1995, 6770 note = {Language and Standards Libraries} 6771 } 6772 6773 @manual{Ada12, 6774 keywords = {ISO/IEC Ada}, 6775 contributer = {pabuhr@plg}, 6776 author = {Ada12}, 6777 title = {Programming languages -- {Ada} ISO/IEC 8652:2012}, 6778 edition = {3rd}, 6779 organization= {International Standard Organization}, 6780 address = {Geneva, Switzerland}, 6781 year = 2012, 6782 note = {\href{https://www.iso.org/standard/61507.html}{https://\-www.iso.org/\-standard/\-61507.html}}, 6783 } 6784 6785 @manual{Ada95:annotated, 6786 keywords = {Ada}, 6787 contributer = {pabuhr@plg}, 6788 title = {Annotated {A}da Reference Manual}, 6789 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}}, 6790 organization = {Intermetrics, Inc.}, 6791 month = dec, 6792 year = 1995, 6793 note = {Language and Standards Libraries} 7195 @inproceedings{Bacon03, 7196 keywords = {utilization, real-time scheduling, read barrier, defragmentation}, 7197 contributer = {pabuhr@plg}, 7198 author = {David F. Bacon and Perry Cheng and V. T. Rajan}, 7199 title = {A Real-Time Garbage Collector with Low Overhead and Consistent Utilization}, 7200 year = {2003}, 7201 organization= {Proceedings of the 30th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, 7202 publisher = {ACM}, 7203 address = {New York, NY, USA}, 7204 pages = {285-298}, 7205 location = {New Orleans, Louisiana, USA}, 6794 7206 } 6795 7207 … … 6927 7339 journal = sigplan, 6928 7340 year = 1991, 6929 month = oct, volume = 26, number = 10, pages = {29-43}, 7341 month = oct, 7342 volume = 26, 7343 number = 10, 7344 pages = {29-43}, 6930 7345 abstract = { 6931 7346 {\tt lcc} is a new retargetable compiler for ANSI C. Versions for … … 6987 7402 } 6988 7403 7404 @misc{rpmalloc, 7405 author = {Mattias Jansson}, 7406 title = {rpmalloc version 1.4.1}, 7407 month = apr, 7408 year = 2022, 7409 howpublished= {\href{https://github.com/mjansson/rpmalloc}{https://\-github.com/\-mjansson/\-rpmalloc}}, 7410 } 7411 6989 7412 @manual{Rust, 6990 7413 keywords = {Rust programming language}, … … 7017 7440 publisher = {ACM}, 7018 7441 address = {New York, NY, USA}, 7019 booktitle= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},7442 organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control}, 7020 7443 pages = {67-80}, 7021 7444 numpages = {14}, … … 7041 7464 booktitle = {PLDI '04: Proceedings of the ACM SIGPLAN 2004 Conference on Programming Language Design and Implementation}, 7042 7465 location = {Washington DC, USA}, 7043 publisher= {ACM},7466 organization= {ACM}, 7044 7467 address = {New York, NY, USA}, 7045 7468 volume = 39, … … 7047 7470 month = jun, 7048 7471 pages = {35-46}, 7472 } 7473 7474 @article{Nickolls08, 7475 author = {Nickolls, John and Buck, Ian and Garland, Michael and Skadron, Kevin}, 7476 title = {Scalable Parallel Programming with CUDA}, 7477 journal = {Queue}, 7478 volume = {6}, 7479 number = {2}, 7480 month = mar, 7481 year = 2008, 7482 pages = {40-53}, 7483 publisher = {ACM}, 7484 address = {New York, NY, USA}, 7049 7485 } 7050 7486 … … 7062 7498 } 7063 7499 7500 @article{Blumofe99, 7501 keywords = {critical-path length, multiprocessor, multithreading, randomized algorithm, thread scheduling, work stealing}, 7502 author = {Blumofe, Robert D. and Leiserson, Charles E.}, 7503 title = {Scheduling Multithreaded Computations by Work Stealing}, 7504 journal = {Journal of the ACM}, 7505 volume = {46}, 7506 number = {5}, 7507 month = sep, 7508 year = {1999}, 7509 pages = {720-748}, 7510 publisher = {ACM}, 7511 address = {New York, NY, USA}, 7512 } 7513 7514 @inproceedings{Acar13, 7515 keywords = {dynamic load balancing, nested parallelism, work stealing}, 7516 author = {Acar, Umut A. and Chargueraud, Arthur and Rainey, Mike}, 7517 title = {Scheduling Parallel Programs by Work Stealing with Private Deques}, 7518 organization= {Proceedings of the 18th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming}, 7519 series = {PPoPP '13}, 7520 year = {2013}, 7521 location = {Shenzhen, China}, 7522 pages = {219-228}, 7523 publisher = {ACM}, 7524 address = {New York, NY, USA}, 7525 } 7526 7527 @inproceedings{Chen07, 7528 keywords = {chip multiprocessors, constructive cache sharing, parallel depth first, scheduling algorithms, thread granularity, work stealing, working set profiling}, 7529 author = {Chen, Shimin and Gibbons, Phillip B. and Kozuch, Michael and Liaskovitis, Vasileios and Ailamaki, Anastassia and Blelloch, Guy E. and Falsafi, Babak and Fix, Limor and Hardavellas, Nikos and Mowry, Todd C. and Wilkerson, Chris}, 7530 title = {Scheduling Threads for Constructive Cache Sharing on CMPs}, 7531 organization= {Proceedings of the Nineteenth Annual ACM Symposium on Parallel Algorithms and Architectures}, 7532 series = {SPAA '07}, 7533 year = {2007}, 7534 location = {San Diego, California, USA}, 7535 pages = {105-115}, 7536 numpages = {11}, 7537 publisher = {ACM}, 7538 address = {New York, NY, USA}, 7539 } 7540 7064 7541 @manual{SELF, 7065 7542 keywords = {programming language, obect-oriented, polymorphism}, … … 7083 7560 publisher = {Springer}, 7084 7561 note = {Lecture Notes in Computer Science v. 173}, 7562 } 7563 7564 @inproceedings{Kahn74, 7565 keywords = {programming language, obect-oriented, polymorphism}, 7566 contributer = {pabuhr@plg}, 7567 title = {The Semantics of a Simple Language for Parallel Programming}, 7568 author = {Gilles Kahn}, 7569 organization= {IFIP Congress}, 7570 year = 1974, 7085 7571 } 7086 7572 … … 7143 7629 number = 12, 7144 7630 pages = {66-76}, 7631 } 7632 7633 @book{Scott13, 7634 author = {Michael L. Scott}, 7635 title = {Shared-Memory Synchronization}, 7636 publisher = {Morgan \& Claypool}, 7637 year = 2013, 7638 } 7639 7640 @inproceedings{Leissa14, 7641 title = {{S}ierra: a {SIMD} extension for {C}++}, 7642 author = {Lei{\ss}a, Roland and Haffner, Immanuel and Hack, Sebastian}, 7643 booktitle = {Proceedings of the 2014 Workshop on Workshop on programming models for SIMD/Vector processing}, 7644 pages = {17-24}, 7645 year = {2014}, 7646 organization= {ACM} 7145 7647 } 7146 7648 … … 7780 8282 7781 8283 @article{SysVABI, 7782 keywords = {System V ABI},7783 contributer = {a3moss@uwaterloo.ca},8284 keywords = {System V ABI}, 8285 contributer = {a3moss@uwaterloo.ca}, 7784 8286 title = {System {V} application binary interface}, 7785 8287 author = {Matz, Michael and Hubicka, Jan and Jaeger, Andreas and Mitchell, Mark}, … … 7787 8289 volume = {99}, 7788 8290 year = {2013} 8291 } 8292 8293 @article{Albert18, 8294 keywords = {actor-based concurrency, partial order reduction, systematic testing, synchronization, task independence}, 8295 contributer = {pabuhr@plg}, 8296 author = {Albert, Elvira and Arenas, Puri and G\'{o}mez-Zamalloa, Miguel}, 8297 title = {Systematic testing of actor systems}, 8298 journal = {Software Testing, Verification and Reliability}, 8299 volume = {28}, 8300 number = {3}, 8301 pages = {e1661}, 8302 year = {2018} 7789 8303 } 7790 8304 … … 7813 8327 journal = jcss, 7814 8328 year = 1978, 7815 volume = 17, pages = {348-375} 8329 volume = 17, 8330 pages = {348-375}, 7816 8331 } 7817 8332 … … 7824 8339 address = {New York, New York, U.S.A.}, 7825 8340 year = 1982 8341 } 8342 8343 @article{Arora01, 8344 author = {Arora, N. S. and Blumofe, R. D. and Plaxton, C. G.}, 8345 title = {Thread Scheduling for Multiprogrammed Multiprocessors}, 8346 journal = {Theory of Computing Systems}, 8347 year = {2001}, 8348 volume = {34}, 8349 number = {2}, 8350 pages = {115-144}, 8351 publisher = {Springer-Verlag}, 7826 8352 } 7827 8353 … … 8053 8579 } 8054 8580 8581 @misc{AkkaBecome, 8582 contributer = {pabuhr@plg}, 8583 key = {AkkaBecome}, 8584 title = {Typed Actors}, 8585 author = {{Lightbend}}, 8586 howpublished= {\href{https://doc.akka.io/docs/akka/2.5/typed-actors.html}{https://\-doc.akka.io/\-docs/\-akka/\-2.5/\-typed-actors.html}}, 8587 year = 2022, 8588 } 8589 8055 8590 @article{concatenation, 8056 8591 keywords = {record concatenation, isa}, … … 8117 8652 author = {Paul R. Wilson}, 8118 8653 title = {Uniprocessor Garbage Collection Techniques}, 8119 booktitle= {Proceedings of the International Workshop on Memory Management},8654 organization= {Proceedings of the International Workshop on Memory Management}, 8120 8655 location = {St. Malo, France}, 8121 8656 publisher = {Springer}, … … 8130 8665 author = {Carl Hewitt and Peter Bishop and Richard Steiger}, 8131 8666 title = {A Universal Modular {ACTOR} Formalism for Artificial Intelligence}, 8132 booktitle= {Proceedings of the 3rd International Joint Conference on Artificial Intelligence},8667 organization= {Proceedings of the 3rd International Joint Conference on Artificial Intelligence}, 8133 8668 address = {Standford, California, U.S.A.}, 8134 8669 pages = {235-245}, 8670 location = {Stanford, USA}, 8671 series = {IJCAI'73}, 8135 8672 month = aug, 8136 8673 year = 1973, … … 8164 8701 @article{Karsten20, 8165 8702 author = {Karsten, Martin and Barghi, Saman}, 8166 title = { {User-level Threading: Have Your Cake and Eat It Too}},8703 title = {User-level Threading: Have Your Cake and Eat It Too}, 8167 8704 year = {2020}, 8168 8705 issue_date = {March 2020}, … … 8189 8726 } 8190 8727 8728 @article{Squillante93, 8729 keywords = {buffer storage, performance evaluation, queueing theory, scheduling, shared memory systems, processor-cache affinity}, 8730 author = {Squillante, M.S. and Lazowska, E.D.}, 8731 title = {Using Processor-Cache Affinity Information in Shared-Memory Multiprocessor Scheduling}, 8732 journal = {Parallel and Distributed Systems, IEEE Transactions on}, 8733 year = {1993}, 8734 month = {Feb}, 8735 volume = {4}, 8736 number = {2}, 8737 pages = {131-143}, 8738 } 8739 8191 8740 @article{delegation, 8192 8741 keywords = {delegation, inheritance, actors}, … … 8338 8887 year = 2003, 8339 8888 pages = {19-24}, 8889 } 8890 8891 @inproceedings{Saman18, 8892 keywords = {actors, scheduling, NUMA, locality}, 8893 contributer = {pabuhr@plg}, 8894 author = {Saman Barghi and Martin Karsten}, 8895 organization= {2018 IEEE International Parallel and Distributed Processing Symposium (IPDPS)}, 8896 title = {Work-Stealing, Locality-Aware Actor Scheduling}, 8897 year = {2018}, 8898 address = {Vancouver, BC, Canada}, 8899 pages = {484-494}, 8900 } 8901 8902 @article{Wimmer13, 8903 keywords = {priorities, scheduler hints, strategies, work-stealing}, 8904 author = {Wimmer, Martin and Cederman, Daniel and Tr\"{a}ff, Jesper Larsson and Tsigas, Philippas}, 8905 title = {Work-stealing with Configurable Scheduling Strategies}, 8906 journal = {SIGPLAN Not.}, 8907 issue_date = {August 2013}, 8908 volume = {48}, 8909 number = {8}, 8910 month = feb, 8911 year = {2013}, 8912 issn = {0362-1340}, 8913 pages = {315-316}, 8914 publisher = {ACM}, 8915 address = {New York, NY, USA}, 8340 8916 } 8341 8917 -
doc/theses/mike_brooks_MMath/Makefile
r34b4268 r24d6572 8 8 PicSRC = ${notdir ${wildcard ${Pictures}/*.png}} 9 9 DemoSRC = ${notdir ${wildcard ${Programs}/*-demo.cfa}} 10 PgmSRC = ${notdir ${wildcard ${Programs}/*.cfa}} 10 PgmSRC = ${notdir ${wildcard ${Programs}/*}} 11 RunPgmSRC = ${notdir ${wildcard ${Programs}/*.run.*}} 11 12 BibSRC = ${wildcard *.bib} 12 13 … … 14 15 BibLIB = .:../../bibliography # common citation repository 15 16 16 MAKEFLAGS = --no-print-directory # --silent17 #MAKEFLAGS = --no-print-directory # --silent 17 18 VPATH = ${Build} ${Pictures} ${Programs} # extra search path for file names used in document 18 19 … … 20 21 BASE = ${basename ${DOCUMENT}} # remove suffix 21 22 23 DemoTex = ${DemoSRC:%.cfa=${Build}/%.tex} 24 RunPgmExe = ${addprefix ${Build}/,${basename ${basename ${RunPgmSRC}}}} 25 RunPgmOut = ${RunPgmExe:%=%.out} 26 22 27 # Commands 23 28 24 29 LaTeX = TEXINPUTS=${TeXLIB} && export TEXINPUTS && pdflatex -halt-on-error -output-directory=${Build} 25 30 BibTeX = BIBINPUTS=${BibLIB} && export BIBINPUTS && bibtex 26 CFA = cfa 31 CFA = cfa -O0 -g 32 CC = gcc -O0 -g 33 CXX = g++-11 --std=c++20 -O0 -g 27 34 28 35 # Rules and Recipes 29 36 30 .PHONY : all clean # not file names 37 .PHONY : all fragments_ran clean # not file names 38 .PRECIOUS : ${Build}/% ${Build}/%-demo # don't delete intermediates 31 39 .ONESHELL : 32 40 33 all : ${DOCUMENT} 41 all : fragments_ran ${DOCUMENT} 42 43 fragments_ran : $(RunPgmOut) 34 44 35 45 clean : … … 38 48 # File Dependencies 39 49 40 %.pdf : ${TeXSRC} ${Demo SRC:%.cfa=%.tex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build}50 %.pdf : ${TeXSRC} ${DemoTex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build} 41 51 ${LaTeX} ${BASE} 42 52 ${BibTeX} ${Build}/${BASE} … … 52 62 53 63 %-demo.tex: %-demo | ${Build} 54 $ {Build}/$< > ${Build}/$@64 $< > $@ 55 65 56 %-demo: %-demo.cfa 57 ${CFA} $< -o $ {Build}/$@66 ${Build}/%-demo: ${Programs}/%-demo.cfa | ${Build} 67 ${CFA} $< -o $@ 58 68 69 ${Build}/%: ${Programs}/%.run.cfa | ${Build} 70 ${CFA} $< -o $@ 71 72 ${Build}/%: ${Programs}/%.run.c | ${Build} 73 ${CC} $< -o $@ 74 75 ${Build}/%: ${Programs}/%.run.cpp | ${Build} 76 ${CXX} -MMD $< -o $@ 77 78 ${Build}/%.out: ${Build}/% | ${Build} 79 $< > $@ 80 81 -include ${Build}/*.d -
doc/theses/mike_brooks_MMath/uw-ethesis.bib
r34b4268 r24d6572 65 65 bibsource = {dblp computer science bibliography, https://dblp.org} 66 66 } 67 68 % -------------------------------------------------- 69 % Linked-list prior work 70 71 @misc{CFAStackEvaluation, 72 contributer = {a3moss@plg}, 73 author = {Aaron Moss}, 74 title = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs}, 75 year = 2018, 76 howpublished= {\href{https://cforall.uwaterloo.ca/CFAStackEvaluation.zip}{https://cforall.uwaterloo.ca/\-CFAStackEvaluation.zip}}, 77 } 78 79 @misc{lst:linuxq, 80 title = {queue(7) — Linux manual page}, 81 howpublished= {\href{https://man7.org/linux/man-pages/man3/queue.3.html}{https://man7.org/linux/man-pages/man3/queue.3.html}}, 82 } 83 % see also https://man7.org/linux/man-pages/man7/queue.7.license.html 84 % https://man7.org/tlpi/ 85 % https://www.kernel.org/doc/man-pages/ 86 87 @misc{lst:stl, 88 title = {std::list}, 89 howpublished= {\href{https://en.cppreference.com/w/cpp/container/list}{https://en.cppreference.com/w/cpp/container/list}}, 90 } 91 -
doc/theses/mike_brooks_MMath/uw-ethesis.tex
r34b4268 r24d6572 60 60 % For hyperlinked PDF, suitable for viewing on a computer, use this: 61 61 \documentclass[letterpaper,12pt,titlepage,oneside,final]{book} 62 \usepackage{times} 62 63 \usepackage[T1]{fontenc} % Latin-1 => 256-bit characters, => | not dash, <> not Spanish question marks 63 64 … … 87 88 \usepackage{comment} % Removes large sections of the document. 88 89 \usepackage{tabularx} 89 \usepackage{subfigure} 90 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig} 91 \renewcommand\thesubfigure{(\alph{subfigure})} 90 92 91 93 \usepackage{algorithm} … … 115 117 citecolor=blue, % color of links to bibliography 116 118 filecolor=magenta, % color of file links 117 urlcolor=blue % color of external links 119 urlcolor=blue, % color of external links 120 breaklinks=true 118 121 } 119 122 \ifthenelse{\boolean{PrintVersion}}{ % for improved print quality, change some hyperref options … … 129 132 % although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and 130 133 % installation instructions there. 134 135 % Customizing tabularx 136 \newcolumntype{Y}{>{\centering\arraybackslash}X} 131 137 132 138 % Setting up the page margins... … … 175 181 \CFAStyle % CFA code-style 176 182 \lstset{language=CFA} % default language 177 \lstset{basicstyle=\linespread{0.9}\ tt} % CFA typewriter font183 \lstset{basicstyle=\linespread{0.9}\sf} % CFA typewriter font 178 184 \lstset{inputpath={programs}} 179 185 \newcommand{\PAB}[1]{{\color{red}PAB: #1}} 186 187 \newcommand{\uCpp}{$\mu$\CC} 180 188 181 189 %====================================================================== … … 201 209 %---------------------------------------------------------------------- 202 210 \begin{sloppypar} 203 204 211 \input{intro} 205 212 \input{background} 213 \input{list} 206 214 \input{array} 207 215 \input{string} -
driver/cfa.cc
r34b4268 r24d6572 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 14 21:55:12 202113 // Update Count : 4 6712 // Last Modified On : Tue May 30 10:47:52 2023 13 // Update Count : 478 14 14 // 15 15 … … 44 44 static int flags = 0; 45 45 46 // This allocation 'leaks' memory from the program to the execution 47 // environment, as putenv does not manage the storage of the string used 48 // as an environment variable. This leak is necessary to ensure the 49 // underlying C string is allocated long enough. 46 50 if ( putenv( (char *)( *new string( string( __CFA_FLAGPREFIX__ + to_string( flags++ ) + "__=" ) + arg ) ).c_str() ) ) { 47 51 cerr << argv[0] << " error, cannot set environment variable." << endl; … … 198 202 } // if 199 203 } else if ( arg == "-CFA" ) { 200 CFA_flag = true; // strip the-CFA flag204 CFA_flag = true; // strip -CFA flag 201 205 link = false; 202 206 args[nargs++] = "-fsyntax-only"; // stop after stage 2 203 207 } else if ( arg == "-debug" ) { 204 debug = true; // strip thedebug flag208 debug = true; // strip debug flag 205 209 } else if ( arg == "-nodebug" ) { 206 debug = false; // strip thenodebug flag210 debug = false; // strip nodebug flag 207 211 } else if ( arg == "-quiet" ) { 208 quiet = true; // strip thequiet flag212 quiet = true; // strip quiet flag 209 213 } else if ( arg == "-noquiet" ) { 210 quiet = false; // strip the noquiet flag 214 quiet = false; // strip noquiet flag 215 } else if ( arg == "-invariant" ) { 216 Putenv( argv, "-" + arg ); 217 } else if ( arg == "--invariant" ) { 218 Putenv( argv, arg ); 211 219 } else if ( arg == "-no-include-stdhdr" ) { 212 noincstd_flag = true; // strip theno-include-stdhdr flag220 noincstd_flag = true; // strip no-include-stdhdr flag 213 221 } else if ( arg == "-nolib" ) { 214 nolib = true; // strip thenolib flag222 nolib = true; // strip nolib flag 215 223 } else if ( arg == "-help" ) { 216 help = true; // strip thehelp flag224 help = true; // strip help flag 217 225 } else if ( arg == "-nohelp" ) { 218 help = false; // strip thenohelp flag226 help = false; // strip nohelp flag 219 227 } else if ( arg == "-cfalib") { 220 228 compiling_libs = true; … … 274 282 } // if 275 283 } else if ( prefix( arg, "-B" ) ) { 276 bprefix = arg.substr(2); // strip the-B flag284 bprefix = arg.substr(2); // strip -B flag 277 285 } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) { 278 286 args[nargs++] = argv[i]; // pass flag along … … 321 329 #endif // __x86_64__ 322 330 331 // ARM -mno-outline-atomics => use LL/SC instead of calls to atomic routines: __aarch64_swp_acq_rel, __aarch64_cas8_acq_rel 332 // ARM -march=armv8.2-a+lse => generate Arm LSE extension instructions SWAP and CAS 333 // https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/making-the-most-of-the-arm-architecture-in-gcc-10 334 #ifdef __ARM_ARCH 335 args[nargs++] = "-mno-outline-atomics"; // use ARM LL/SC instructions for atomics 336 #endif // __ARM_ARCH 337 323 338 #ifdef __DEBUG_H__ 324 339 cerr << "args:"; … … 444 459 445 460 args[nargs++] = "-fexceptions"; // add exception flags (unconditionally) 461 args[nargs++] = "-D_GNU_SOURCE"; // force gnu libraries 446 462 447 463 // add flags based on the type of compile -
libcfa/configure.ac
r34b4268 r24d6572 122 122 AC_PROG_CC 123 123 AM_PROG_AS 124 AC_PROG_LIBTOOL 124 LT_INIT 125 125 AC_PROG_INSTALL 126 126 AC_PROG_MAKE_SET … … 246 246 AC_CONFIG_HEADERS(prelude/defines.hfa) 247 247 248 AC_OUTPUT ()248 AC_OUTPUT 249 249 250 250 # Final text -
libcfa/prelude/builtins.c
r34b4268 r24d6572 10 10 // Created On : Fri Jul 21 16:21:03 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 14 08:45:54 202113 // Update Count : 13 312 // Last Modified On : Thu Feb 2 11:33:56 2023 13 // Update Count : 135 14 14 // 15 15 … … 64 64 static inline void ^?{}(generator$ &) {} 65 65 66 trait is_generator(T &) { 66 forall( T & ) 67 trait is_generator { 67 68 void main(T & this); 68 69 generator$ * get_generator(T & this); … … 148 149 149 150 static inline { 150 longint ?\?( int x, unsigned int y ) { __CFA_EXP__(); }151 int ?\?( int x, unsigned int y ) { __CFA_EXP__(); } 151 152 long int ?\?( long int x, unsigned long int y ) { __CFA_EXP__(); } 152 153 long long int ?\?( long long int x, unsigned long long int y ) { __CFA_EXP__(); } 153 154 // unsigned computation may be faster and larger 154 unsigned longint ?\?( unsigned int x, unsigned int y ) { __CFA_EXP__(); }155 unsigned int ?\?( unsigned int x, unsigned int y ) { __CFA_EXP__(); } 155 156 unsigned long int ?\?( unsigned long int x, unsigned long int y ) { __CFA_EXP__(); } 156 157 unsigned long long int ?\?( unsigned long long int x, unsigned long long int y ) { __CFA_EXP__(); } … … 175 176 176 177 static inline { 177 longint ?\=?( int & x, unsigned int y ) { x = x \ y; return x; }178 int ?\=?( int & x, unsigned int y ) { x = x \ y; return x; } 178 179 long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; } 179 180 long long int ?\=?( long long int & x, unsigned long long int y ) { x = x \ y; return x; } 180 unsigned longint ?\=?( unsigned int & x, unsigned int y ) { x = x \ y; return x; }181 unsigned int ?\=?( unsigned int & x, unsigned int y ) { x = x \ y; return x; } 181 182 unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; } 182 183 unsigned long long int ?\=?( unsigned long long int & x, unsigned long long int y ) { x = x \ y; return x; } -
libcfa/prelude/prelude-gen.cc
r34b4268 r24d6572 10 10 // Created On : Sat Feb 16 08:44:58 2019 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Apr 2 17:18:24 201913 // Update Count : 3 712 // Last Modified On : Thu Feb 2 11:40:01 2023 13 // Update Count : 38 14 14 // 15 15 … … 159 159 int main() { 160 160 cout << "# 2 \"prelude.cfa\" // needed for error messages from this file" << endl; 161 cout << " trait sized(T &){};" << endl;161 cout << "forall( T & ) trait sized {};" << endl; 162 162 163 163 cout << "//////////////////////////" << endl; -
libcfa/src/Makefile.am
r34b4268 r24d6572 11 11 ## Created On : Sun May 31 08:54:01 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Fri Jul 16 16:00:40 202114 ## Update Count : 25 513 ## Last Modified On : Thu May 25 15:20:04 2023 14 ## Update Count : 259 15 15 ############################################################################### 16 16 … … 48 48 math.hfa \ 49 49 time_t.hfa \ 50 virtual_dtor.hfa \ 50 51 bits/algorithm.hfa \ 51 52 bits/align.hfa \ … … 58 59 bits/queue.hfa \ 59 60 bits/sequence.hfa \ 61 concurrency/atomic.hfa \ 60 62 concurrency/iofwd.hfa \ 61 63 concurrency/barrier.hfa \ … … 113 115 concurrency/once.hfa \ 114 116 concurrency/kernel/fwd.hfa \ 115 concurrency/mutex_stmt.hfa 117 concurrency/mutex_stmt.hfa \ 118 concurrency/channel.hfa \ 119 concurrency/actor.hfa 116 120 117 121 inst_thread_headers_src = \ … … 124 128 concurrency/monitor.hfa \ 125 129 concurrency/mutex.hfa \ 130 concurrency/select.hfa \ 126 131 concurrency/thread.hfa 127 132 -
libcfa/src/algorithms/range_iterator.hfa
r34b4268 r24d6572 9 9 // Author : Thierry Delisle 10 10 // Created On : Tue Nov 30 13:06:22 2021 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 13 23:10:35 2023 13 // Update Count : 1 14 14 // 15 16 #pragma once 15 17 16 18 generator RangeIter { -
libcfa/src/bitmanip.hfa
r34b4268 r24d6572 11 11 // Created On : Sat Mar 14 18:12:27 2020 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Sat Oct 8 08:28:15 202214 // Update Count : 14 213 // Last Modified On : Mon Jan 9 09:02:43 2023 14 // Update Count : 144 15 15 // 16 16 17 17 #pragma once 18 19 #include "bits/debug.hfa" // verify 18 20 19 21 // Reference: Bit Twiddling Hacks: http://graphics.stanford.edu/%7Eseander/bithacks.html#CountBitsSetNaive -
libcfa/src/bits/containers.hfa
r34b4268 r24d6572 10 10 // Created On : Tue Oct 31 16:38:50 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 15 07:42:35 202013 // Update Count : 2 812 // Last Modified On : Thu Feb 2 11:33:08 2023 13 // Update Count : 29 14 14 15 15 #pragma once … … 69 69 70 70 #ifdef __cforall 71 trait is_node(T &) { 71 forall( T & ) 72 trait is_node { 72 73 T *& get_next( T & ); 73 74 }; -
libcfa/src/bits/random.hfa
r34b4268 r24d6572 10 10 // Created On : Fri Jan 14 07:18:11 2022 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 11 18:43:58 202213 // Update Count : 1 7112 // Last Modified On : Mon Mar 20 21:45:24 2023 13 // Update Count : 186 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <stdint.h> 18 #include <stdint.h> // uintXX_t 19 19 20 20 #define GLUE2( x, y ) x##y … … 24 24 #ifdef __x86_64__ // 64-bit architecture 25 25 // 64-bit generators 26 #define LEHMER6426 //#define LEHMER64 27 27 //#define XORSHIFT_12_25_27 28 //#define XOSHIRO256PP28 #define XOSHIRO256PP 29 29 //#define KISS_64 30 // #define SPLITMIX_64 30 31 31 32 // 32-bit generators 32 #define XORSHIFT_6_21_7 33 //#define XOSHIRO128PP 33 //#define XORSHIFT_6_21_7 34 #define XOSHIRO128PP 35 // #define SPLITMIX_32 34 36 #else // 32-bit architecture 35 37 // 64-bit generators 36 #define XORSHIFT_13_7_17 38 //#define XORSHIFT_13_7_17 39 #define XOSHIRO256PP 40 // #define SPLITMIX_64 37 41 38 42 // 32-bit generators 39 #define XORSHIFT_6_21_7 43 //#define XORSHIFT_6_21_7 44 #define XOSHIRO128PP 45 // #define SPLITMIX_32 40 46 #endif // __x86_64__ 41 47 42 48 // Define C/CFA PRNG name and random-state. 43 44 // SKULLDUGGERY: typedefs name struct and typedef with the same name to deal with CFA typedef numbering problem.45 49 46 50 #ifdef XOSHIRO256PP 47 51 #define PRNG_NAME_64 xoshiro256pp 48 52 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 49 typedef struct PRNG_STATE_64_T { uint64_t s[4]; } PRNG_STATE_64_T;53 typedef struct { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T; 50 54 #endif // XOSHIRO256PP 51 55 … … 53 57 #define PRNG_NAME_32 xoshiro128pp 54 58 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 55 typedef struct PRNG_STATE_32_T { uint32_t s[4]; } PRNG_STATE_32_T;59 typedef struct { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T; 56 60 #endif // XOSHIRO128PP 57 61 … … 81 85 #endif // XORSHIFT_12_25_27 82 86 87 #ifdef SPLITMIX_64 88 #define PRNG_NAME_64 splitmix64 89 #define PRNG_STATE_64_T uint64_t 90 #endif // SPLITMIX32 91 92 #ifdef SPLITMIX_32 93 #define PRNG_NAME_32 splitmix32 94 #define PRNG_STATE_32_T uint32_t 95 #endif // SPLITMIX32 96 83 97 #ifdef KISS_64 84 98 #define PRNG_NAME_64 kiss_64 85 99 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 86 typedef struct PRNG_STATE_64_T{ uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;100 typedef struct { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T; 87 101 #endif // KISS_^64 88 102 … … 90 104 #define PRNG_NAME_32 xorwow 91 105 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 92 typedef struct PRNG_STATE_32_T{ uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;106 typedef struct { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T; 93 107 #endif // XOSHIRO128PP 94 108 … … 110 124 111 125 // ALL PRNG ALGORITHMS ARE OPTIMIZED SO THAT THE PRNG LOGIC CAN HAPPEN IN PARALLEL WITH THE USE OF THE RESULT. 112 // Therefore, the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the 113 // first random value. 126 // Specifically, the current random state is copied for returning, before computing the next value. As a consequence, 127 // the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the first random 128 // value. 129 114 130 115 131 #ifdef __cforall // don't include in C code (invoke.h) 132 133 // https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64 134 // 135 // Splitmix64 is not recommended for demanding random number requirements, but is often used to calculate initial states 136 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it). 137 // Also https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64. 138 static inline uint64_t splitmix64( uint64_t & state ) { 139 state += 0x9e3779b97f4a7c15; 140 uint64_t z = state; 141 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 142 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 143 return z ^ (z >> 31); 144 } // splitmix64 145 146 static inline void splitmix64_set_seed( uint64_t & state , uint64_t seed ) { 147 state = seed; 148 splitmix64( state ); // prime 149 } // splitmix64_set_seed 150 151 // https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32 152 // 153 // Splitmix32 is not recommended for demanding random number requirements, but is often used to calculate initial states 154 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it). 155 156 static inline uint32_t splitmix32( uint32_t & state ) { 157 state += 0x9e3779b9; 158 uint64_t z = state; 159 z = (z ^ (z >> 15)) * 0x85ebca6b; 160 z = (z ^ (z >> 13)) * 0xc2b2ae35; 161 return z ^ (z >> 16); 162 } // splitmix32 163 164 static inline void splitmix32_set_seed( uint32_t & state, uint64_t seed ) { 165 state = seed; 166 splitmix32( state ); // prime 167 } // splitmix32_set_seed 168 169 #ifdef __SIZEOF_INT128__ 170 //-------------------------------------------------- 171 static inline uint64_t lehmer64( __uint128_t & state ) { 172 __uint128_t ret = state; 173 state *= 0x_da94_2042_e4dd_58b5; 174 return ret >> 64; 175 } // lehmer64 176 177 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) { 178 // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed. 179 state = splitmix64( seed ); // prime 180 } // lehmer64_set_seed 181 182 //-------------------------------------------------- 183 static inline uint64_t wyhash64( uint64_t & state ) { 184 uint64_t ret = state; 185 state += 0x_60be_e2be_e120_fc15; 186 __uint128_t tmp; 187 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d; 188 uint64_t m1 = (tmp >> 64) ^ tmp; 189 tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9; 190 uint64_t m2 = (tmp >> 64) ^ tmp; 191 return m2; 192 } // wyhash64 193 194 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) { 195 state = splitmix64( seed ); // prime 196 } // wyhash64_set_seed 197 #endif // __SIZEOF_INT128__ 116 198 117 199 // https://prng.di.unimi.it/xoshiro256starstar.c … … 126 208 127 209 #ifndef XOSHIRO256PP 128 typedef struct xoshiro256pp_t { uint64_t s[4]; } xoshiro256pp_t;210 typedef struct { uint64_t s0, s1, s2, s3; } xoshiro256pp_t; 129 211 #endif // ! XOSHIRO256PP 130 212 131 213 static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) { 132 inline uint64_t rotl( const uint64_t x, int k) {214 inline uint64_t rotl( const uint64_t x, int k ) { 133 215 return (x << k) | (x >> (64 - k)); 134 216 } // rotl 135 217 136 const uint64_t result = rotl( s [0] + s[3], 23 ) + s[0];137 const uint64_t t = s [1]<< 17;138 139 s [2] ^= s[0];140 s [3] ^= s[1];141 s [1] ^= s[2];142 s [0] ^= s[3];143 s [2]^= t;144 s [3] = rotl( s[3], 45 );218 const uint64_t result = rotl( s0 + s3, 23 ) + s0; 219 const uint64_t t = s1 << 17; 220 221 s2 ^= s0; 222 s3 ^= s1; 223 s1 ^= s2; 224 s0 ^= s3; 225 s2 ^= t; 226 s3 = rotl( s3, 45 ); 145 227 return result; 146 228 } // xoshiro256pp 147 229 148 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) { 149 state = (xoshiro256pp_t){ {seed, seed, seed, seed} }; 150 xoshiro256pp( state ); 230 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) { 231 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 232 uint64_t seed1 = splitmix64( seed ); // prime 233 uint64_t seed2 = splitmix64( seed ); 234 uint64_t seed3 = splitmix64( seed ); 235 uint64_t seed4 = splitmix64( seed ); 236 state = (xoshiro256pp_t){ seed1, seed2, seed3, seed4 }; 151 237 } // xoshiro256pp_set_seed 152 238 … … 161 247 162 248 #ifndef XOSHIRO128PP 163 typedef struct xoshiro128pp_t { uint32_t s[4]; } xoshiro128pp_t;249 typedef struct { uint32_t s0, s1, s2, s3; } xoshiro128pp_t; 164 250 #endif // ! XOSHIRO128PP 165 251 … … 169 255 } // rotl 170 256 171 const uint32_t result = rotl( s [0] + s[3], 7 ) + s[0];172 const uint32_t t = s [1]<< 9;173 174 s [2] ^= s[0];175 s [3] ^= s[1];176 s [1] ^= s[2];177 s [0] ^= s[3];178 s [2]^= t;179 s [3] = rotl( s[3], 11 );257 const uint32_t result = rotl( s0 + s3, 7 ) + s0; 258 const uint32_t t = s1 << 9; 259 260 s2 ^= s0; 261 s3 ^= s1; 262 s1 ^= s2; 263 s0 ^= s3; 264 s2 ^= t; 265 s3 = rotl( s3, 11 ); 180 266 return result; 181 267 } // xoshiro128pp 182 268 183 269 static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) { 184 state = (xoshiro128pp_t){ {seed, seed, seed, seed} }; 185 xoshiro128pp( state ); // prime 270 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 271 uint32_t seed1 = splitmix32( seed ); // prime 272 uint32_t seed2 = splitmix32( seed ); 273 uint32_t seed3 = splitmix32( seed ); 274 uint32_t seed4 = splitmix32( seed ); 275 state = (xoshiro128pp_t){ seed1, seed2, seed3, seed4 }; 186 276 } // xoshiro128pp_set_seed 187 188 #ifdef __SIZEOF_INT128__189 // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is190 // returned (copied), and then compute and store the next random value.191 //--------------------------------------------------192 static inline uint64_t lehmer64( __uint128_t & state ) {193 __uint128_t ret = state;194 state *= 0xda942042e4dd58b5;195 return ret >> 64;196 } // lehmer64197 198 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) {199 state = seed;200 lehmer64( state );201 } // lehmer64_set_seed202 203 //--------------------------------------------------204 static inline uint64_t wyhash64( uint64_t & state ) {205 uint64_t ret = state;206 state += 0x_60be_e2be_e120_fc15;207 __uint128_t tmp;208 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d;209 uint64_t m1 = (tmp >> 64) ^ tmp;210 tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9;211 uint64_t m2 = (tmp >> 64) ^ tmp;212 return m2;213 } // wyhash64214 215 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) {216 state = seed;217 wyhash64( state ); // prime218 } // wyhash64_set_seed219 #endif // __SIZEOF_INT128__220 277 221 278 //-------------------------------------------------- … … 229 286 230 287 static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) { 231 state = seed; 232 xorshift_13_7_17( state ); // prime 288 state = splitmix64( seed ); // prime 233 289 } // xorshift_13_7_17_set_seed 234 290 … … 247 303 248 304 static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) { 249 state = seed; 250 xorshift_6_21_7( state ); // prime 305 state = splitmix32( seed ); // prime 251 306 } // xorshift_6_21_7_set_seed 252 307 … … 262 317 263 318 static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) { 264 state = seed; 265 xorshift_12_25_27( state ); // prime 319 state = splitmix64( seed ); // prime 266 320 } // xorshift_12_25_27_set_seed 267 321 … … 269 323 // The state must be seeded with a nonzero value. 270 324 #ifndef KISS_64 271 typedef struct kiss_64_t{ uint64_t z, w, jsr, jcong; } kiss_64_t;325 typedef struct { uint64_t z, w, jsr, jcong; } kiss_64_t; 272 326 #endif // ! KISS_64 273 327 274 static inline uint64_t kiss_64( kiss_64_t & state ) with(state) {275 kiss_64_t ret = state;328 static inline uint64_t kiss_64( kiss_64_t & rs ) with(rs) { 329 kiss_64_t ret = rs; 276 330 z = 36969 * (z & 65535) + (z >> 16); 277 331 w = 18000 * (w & 65535) + (w >> 16); 278 jsr ^= (jsr << 17);279 332 jsr ^= (jsr << 13); 333 jsr ^= (jsr >> 17); 280 334 jsr ^= (jsr << 5); 281 335 jcong = 69069 * jcong + 1234567; … … 283 337 } // kiss_64 284 338 285 static inline void kiss_64_set_seed( kiss_64_t & state, uint64_t seed ) with(state) { 286 z = 1; w = 1; jsr = 4; jcong = seed; 287 kiss_64( state ); // prime 339 static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) { 340 z = 1; w = 1; jsr = 4; jcong = splitmix64( seed ); // prime 288 341 } // kiss_64_set_seed 289 342 … … 291 344 // The state array must be initialized to non-zero in the first four words. 292 345 #ifndef XORWOW 293 typedef struct xorwow_t{ uint32_t a, b, c, d, counter; } xorwow_t;346 typedef struct { uint32_t a, b, c, d, counter; } xorwow_t; 294 347 #endif // ! XORWOW 295 348 296 static inline uint32_t xorwow( xorwow_t & state ) with(state) {349 static inline uint32_t xorwow( xorwow_t & rs ) with(rs) { 297 350 // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs". 298 351 uint32_t ret = a + counter; … … 312 365 } // xorwow 313 366 314 static inline void xorwow_set_seed( xorwow_t & state, uint32_t seed ) { 315 state = (xorwow_t){ seed, seed, seed, seed, 0 }; 316 xorwow( state ); // prime 367 static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) { 368 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 369 uint32_t seed1 = splitmix32( seed ); // prime 370 uint32_t seed2 = splitmix32( seed ); 371 uint32_t seed3 = splitmix32( seed ); 372 uint32_t seed4 = splitmix32( seed ); 373 rs = (xorwow_t){ seed1, seed2, seed3, seed4, 0 }; 317 374 } // xorwow_set_seed 318 375 … … 320 377 // Used in __tls_rand_fwd 321 378 #define M (1_l64u << 48_l64u) 322 #define A (25 214903917_l64u)323 #define AI (18 446708753438544741_l64u)379 #define A (25_214_903_917_l64u) 380 #define AI (18_446_708_753_438_544_741_l64u) 324 381 #define C (11_l64u) 325 382 #define D (16_l64u) 326 383 327 384 // Bi-directional LCG random-number generator 328 static inline uint32_t LCGBI_fwd( uint64_t & state) {329 state = (A * state+ C) & (M - 1);330 return state>> D;385 static inline uint32_t LCGBI_fwd( uint64_t & rs ) { 386 rs = (A * rs + C) & (M - 1); 387 return rs >> D; 331 388 } // LCGBI_fwd 332 389 333 static inline uint32_t LCGBI_bck( uint64_t & state) {334 unsigned int r = state>> D;335 state = AI * (state- C) & (M - 1);390 static inline uint32_t LCGBI_bck( uint64_t & rs ) { 391 unsigned int r = rs >> D; 392 rs = AI * (rs - C) & (M - 1); 336 393 return r; 337 394 } // LCGBI_bck -
libcfa/src/bits/weakso_locks.cfa
r34b4268 r24d6572 15 15 // Update Count : 16 16 // 17 18 17 #include "bits/weakso_locks.hfa" 19 20 18 #pragma GCC visibility push(default) 21 19 … … 27 25 void unlock( blocking_lock & ) {} 28 26 void on_notify( blocking_lock &, struct thread$ * ) {} 29 size_t on_wait( blocking_lock & ) { return 0; }27 size_t on_wait( blocking_lock &, void (*pp_fn)( void * ), void * pp_datum ) { return 0; } 30 28 void on_wakeup( blocking_lock &, size_t ) {} 31 29 size_t wait_count( blocking_lock & ) { return 0; } 30 bool register_select( blocking_lock & this, select_node & node ) { return false; } 31 bool unregister_select( blocking_lock & this, select_node & node ) { return false; } 32 void on_selected( blocking_lock & this, select_node & node ) {} 33 -
libcfa/src/bits/weakso_locks.hfa
r34b4268 r24d6572 23 23 #include "containers/list.hfa" 24 24 25 struct thread$;25 struct select_node; 26 26 27 27 //----------------------------------------------------------------------------- … … 32 32 33 33 // List of blocked threads 34 dlist( thread$) blocked_threads;34 dlist( select_node ) blocked_threads; 35 35 36 36 // Count of current blocked threads … … 57 57 void unlock( blocking_lock & this ) OPTIONAL_THREAD; 58 58 void on_notify( blocking_lock & this, struct thread$ * t ) OPTIONAL_THREAD; 59 size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD;59 size_t on_wait( blocking_lock & this, void (*pp_fn)( void * ), void * pp_datum ) OPTIONAL_THREAD; 60 60 void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD; 61 61 size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD; 62 bool register_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 63 bool unregister_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 64 void on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 62 65 63 66 //---------- … … 72 75 static inline bool try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); } 73 76 static inline void unlock ( multiple_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 74 static inline size_t on_wait ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this); }77 static inline size_t on_wait ( multiple_acquisition_lock & this, void (*pp_fn)( void * ), void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); } 75 78 static inline void on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 76 79 static inline void on_notify( multiple_acquisition_lock & this, struct thread$ * t ){ on_notify( (blocking_lock &)this, t ); } 80 static inline bool register_select( multiple_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 81 static inline bool unregister_select( multiple_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 82 static inline void on_selected( multiple_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } -
libcfa/src/common.hfa
r34b4268 r24d6572 32 32 } // extern "C" 33 33 static inline __attribute__((always_inline)) { 34 unsigned char abs( signed char v ) { return abs( (int)v ); }34 unsigned char abs( signed char v ) { return (int)abs( (int)v ); } 35 35 // use default C routine for int 36 36 unsigned long int abs( long int v ) { return labs( v ); } … … 70 70 unsigned int min( unsigned int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; } 71 71 long int min( long int v1, long int v2 ) { return v1 < v2 ? v1 : v2; } 72 unsigned long int min( unsigned long int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }72 unsigned long int min( unsigned long int v1, unsigned long int v2 ) { return v1 < v2 ? v1 : v2; } 73 73 long long int min( long long int v1, long long int v2 ) { return v1 < v2 ? v1 : v2; } 74 unsigned long long int min( unsigned long long int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }74 unsigned long long int min( unsigned long long int v1, unsigned long long int v2 ) { return v1 < v2 ? v1 : v2; } 75 75 forall( T | { int ?<?( T, T ); } ) // generic 76 76 T min( T v1, T v2 ) { return v1 < v2 ? v1 : v2; } -
libcfa/src/concurrency/clib/cfathread.cfa
r34b4268 r24d6572 16 16 // #define EPOLL_FOR_SOCKETS 17 17 18 #include <string.h> 19 18 20 #include "fstream.hfa" 19 21 #include "locks.hfa" … … 23 25 #include "time.hfa" 24 26 #include "stdlib.hfa" 25 27 #include "iofwd.hfa" 26 28 #include "cfathread.h" 27 28 extern "C" {29 #include <string.h>30 #include <errno.h>31 }32 29 33 30 extern void ?{}(processor &, const char[], cluster &, thread$ *); 34 31 extern "C" { 35 extern void __cfactx_invoke_thread(void (*main)(void *), void * this); 36 extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); 32 extern void __cfactx_invoke_thread(void (*main)(void *), void * this); 37 33 } 38 34 … … 439 435 // Mutex 440 436 struct cfathread_mutex { 441 linear_backoff_then_block_lock impl;437 exp_backoff_then_block_lock impl; 442 438 }; 443 439 int cfathread_mutex_init(cfathread_mutex_t *restrict mut, const cfathread_mutexattr_t *restrict) __attribute__((nonnull (1))) { *mut = new(); return 0; } … … 454 450 // Condition 455 451 struct cfathread_condition { 456 condition_variable( linear_backoff_then_block_lock) impl;452 condition_variable(exp_backoff_then_block_lock) impl; 457 453 }; 458 454 int cfathread_cond_init(cfathread_cond_t *restrict cond, const cfathread_condattr_t *restrict) __attribute__((nonnull (1))) { *cond = new(); return 0; } … … 472 468 } 473 469 474 #include <iofwd.hfa>475 476 470 extern "C" { 477 #include <unistd.h>478 #include <sys/types.h>479 #include <sys/socket.h>480 481 471 //-------------------- 482 472 // IO operations … … 488 478 , protocol); 489 479 } 490 int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len) {480 int cfathread_bind(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len) { 491 481 return bind(socket, address, address_len); 492 482 } … … 496 486 } 497 487 498 int cfathread_accept(int socket, struct sockaddr *restrictaddress, socklen_t *restrict address_len) {488 int cfathread_accept(int socket, __SOCKADDR_ARG address, socklen_t *restrict address_len) { 499 489 #if defined(EPOLL_FOR_SOCKETS) 500 490 int ret; … … 513 503 } 514 504 515 int cfathread_connect(int socket, const struct sockaddr *address, socklen_t address_len) {505 int cfathread_connect(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len) { 516 506 #if defined(EPOLL_FOR_SOCKETS) 517 507 int ret; -
libcfa/src/concurrency/clib/cfathread.h
r34b4268 r24d6572 9 9 // Author : Thierry Delisle 10 10 // Created On : Tue Sep 22 15:31:20 2020 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 13 23:48:40 2023 13 // Update Count : 7 14 14 // 15 15 16 #pragma once 17 16 18 #if defined(__cforall) || defined(__cplusplus) 19 #include <unistd.h> 20 #include <errno.h> 21 #include <sys/socket.h> 22 17 23 extern "C" { 18 24 #endif 19 #include <asm/types.h>20 #include <errno.h>21 #include <unistd.h>22 23 24 25 //-------------------- 25 26 // Basic types … … 73 74 } cfathread_mutexattr_t; 74 75 typedef struct cfathread_mutex * cfathread_mutex_t; 75 int cfathread_mutex_init(cfathread_mutex_t * restrict mut, const cfathread_mutexattr_t *restrict attr) __attribute__((nonnull (1)));76 int cfathread_mutex_init(cfathread_mutex_t * restrict mut, const cfathread_mutexattr_t * restrict attr) __attribute__((nonnull (1))); 76 77 int cfathread_mutex_destroy(cfathread_mutex_t *mut) __attribute__((nonnull (1))); 77 78 int cfathread_mutex_lock(cfathread_mutex_t *mut) __attribute__((nonnull (1))); … … 91 92 //-------------------- 92 93 // IO operations 93 struct sockaddr;94 struct msghdr;95 94 int cfathread_socket(int domain, int type, int protocol); 96 int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len);95 int cfathread_bind(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len); 97 96 int cfathread_listen(int socket, int backlog); 98 int cfathread_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);99 int cfathread_connect(int socket, const struct sockaddr *address, socklen_t address_len);97 int cfathread_accept(int socket, __SOCKADDR_ARG address, socklen_t * restrict address_len); 98 int cfathread_connect(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len); 100 99 int cfathread_dup(int fildes); 101 100 int cfathread_close(int fildes); -
libcfa/src/concurrency/coroutine.cfa
r34b4268 r24d6572 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Dec 15 12:06:04 202013 // Update Count : 2 312 // Last Modified On : Thu Feb 16 15:34:46 2023 13 // Update Count : 24 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #include "coroutine.hfa" -
libcfa/src/concurrency/coroutine.hfa
r34b4268 r24d6572 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jan 6 16:33:16 202213 // Update Count : 1 212 // Last Modified On : Thu Feb 2 11:31:42 2023 13 // Update Count : 13 14 14 // 15 15 … … 38 38 // Anything that implements this trait can be resumed. 39 39 // Anything that is resumed is a coroutine. 40 trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T))) { 40 forall( T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T)) ) 41 trait is_coroutine { 41 42 void main(T & this); 42 43 coroutine$ * get_coroutine(T & this); -
libcfa/src/concurrency/future.hfa
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // io/types.hfa --8 // 9 // Author : Thierry Delisle & Peiran Hong 7 // concurrency/future.hfa -- 8 // 9 // Author : Thierry Delisle & Peiran Hong & Colby Parsons 10 10 // Created On : Wed Jan 06 17:33:18 2021 11 11 // Last Modified By : … … 18 18 #include "bits/locks.hfa" 19 19 #include "monitor.hfa" 20 20 #include "select.hfa" 21 #include "locks.hfa" 22 23 //---------------------------------------------------------------------------- 24 // future 25 // I don't use future_t here since I need to use a lock for this future 26 // since it supports multiple consumers 27 // future_t is lockfree and uses atomics which aren't needed given we use locks here 21 28 forall( T ) { 29 // enum { FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards 30 31 // temporary enum replacement 32 const int FUTURE_EMPTY = 0; 33 const int FUTURE_FULFILLED = 1; 34 22 35 struct future { 36 int state; 37 T result; 38 dlist( select_node ) waiters; 39 futex_mutex lock; 40 }; 41 42 struct future_node { 43 inline select_node; 44 T * my_result; 45 }; 46 47 static inline { 48 49 void ?{}( future_node(T) & this, thread$ * blocked_thread, T * my_result ) { 50 ((select_node &)this){ blocked_thread }; 51 this.my_result = my_result; 52 } 53 54 void ?{}( future(T) & this ) { 55 this.waiters{}; 56 this.state = FUTURE_EMPTY; 57 this.lock{}; 58 } 59 60 // Reset future back to original state 61 void reset( future(T) & this ) with(this) 62 { 63 lock( lock ); 64 if( ! waiters`isEmpty ) 65 abort("Attempting to reset a future with blocked waiters"); 66 state = FUTURE_EMPTY; 67 unlock( lock ); 68 } 69 70 // check if the future is available 71 // currently no mutual exclusion because I can't see when you need this call to be synchronous or protected 72 bool available( future(T) & this ) { return __atomic_load_n( &this.state, __ATOMIC_RELAXED ); } 73 74 75 // memcpy wrapper to help copy values 76 void copy_T( T & from, T & to ) { 77 memcpy((void *)&to, (void *)&from, sizeof(T)); 78 } 79 80 // internal helper to signal waiters off of the future 81 void _internal_flush( future(T) & this ) with(this) { 82 while( ! waiters`isEmpty ) { 83 if ( !__handle_waituntil_OR( waiters ) ) // handle special waituntil OR case 84 break; // if handle_OR returns false then waiters is empty so break 85 select_node &s = try_pop_front( waiters ); 86 87 if ( s.clause_status == 0p ) // poke in result so that woken threads do not need to reacquire any locks 88 copy_T( result, *(((future_node(T) &)s).my_result) ); 89 90 wake_one( waiters, s ); 91 } 92 } 93 94 // Fulfil the future, returns whether or not someone was unblocked 95 bool fulfil( future(T) & this, T val ) with(this) { 96 lock( lock ); 97 if( state != FUTURE_EMPTY ) 98 abort("Attempting to fulfil a future that has already been fulfilled"); 99 100 copy_T( val, result ); 101 102 bool ret_val = ! waiters`isEmpty; 103 state = FUTURE_FULFILLED; 104 _internal_flush( this ); 105 unlock( lock ); 106 return ret_val; 107 } 108 109 // Wait for the future to be fulfilled 110 // Also return whether the thread had to block or not 111 [T, bool] get( future(T) & this ) with( this ) { 112 lock( lock ); 113 T ret_val; 114 if( state == FUTURE_FULFILLED ) { 115 copy_T( result, ret_val ); 116 unlock( lock ); 117 return [ret_val, false]; 118 } 119 120 future_node(T) node = { active_thread(), &ret_val }; 121 insert_last( waiters, ((select_node &)node) ); 122 unlock( lock ); 123 park( ); 124 125 return [ret_val, true]; 126 } 127 128 // Wait for the future to be fulfilled 129 T get( future(T) & this ) { 130 [T, bool] tt; 131 tt = get(this); 132 return tt.0; 133 } 134 135 // Gets value if it is available and returns [ val, true ] 136 // otherwise returns [ default_val, false] 137 // will not block 138 [T, bool] try_get( future(T) & this ) with(this) { 139 lock( lock ); 140 T ret_val; 141 if( state == FUTURE_FULFILLED ) { 142 copy_T( result, ret_val ); 143 unlock( lock ); 144 return [ret_val, true]; 145 } 146 unlock( lock ); 147 148 return [ret_val, false]; 149 } 150 151 bool register_select( future(T) & this, select_node & s ) with(this) { 152 lock( lock ); 153 154 // check if we can complete operation. If so race to establish winner in special OR case 155 if ( !s.park_counter && state != FUTURE_EMPTY ) { 156 if ( !__make_select_node_available( s ) ) { // we didn't win the race so give up on registering 157 unlock( lock ); 158 return false; 159 } 160 } 161 162 // future not ready -> insert select node and return 163 if( state == FUTURE_EMPTY ) { 164 insert_last( waiters, s ); 165 unlock( lock ); 166 return false; 167 } 168 169 __make_select_node_available( s ); 170 unlock( lock ); 171 return true; 172 } 173 174 bool unregister_select( future(T) & this, select_node & s ) with(this) { 175 if ( ! s`isListed ) return false; 176 lock( lock ); 177 if ( s`isListed ) remove( s ); 178 unlock( lock ); 179 return false; 180 } 181 182 void on_selected( future(T) & this, select_node & node ) {} 183 } 184 } 185 186 //-------------------------------------------------------------------------------------------------------- 187 // These futures below do not support select statements so they may not have as many features as 'future' 188 // however the 'single_future' is cheap and cheerful and is most likely more performant than 'future' 189 // since it uses raw atomics and no locks 190 // 191 // As far as 'multi_future' goes I can't see many use cases as it will be less performant than 'future' 192 // since it is monitor based and also is not compatible with select statements 193 //-------------------------------------------------------------------------------------------------------- 194 195 forall( T ) { 196 struct single_future { 23 197 inline future_t; 24 198 T result; … … 27 201 static inline { 28 202 // Reset future back to original state 29 void reset( future(T) & this) { reset( (future_t&)this ); }203 void reset(single_future(T) & this) { reset( (future_t&)this ); } 30 204 31 205 // check if the future is available 32 bool available( future(T) & this ) { return available( (future_t&)this ); }206 bool available( single_future(T) & this ) { return available( (future_t&)this ); } 33 207 34 208 // Mark the future as abandoned, meaning it will be deleted by the server 35 209 // This doesn't work beause of the potential need for a destructor 36 void abandon( future(T) & this );210 void abandon( single_future(T) & this ); 37 211 38 212 // Fulfil the future, returns whether or not someone was unblocked 39 thread$ * fulfil( future(T) & this, T result ) {213 thread$ * fulfil( single_future(T) & this, T result ) { 40 214 this.result = result; 41 215 return fulfil( (future_t&)this ); … … 44 218 // Wait for the future to be fulfilled 45 219 // Also return whether the thread had to block or not 46 [T, bool] wait( future(T) & this ) {220 [T, bool] wait( single_future(T) & this ) { 47 221 bool r = wait( (future_t&)this ); 48 222 return [this.result, r]; … … 50 224 51 225 // Wait for the future to be fulfilled 52 T wait( future(T) & this ) {226 T wait( single_future(T) & this ) { 53 227 [T, bool] tt; 54 228 tt = wait(this); -
libcfa/src/concurrency/invoke.h
r34b4268 r24d6572 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 29 20:42:21 2022 13 // Update Count : 56 14 // 12 // Last Modified On : Tue Mar 14 13:39:31 2023 13 // Update Count : 59 14 // 15 16 // No not use #pragma once was this file is included twice in some places. It has its own guard system. 15 17 16 18 #include "bits/containers.hfa" … … 215 217 struct __thread_user_link cltr_link; 216 218 217 // used to store state between clh lock/unlock218 volatile bool * clh_prev;219 220 // used to point to this thd's current clh node221 volatile bool * clh_node;222 223 219 struct processor * last_proc; 220 221 // ptr used during handover between blocking lists to allow for stack allocation of intrusive nodes 222 // main use case is wait-morphing to allow a different node to be used to block on condvar vs lock 223 void * link_node; 224 224 225 225 PRNG_STATE_T random_state; // fast random numbers -
libcfa/src/concurrency/io.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #if defined(__CFA_DEBUG__) … … 85 84 static io_context$ * __ioarbiter_allocate( io_arbiter$ & this, __u32 idxs[], __u32 want ); 86 85 static void __ioarbiter_submit( io_context$ * , __u32 idxs[], __u32 have, bool lazy ); 87 static void __ioarbiter_flush ( io_context$ & );86 static void __ioarbiter_flush ( io_context$ &, bool kernel ); 88 87 static inline void __ioarbiter_notify( io_context$ & ctx ); 89 88 //============================================================================================= … … 94 93 extern void __kernel_unpark( thread$ * thrd, unpark_hint ); 95 94 95 static inline void __post(oneshot & this, bool kernel, unpark_hint hint) { 96 thread$ * t = post( this, false ); 97 if(kernel) __kernel_unpark( t, hint ); 98 else unpark( t, hint ); 99 } 100 101 // actual system call of io uring 102 // wrap so everything that needs to happen around it is always done 103 // i.e., stats, book keeping, sqe reclamation, etc. 96 104 static void ioring_syscsll( struct io_context$ & ctx, unsigned int min_comp, unsigned int flags ) { 97 105 __STATS__( true, io.calls.flush++; ) 98 106 int ret; 99 107 for() { 108 // do the system call in a loop, repeat on interrupts 100 109 ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, min_comp, flags, (sigset_t *)0p, _NSIG / 8); 101 110 if( ret < 0 ) { … … 120 129 /* paranoid */ verify( ctx.sq.to_submit >= ret ); 121 130 122 ctx.sq.to_submit -= ret; 131 // keep track of how many still need submitting 132 __atomic_fetch_sub(&ctx.sq.to_submit, ret, __ATOMIC_SEQ_CST); 123 133 124 134 /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num ); … … 129 139 /* paranoid */ verify( ! __preemption_enabled() ); 130 140 141 // mark that there is no pending io left 131 142 __atomic_store_n(&ctx.proc->io.pending, false, __ATOMIC_RELAXED); 132 143 } 133 144 145 // try to acquire an io context for draining, helping means we never *need* to drain, we can always do it later 134 146 static bool try_acquire( io_context$ * ctx ) __attribute__((nonnull(1))) { 135 147 /* paranoid */ verify( ! __preemption_enabled() ); … … 138 150 139 151 { 152 // if there is nothing to drain there is no point in acquiring anything 140 153 const __u32 head = *ctx->cq.head; 141 154 const __u32 tail = *ctx->cq.tail; … … 144 157 } 145 158 146 // Drain the queue 147 if(!__atomic_try_acquire(&ctx->cq.lock)) { 159 // try a simple spinlock acquire, it's likely there are completions to drain 160 if(!__atomic_try_acquire(&ctx->cq.try_lock)) { 161 // some other processor already has it 148 162 __STATS__( false, io.calls.locked++; ) 149 163 return false; 150 164 } 151 165 166 // acquired!! 152 167 return true; 153 168 } 154 169 170 // actually drain the completion 155 171 static bool __cfa_do_drain( io_context$ * ctx, cluster * cltr ) __attribute__((nonnull(1, 2))) { 156 172 /* paranoid */ verify( ! __preemption_enabled() ); 157 173 /* paranoid */ verify( ready_schedule_islocked() ); 158 /* paranoid */ verify( ctx->cq.lock == true ); 159 174 /* paranoid */ verify( ctx->cq.try_lock == true ); 175 176 // get all the invariants and initial state 160 177 const __u32 mask = *ctx->cq.mask; 161 178 const __u32 num = *ctx->cq.num; … … 166 183 for() { 167 184 // re-read the head and tail in case it already changed. 185 // count the difference between the two 168 186 const __u32 head = *ctx->cq.head; 169 187 const __u32 tail = *ctx->cq.tail; … … 171 189 __STATS__( false, io.calls.drain++; io.calls.completed += count; ) 172 190 191 // for everything between head and tail, drain it 173 192 for(i; count) { 174 193 unsigned idx = (head + i) & mask; … … 177 196 /* paranoid */ verify(&cqe); 178 197 198 // find the future in the completion 179 199 struct io_future_t * future = (struct io_future_t *)(uintptr_t)cqe.user_data; 180 200 // __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", &cqe, cqe.res, future ); 181 201 202 // don't directly fulfill the future, preemption is disabled so we need to use kernel_unpark 182 203 __kernel_unpark( fulfil( *future, cqe.res, false ), UNPARK_LOCAL ); 183 204 } 184 205 206 // update the timestamps accordingly 207 // keep a local copy so we can update the relaxed copy 185 208 ts_next = ctx->cq.ts = rdtscl(); 186 209 … … 190 213 ctx->proc->idle_wctx.drain_time = ts_next; 191 214 215 // we finished draining the completions... unless the ring buffer was full and there are more secret completions in the kernel. 192 216 if(likely(count < num)) break; 193 217 218 // the ring buffer was full, there could be more stuff in the kernel. 194 219 ioring_syscsll( *ctx, 0, IORING_ENTER_GETEVENTS); 195 220 } … … 199 224 /* paranoid */ verify( ! __preemption_enabled() ); 200 225 201 __atomic_unlock(&ctx->cq.lock); 202 226 // everything is drained, we can release the lock 227 __atomic_unlock(&ctx->cq.try_lock); 228 229 // update the relaxed timestamp 203 230 touch_tsc( cltr->sched.io.tscs, ctx->cq.id, ts_prev, ts_next, false ); 204 231 … … 206 233 } 207 234 235 // call from a processor to flush 236 // contains all the bookkeeping a proc must do, not just the barebones flushing logic 237 void __cfa_do_flush( io_context$ & ctx, bool kernel ) { 238 /* paranoid */ verify( ! __preemption_enabled() ); 239 240 // flush any external requests 241 ctx.sq.last_external = false; // clear the external bit, the arbiter will reset it if needed 242 __ioarbiter_flush( ctx, kernel ); 243 244 // if submitting must be submitted, do the system call 245 if(ctx.sq.to_submit != 0) { 246 ioring_syscsll(ctx, 0, 0); 247 } 248 } 249 250 // call from a processor to drain 251 // contains all the bookkeeping a proc must do, not just the barebones draining logic 208 252 bool __cfa_io_drain( struct processor * proc ) { 209 253 bool local = false; 210 254 bool remote = false; 211 255 256 // make sure no ones creates/destroys io contexts 212 257 ready_schedule_lock(); 213 258 … … 217 262 /* paranoid */ verify( ctx ); 218 263 264 // Help if needed 219 265 with(cltr->sched) { 220 266 const size_t ctxs_count = io.count; … … 230 276 const unsigned long long ctsc = rdtscl(); 231 277 278 // only help once every other time 279 // pick a target when not helping 232 280 if(proc->io.target == UINT_MAX) { 233 281 uint64_t chaos = __tls_rand(); 282 // choose who to help and whether to accept helping far processors 234 283 unsigned ext = chaos & 0xff; 235 284 unsigned other = (chaos >> 8) % (ctxs_count); 236 285 286 // if the processor is on the same cache line or is lucky ( 3 out of 256 odds ) help it 237 287 if(ext < 3 || __atomic_load_n(&caches[other / __shard_factor.io].id, __ATOMIC_RELAXED) == this_cache) { 238 288 proc->io.target = other; … … 240 290 } 241 291 else { 292 // a target was picked last time, help it 242 293 const unsigned target = proc->io.target; 243 294 /* paranoid */ verify( io.tscs[target].t.tv != ULLONG_MAX ); 295 // make sure the target hasn't stopped existing since last time 244 296 HELP: if(target < ctxs_count) { 297 // calculate it's age and how young it could be before we give up on helping 245 298 const __readyQ_avg_t cutoff = calc_cutoff(ctsc, ctx->cq.id, ctxs_count, io.data, io.tscs, __shard_factor.io, false); 246 299 const __readyQ_avg_t age = moving_average(ctsc, io.tscs[target].t.tv, io.tscs[target].t.ma, false); 247 300 __cfadbg_print_safe(io, "Kernel I/O: Help attempt on %u from %u, age %'llu vs cutoff %'llu, %s\n", target, ctx->cq.id, age, cutoff, age > cutoff ? "yes" : "no"); 301 // is the target older than the cutoff, recall 0 is oldest and bigger ints are younger 248 302 if(age <= cutoff) break HELP; 249 303 250 if(!try_acquire(io.data[target])) break HELP; 251 304 // attempt to help the submission side 305 __cfa_do_flush( *io.data[target], true ); 306 307 // attempt to help the completion side 308 if(!try_acquire(io.data[target])) break HELP; // already acquire no help needed 309 310 // actually help 252 311 if(!__cfa_do_drain( io.data[target], cltr )) break HELP; 253 312 313 // track we did help someone 254 314 remote = true; 255 315 __STATS__( true, io.calls.helped++; ) 256 316 } 317 318 // reset the target 257 319 proc->io.target = UINT_MAX; 258 320 } 259 321 } 260 261 322 262 323 // Drain the local queue … … 270 331 271 332 ready_schedule_unlock(); 333 334 // return true if some completion entry, local or remote, was drained 272 335 return local || remote; 273 336 } 274 337 338 339 340 // call from a processor to flush 341 // contains all the bookkeeping a proc must do, not just the barebones flushing logic 275 342 bool __cfa_io_flush( struct processor * proc ) { 276 343 /* paranoid */ verify( ! __preemption_enabled() ); … … 278 345 /* paranoid */ verify( proc->io.ctx ); 279 346 280 io_context$ & ctx = *proc->io.ctx; 281 282 __ioarbiter_flush( ctx ); 283 284 if(ctx.sq.to_submit != 0) { 285 ioring_syscsll(ctx, 0, 0); 286 287 } 288 347 __cfa_do_flush( *proc->io.ctx, false ); 348 349 // also drain since some stuff will immediately complete 289 350 return __cfa_io_drain( proc ); 290 351 } … … 393 454 //============================================================================================= 394 455 // submission 395 static inline void __submit_only( struct io_context$ * ctx, __u32 idxs[], __u32 have) { 456 // barebones logic to submit a group of sqes 457 static inline void __submit_only( struct io_context$ * ctx, __u32 idxs[], __u32 have, bool lock) { 458 if(!lock) 459 lock( ctx->ext_sq.lock __cfaabi_dbg_ctx2 ); 396 460 // We can proceed to the fast path 397 461 // Get the right objects … … 408 472 // Make the sqes visible to the submitter 409 473 __atomic_store_n(sq.kring.tail, tail + have, __ATOMIC_RELEASE); 410 sq.to_submit += have; 411 474 __atomic_fetch_add(&sq.to_submit, have, __ATOMIC_SEQ_CST); 475 476 // set the bit to mark things need to be flushed 412 477 __atomic_store_n(&ctx->proc->io.pending, true, __ATOMIC_RELAXED); 413 478 __atomic_store_n(&ctx->proc->io.dirty , true, __ATOMIC_RELAXED); 414 } 415 479 480 if(!lock) 481 unlock( ctx->ext_sq.lock ); 482 } 483 484 // submission logic + maybe flushing 416 485 static inline void __submit( struct io_context$ * ctx, __u32 idxs[], __u32 have, bool lazy) { 417 486 __sub_ring_t & sq = ctx->sq; 418 __submit_only(ctx, idxs, have );487 __submit_only(ctx, idxs, have, false); 419 488 420 489 if(sq.to_submit > 30) { … … 428 497 } 429 498 499 // call from a processor to flush 500 // might require arbitration if the thread was migrated after the allocation 430 501 void cfa_io_submit( struct io_context$ * inctx, __u32 idxs[], __u32 have, bool lazy ) __attribute__((nonnull (1))) libcfa_public { 431 502 // __cfadbg_print_safe(io, "Kernel I/O : attempting to submit %u (%s)\n", have, lazy ? "lazy" : "eager"); … … 441 512 if( ctx == inctx ) // We have the right instance? 442 513 { 514 // yes! fast submit 443 515 __submit(ctx, idxs, have, lazy); 444 516 … … 507 579 __atomic_store_n(&ctx.sq.free_ring.tail, ftail + count, __ATOMIC_SEQ_CST); 508 580 581 // notify the allocator that new allocations can be made 509 582 __ioarbiter_notify(ctx); 510 583 … … 557 630 } 558 631 632 // notify the arbiter that new allocations are available 559 633 static void __ioarbiter_notify( io_arbiter$ & this, io_context$ * ctx ) { 560 634 /* paranoid */ verify( !empty(this.pending.queue) ); 561 635 /* paranoid */ verify( __preemption_enabled() ); 636 637 // mutual exclusion is needed 562 638 lock( this.pending.lock __cfaabi_dbg_ctx2 ); 563 639 { 640 __cfadbg_print_safe(io, "Kernel I/O : notifying\n"); 641 642 // as long as there are pending allocations try to satisfy them 643 // for simplicity do it in FIFO order 564 644 while( !empty(this.pending.queue) ) { 565 __cfadbg_print_safe(io, "Kernel I/O : notifying\n");645 // get first pending allocs 566 646 __u32 have = ctx->sq.free_ring.tail - ctx->sq.free_ring.head; 567 647 __pending_alloc & pa = (__pending_alloc&)head( this.pending.queue ); 568 648 649 // check if we have enough to satisfy the request 569 650 if( have > pa.want ) goto DONE; 651 652 // if there are enough allocations it means we can drop the request 570 653 drop( this.pending.queue ); 571 654 572 655 /* paranoid */__attribute__((unused)) bool ret = 573 656 657 // actually do the alloc 574 658 __alloc(ctx, pa.idxs, pa.want); 575 659 576 660 /* paranoid */ verify( ret ); 577 661 662 // write out which context statisfied the request and post 663 // this 578 664 pa.ctx = ctx; 579 580 665 post( pa.waitctx ); 581 666 } … … 585 670 } 586 671 unlock( this.pending.lock ); 587 } 588 672 673 /* paranoid */ verify( __preemption_enabled() ); 674 } 675 676 // short hand to avoid the mutual exclusion of the pending is empty regardless 589 677 static void __ioarbiter_notify( io_context$ & ctx ) { 590 if(!empty( ctx.arbiter->pending )) { 591 __ioarbiter_notify( *ctx.arbiter, &ctx ); 592 } 593 } 594 595 // Simply append to the pending 678 if(empty( ctx.arbiter->pending )) return; 679 __ioarbiter_notify( *ctx.arbiter, &ctx ); 680 } 681 682 // Submit from outside the local processor: append to the outstanding list 596 683 static void __ioarbiter_submit( io_context$ * ctx, __u32 idxs[], __u32 have, bool lazy ) { 597 684 __cfadbg_print_safe(io, "Kernel I/O : submitting %u from the arbiter to context %u\n", have, ctx->fd); … … 599 686 __cfadbg_print_safe(io, "Kernel I/O : waiting to submit %u\n", have); 600 687 688 // create the intrusive object to append 601 689 __external_io ei; 602 690 ei.idxs = idxs; … … 604 692 ei.lazy = lazy; 605 693 694 // enqueue the io 606 695 bool we = enqueue(ctx->ext_sq, (__outstanding_io&)ei); 607 696 697 // mark pending 608 698 __atomic_store_n(&ctx->proc->io.pending, true, __ATOMIC_SEQ_CST); 609 699 700 // if this is the first to be enqueued, signal the processor in an attempt to speed up flushing 701 // if it's not the first enqueue, a signal is already in transit 610 702 if( we ) { 611 703 sigval_t value = { PREEMPT_IO }; 612 704 __cfaabi_pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value); 613 } 614 705 __STATS__( false, io.flush.signal += 1; ) 706 } 707 __STATS__( false, io.submit.extr += 1; ) 708 709 // to avoid dynamic allocation/memory reclamation headaches, wait for it to have been submitted 615 710 wait( ei.waitctx ); 616 711 … … 618 713 } 619 714 620 static void __ioarbiter_flush( io_context$ & ctx ) { 621 if(!empty( ctx.ext_sq )) { 622 __STATS__( false, io.flush.external += 1; ) 623 624 __cfadbg_print_safe(io, "Kernel I/O : arbiter flushing\n"); 625 626 lock( ctx.ext_sq.lock __cfaabi_dbg_ctx2 ); 627 { 628 while( !empty(ctx.ext_sq.queue) ) { 629 __external_io & ei = (__external_io&)drop( ctx.ext_sq.queue ); 630 631 __submit_only(&ctx, ei.idxs, ei.have); 632 633 post( ei.waitctx ); 634 } 635 636 ctx.ext_sq.empty = true; 715 // flush the io arbiter: move all external io operations to the submission ring 716 static void __ioarbiter_flush( io_context$ & ctx, bool kernel ) { 717 // if there are no external operations just return 718 if(empty( ctx.ext_sq )) return; 719 720 // stats and logs 721 __STATS__( false, io.flush.external += 1; ) 722 __cfadbg_print_safe(io, "Kernel I/O : arbiter flushing\n"); 723 724 // this can happen from multiple processors, mutual exclusion is needed 725 lock( ctx.ext_sq.lock __cfaabi_dbg_ctx2 ); 726 { 727 // pop each operation one at a time. 728 // There is no wait morphing because of the io sq ring 729 while( !empty(ctx.ext_sq.queue) ) { 730 // drop the element from the queue 731 __external_io & ei = (__external_io&)drop( ctx.ext_sq.queue ); 732 733 // submit it 734 __submit_only(&ctx, ei.idxs, ei.have, true); 735 736 // wake the thread that was waiting on it 737 // since this can both be called from kernel and user, check the flag before posting 738 __post( ei.waitctx, kernel, UNPARK_LOCAL ); 637 739 } 638 unlock(ctx.ext_sq.lock ); 740 741 // mark the queue as empty 742 ctx.ext_sq.empty = true; 743 ctx.sq.last_external = true; 744 } 745 unlock(ctx.ext_sq.lock ); 746 } 747 748 extern "C" { 749 // debug functions used for gdb 750 // io_uring doesn't yet support gdb soe the kernel-shared data structures aren't viewable in gdb 751 // these functions read the data that gdb can't and should be removed once the support is added 752 static __u32 __cfagdb_cq_head( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.head; } 753 static __u32 __cfagdb_cq_tail( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.tail; } 754 static __u32 __cfagdb_cq_mask( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.mask; } 755 static __u32 __cfagdb_sq_head( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.kring.head; } 756 static __u32 __cfagdb_sq_tail( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.kring.tail; } 757 static __u32 __cfagdb_sq_mask( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.mask; } 758 759 // fancier version that reads an sqe and copies it out. 760 static struct io_uring_sqe __cfagdb_sq_at( io_context$ * ctx, __u32 at ) __attribute__((nonnull(1),used,noinline)) { 761 __u32 ax = at & *ctx->sq.mask; 762 __u32 ix = ctx->sq.kring.array[ax]; 763 return ctx->sq.sqes[ix]; 639 764 } 640 765 } -
libcfa/src/concurrency/io/call.cfa.in
r34b4268 r24d6572 31 31 Prelude = """#define __cforall_thread__ 32 32 33 #include <unistd.h> 34 #include <errno.h> 35 #include <sys/socket.h> 36 #include <time.hfa> 37 33 38 #include "bits/defs.hfa" 34 39 #include "kernel.hfa" … … 43 48 #include <assert.h> 44 49 #include <stdint.h> 45 #include <errno.h>46 50 #include <linux/io_uring.h> 47 48 51 #include "kernel/fwd.hfa" 49 52 … … 82 85 // I/O Forwards 83 86 //============================================================================================= 84 #include <time.hfa>85 86 // Some forward declarations87 #include <errno.h>88 #include <unistd.h>89 87 90 88 extern "C" { 91 #include <asm/types.h>92 #include <sys/socket.h>93 #include <sys/syscall.h>94 95 89 #if defined(CFA_HAVE_PREADV2) 96 90 struct iovec; 97 extern ssize_t preadv2 (int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);91 extern ssize_t preadv2 (int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags); 98 92 #endif 99 93 #if defined(CFA_HAVE_PWRITEV2) 100 94 struct iovec; 101 extern ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);95 extern ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags); 102 96 #endif 103 97 … … 114 108 struct msghdr; 115 109 struct sockaddr; 116 extern ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); 117 extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); 118 extern ssize_t send(int sockfd, const void *buf, size_t len, int flags); 119 extern ssize_t recv(int sockfd, void *buf, size_t len, int flags); 120 extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); 121 extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 110 extern ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags); 111 extern ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags); 112 extern ssize_t send(int sockfd, const void * buf, size_t len, int flags); 113 extern ssize_t recv(int sockfd, void * buf, size_t len, int flags); 122 114 123 115 extern int fallocate(int fd, int mode, off_t offset, off_t len); 124 116 extern int posix_fadvise(int fd, off_t offset, off_t len, int advice); 125 extern int madvise(void * addr, size_t length, int advice);126 127 extern int openat(int dirfd, const char * pathname, int flags, mode_t mode);117 extern int madvise(void * addr, size_t length, int advice); 118 119 extern int openat(int dirfd, const char * pathname, int flags, mode_t mode); 128 120 extern int close(int fd); 129 121 130 extern ssize_t read (int fd, void * buf, size_t count);122 extern ssize_t read (int fd, void * buf, size_t count); 131 123 132 124 struct epoll_event; 133 extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event);134 135 extern ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags);125 extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event); 126 127 extern ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags); 136 128 extern ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags); 137 129 } … … 232 224 calls = [ 233 225 # CFA_HAVE_IORING_OP_READV 234 Call('READV', 'ssize_t preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {226 Call('READV', 'ssize_t preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', { 235 227 'fd' : 'fd', 228 'addr': '(typeof(sqe->addr))iov', 229 'len' : 'iovcnt', 236 230 'off' : 'offset', 237 'addr': '(uintptr_t)iov', 238 'len' : 'iovcnt', 231 'rw_flags' : 'flags' 239 232 }, define = 'CFA_HAVE_PREADV2'), 240 233 # CFA_HAVE_IORING_OP_WRITEV 241 Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {234 Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', { 242 235 'fd' : 'fd', 236 'addr': '(typeof(sqe->addr))iov', 237 'len' : 'iovcnt', 243 238 'off' : 'offset', 244 'addr': '(uintptr_t)iov', 245 'len' : 'iovcnt' 239 'rw_flags' : 'flags' 246 240 }, define = 'CFA_HAVE_PWRITEV2'), 247 241 # CFA_HAVE_IORING_OP_FSYNC … … 250 244 }), 251 245 # CFA_HAVE_IORING_OP_EPOLL_CTL 252 Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event)', {246 Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event)', { 253 247 'fd': 'epfd', 248 'len': 'op', 254 249 'addr': 'fd', 255 'len': 'op', 256 'off': '(uintptr_t)event' 250 'off': '(typeof(sqe->off))event' 257 251 }), 258 252 # CFA_HAVE_IORING_OP_SYNC_FILE_RANGE … … 264 258 }), 265 259 # CFA_HAVE_IORING_OP_SENDMSG 266 Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags)', {267 'fd': 'sockfd', 268 'addr': '( uintptr_t)(struct msghdr *)msg',260 Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags)', { 261 'fd': 'sockfd', 262 'addr': '(typeof(sqe->addr))(struct msghdr *)msg', 269 263 'len': '1', 270 264 'msg_flags': 'flags' 271 265 }), 272 266 # CFA_HAVE_IORING_OP_RECVMSG 273 Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags)', {274 'fd': 'sockfd', 275 'addr': '( uintptr_t)(struct msghdr *)msg',267 Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags)', { 268 'fd': 'sockfd', 269 'addr': '(typeof(sqe->addr))(struct msghdr *)msg', 276 270 'len': '1', 277 271 'msg_flags': 'flags' 278 272 }), 279 273 # CFA_HAVE_IORING_OP_SEND 280 Call('SEND', 'ssize_t send(int sockfd, const void * buf, size_t len, int flags)', {281 'fd': 'sockfd', 282 'addr': '( uintptr_t)buf',274 Call('SEND', 'ssize_t send(int sockfd, const void * buf, size_t len, int flags)', { 275 'fd': 'sockfd', 276 'addr': '(typeof(sqe->addr))buf', 283 277 'len': 'len', 284 278 'msg_flags': 'flags' 285 279 }), 286 280 # CFA_HAVE_IORING_OP_RECV 287 Call('RECV', 'ssize_t recv(int sockfd, void * buf, size_t len, int flags)', {288 'fd': 'sockfd', 289 'addr': '( uintptr_t)buf',281 Call('RECV', 'ssize_t recv(int sockfd, void * buf, size_t len, int flags)', { 282 'fd': 'sockfd', 283 'addr': '(typeof(sqe->addr))buf', 290 284 'len': 'len', 291 285 'msg_flags': 'flags' 292 286 }), 293 287 # CFA_HAVE_IORING_OP_ACCEPT 294 Call('ACCEPT', 'int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)', {295 'fd': 'sockfd', 296 'addr': '( uintptr_t)addr',297 'addr2': '( uintptr_t)addrlen',288 Call('ACCEPT', 'int accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags)', { 289 'fd': 'sockfd', 290 'addr': '(typeof(sqe->addr))&addr', 291 'addr2': '(typeof(sqe->addr2))addrlen', 298 292 'accept_flags': 'flags' 299 293 }), 300 294 # CFA_HAVE_IORING_OP_CONNECT 301 Call('CONNECT', 'int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)', {302 'fd': 'sockfd', 303 'addr': '( uintptr_t)addr',295 Call('CONNECT', 'int connect(int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen)', { 296 'fd': 'sockfd', 297 'addr': '(typeof(sqe->addr))&addr', 304 298 'off': 'addrlen' 305 299 }), … … 307 301 Call('FALLOCATE', 'int fallocate(int fd, int mode, off_t offset, off_t len)', { 308 302 'fd': 'fd', 309 'addr': '(uintptr_t)len',310 303 'len': 'mode', 311 'off': 'offset' 304 'off': 'offset', 305 'addr': 'len' 312 306 }), 313 307 # CFA_HAVE_IORING_OP_FADVISE … … 319 313 }), 320 314 # CFA_HAVE_IORING_OP_MADVISE 321 Call('MADVISE', 'int madvise(void * addr, size_t length, int advice)', {322 'addr': '( uintptr_t)addr',315 Call('MADVISE', 'int madvise(void * addr, size_t length, int advice)', { 316 'addr': '(typeof(sqe->addr))addr', 323 317 'len': 'length', 324 318 'fadvise_advice': 'advice' 325 319 }), 326 320 # CFA_HAVE_IORING_OP_OPENAT 327 Call('OPENAT', 'int openat(int dirfd, const char * pathname, int flags, mode_t mode)', {321 Call('OPENAT', 'int openat(int dirfd, const char * pathname, int flags, mode_t mode)', { 328 322 'fd': 'dirfd', 329 'addr': '( uintptr_t)pathname',330 ' len': 'mode',331 ' open_flags': 'flags;'323 'addr': '(typeof(sqe->addr))pathname', 324 'open_flags': 'flags;', 325 'len': 'mode' 332 326 }), 333 327 # CFA_HAVE_IORING_OP_OPENAT2 334 Call('OPENAT2', 'int openat2(int dirfd, const char * pathname, struct open_how * how, size_t size)', {328 Call('OPENAT2', 'int openat2(int dirfd, const char * pathname, struct open_how * how, size_t size)', { 335 329 'fd': 'dirfd', 336 'addr': ' pathname',337 ' len': 'sizeof(*how)',338 ' off': '(uintptr_t)how',330 'addr': '(typeof(sqe->addr))pathname', 331 'off': '(typeof(sqe->off))how', 332 'len': 'sizeof(*how)' 339 333 }, define = 'CFA_HAVE_OPENAT2'), 340 334 # CFA_HAVE_IORING_OP_CLOSE … … 343 337 }), 344 338 # CFA_HAVE_IORING_OP_STATX 345 Call('STATX', 'int statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx *statxbuf)', {339 Call('STATX', 'int statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf)', { 346 340 'fd': 'dirfd', 347 ' off': '(uintptr_t)statxbuf',348 ' addr': 'pathname',341 'addr': '(typeof(sqe->addr))pathname', 342 'statx_flags': 'flags', 349 343 'len': 'mask', 350 ' statx_flags': 'flags'344 'off': '(typeof(sqe->off))statxbuf' 351 345 }, define = 'CFA_HAVE_STATX'), 352 346 # CFA_HAVE_IORING_OP_READ 353 347 Call('READ', 'ssize_t read(int fd, void * buf, size_t count)', { 354 348 'fd': 'fd', 355 'addr': '( uintptr_t)buf',349 'addr': '(typeof(sqe->addr))buf', 356 350 'len': 'count' 357 351 }), … … 359 353 Call('WRITE', 'ssize_t write(int fd, void * buf, size_t count)', { 360 354 'fd': 'fd', 361 'addr': '( uintptr_t)buf',355 'addr': '(typeof(sqe->addr))buf', 362 356 'len': 'count' 363 357 }), 364 358 # CFA_HAVE_IORING_OP_SPLICE 365 Call('SPLICE', 'ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags)', {359 Call('SPLICE', 'ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags)', { 366 360 'splice_fd_in': 'fd_in', 367 'splice_off_in': 'off_in ? ( __u64)*off_in : (__u64)-1',361 'splice_off_in': 'off_in ? (typeof(sqe->splice_off_in))*off_in : (typeof(sqe->splice_off_in))-1', 368 362 'fd': 'fd_out', 369 'off': 'off_out ? ( __u64)*off_out : (__u64)-1',363 'off': 'off_out ? (typeof(sqe->off))*off_out : (typeof(sqe->off))-1', 370 364 'len': 'len', 371 365 'splice_flags': 'flags' -
libcfa/src/concurrency/io/setup.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #if defined(__CFA_DEBUG__) … … 216 215 217 216 // completion queue 218 cq. lock= false;217 cq.try_lock = false; 219 218 cq.id = MAX; 220 219 cq.ts = rdtscl(); -
libcfa/src/concurrency/io/types.hfa
r34b4268 r24d6572 37 37 //----------------------------------------------------------------------- 38 38 // Ring Data structure 39 struct __sub_ring_t { 39 // represent the io_uring submission ring which contains operations that will be sent to io_uring for processing 40 struct __sub_ring_t { 41 // lock needed because remote processors might need to flush the instance 42 __spinlock_t lock; 43 40 44 struct { 41 45 // Head and tail of the ring (associated with array) … … 58 62 59 63 // number of sqes to submit on next system call. 60 __u32 to_submit;64 volatile __u32 to_submit; 61 65 62 66 // number of entries and mask to go with it … … 77 81 void * ring_ptr; 78 82 size_t ring_sz; 79 }; 80 83 84 // for debug purposes, whether or not the last flush was due to a arbiter flush 85 bool last_external; 86 }; 87 88 // represent the io_uring completion ring which contains operations that have completed 81 89 struct __cmp_ring_t { 82 volatile bool lock; 83 90 // needed because remote processors can help drain the buffer 91 volatile bool try_lock; 92 93 // id of the ring, used for the helping/topology algorithms 84 94 unsigned id; 85 95 96 // timestamp from last time it was drained 86 97 unsigned long long ts; 87 98 … … 105 116 }; 106 117 118 // struct representing an io operation that still needs processing 119 // actual operations are expected to inherit from this 107 120 struct __outstanding_io { 121 // intrusive link fields 108 122 inline Colable; 123 124 // primitive on which to block until the io is processed 109 125 oneshot waitctx; 110 126 }; 111 127 static inline __outstanding_io *& Next( __outstanding_io * n ) { return (__outstanding_io *)Next( (Colable *)n ); } 112 128 129 // queue of operations that are outstanding 113 130 struct __outstanding_io_queue { 131 // spinlock for protection 132 // TODO: changing to a lock that blocks, I haven't examined whether it should be a kernel or user lock 114 133 __spinlock_t lock; 134 135 // the actual queue 115 136 Queue(__outstanding_io) queue; 137 138 // volatile used to avoid the need for taking the lock if it's empty 116 139 volatile bool empty; 117 140 }; 118 141 142 // struct representing an operation that was submitted 119 143 struct __external_io { 144 // inherits from outstanding io 120 145 inline __outstanding_io; 146 147 // pointer and count to an array of ids to be submitted 121 148 __u32 * idxs; 122 149 __u32 have; 150 151 // whether or not these can be accumulated before flushing the buffer 123 152 bool lazy; 124 153 }; 125 154 126 155 // complete io_context, contains all the data for io submission and completion 127 156 struct __attribute__((aligned(64))) io_context$ { 157 // arbiter, used in cases where threads for migrated at unfortunate moments 128 158 io_arbiter$ * arbiter; 159 160 // which prcessor the context is tied to 129 161 struct processor * proc; 130 162 163 // queue of io submissions that haven't beeen processed. 131 164 __outstanding_io_queue ext_sq; 132 165 166 // io_uring ring data structures 133 167 struct __sub_ring_t sq; 134 168 struct __cmp_ring_t cq; 169 170 // flag the io_uring rings where created with 135 171 __u32 ring_flags; 172 173 // file descriptor that identifies the io_uring instance 136 174 int fd; 137 175 }; 138 176 177 // short hand to check when the io_context was last processed (io drained) 139 178 static inline unsigned long long ts(io_context$ *& this) { 140 179 const __u32 head = *this->cq.head; 141 180 const __u32 tail = *this->cq.tail; 142 181 182 // if there is no pending completions, just pretend it's infinetely recent 143 183 if(head == tail) return ULLONG_MAX; 144 184 … … 146 186 } 147 187 188 // structure represeting allocations that couldn't succeed locally 148 189 struct __pending_alloc { 190 // inherit from outstanding io 149 191 inline __outstanding_io; 192 193 // array and size of the desired allocation 150 194 __u32 * idxs; 151 195 __u32 want; 196 197 // output param, the context the io was allocated from 152 198 io_context$ * ctx; 153 199 }; 154 200 201 // arbiter that handles cases where the context tied to the local processor is unable to satisfy the io 155 202 monitor __attribute__((aligned(64))) io_arbiter$ { 203 // contains a queue of io for pending allocations 156 204 __outstanding_io_queue pending; 157 205 }; -
libcfa/src/concurrency/iofwd.hfa
r34b4268 r24d6572 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu Apr 23 17:31:00 2020 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 13 23:54:57 2023 13 // Update Count : 1 14 14 // 15 15 … … 17 17 18 18 #include <unistd.h> 19 #include <sys/socket.h> 20 19 21 extern "C" { 20 22 #include <asm/types.h> … … 48 50 typedef __off64_t off64_t; 49 51 50 struct cluster;51 struct io_context$;52 53 struct iovec;54 struct msghdr;55 struct sockaddr;56 struct statx;57 52 struct epoll_event; 58 59 struct io_uring_sqe;60 53 61 54 //----------------------------------------------------------------------- … … 88 81 // synchronous calls 89 82 #if defined(CFA_HAVE_PREADV2) 90 extern ssize_t cfa_preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);83 extern ssize_t cfa_preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 91 84 #endif 92 85 #if defined(CFA_HAVE_PWRITEV2) 93 extern ssize_t cfa_pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);86 extern ssize_t cfa_pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 94 87 #endif 95 88 extern int cfa_fsync(int fd, __u64 submit_flags); 96 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags);89 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags); 97 90 extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, __u64 submit_flags); 98 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags);99 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr * msg, int flags, __u64 submit_flags);100 extern ssize_t cfa_send(int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags);101 extern ssize_t cfa_recv(int sockfd, void * buf, size_t len, int flags, __u64 submit_flags);102 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, __u64 submit_flags);103 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, __u64 submit_flags);91 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags); 92 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr * msg, int flags, __u64 submit_flags); 93 extern ssize_t cfa_send(int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags); 94 extern ssize_t cfa_recv(int sockfd, void * buf, size_t len, int flags, __u64 submit_flags); 95 extern int cfa_accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags, __u64 submit_flags); 96 extern int cfa_connect(int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen, __u64 submit_flags); 104 97 extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, __u64 submit_flags); 105 98 extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, __u64 submit_flags); 106 extern int cfa_madvise(void * addr, size_t length, int advice, __u64 submit_flags);107 extern int cfa_openat(int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags);99 extern int cfa_madvise(void * addr, size_t length, int advice, __u64 submit_flags); 100 extern int cfa_openat(int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags); 108 101 #if defined(CFA_HAVE_OPENAT2) 109 extern int cfa_openat2(int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);102 extern int cfa_openat2(int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags); 110 103 #endif 111 104 extern int cfa_close(int fd, __u64 submit_flags); 112 105 #if defined(CFA_HAVE_STATX) 113 extern int cfa_statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags);106 extern int cfa_statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf, __u64 submit_flags); 114 107 #endif 115 108 extern ssize_t cfa_read(int fd, void * buf, size_t count, __u64 submit_flags); 116 109 extern ssize_t cfa_write(int fd, void * buf, size_t count, __u64 submit_flags); 117 extern ssize_t cfa_splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags, __u64 submit_flags);110 extern ssize_t cfa_splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags, __u64 submit_flags); 118 111 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags); 119 112 … … 121 114 // asynchronous calls 122 115 #if defined(CFA_HAVE_PREADV2) 123 extern void async_preadv2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);116 extern void async_preadv2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 124 117 #endif 125 118 #if defined(CFA_HAVE_PWRITEV2) 126 extern void async_pwritev2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);119 extern void async_pwritev2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 127 120 #endif 128 121 extern void async_fsync(io_future_t & future, int fd, __u64 submit_flags); 129 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags);122 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags); 130 123 extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, __u64 submit_flags); 131 extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags);132 extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr * msg, int flags, __u64 submit_flags);133 extern void async_send(io_future_t & future, int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags);134 extern void async_recv(io_future_t & future, int sockfd, void * buf, size_t len, int flags, __u64 submit_flags);135 extern void async_accept4(io_future_t & future, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, __u64 submit_flags);136 extern void async_connect(io_future_t & future, int sockfd, const struct sockaddr *addr, socklen_t addrlen, __u64 submit_flags);124 extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags); 125 extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr * msg, int flags, __u64 submit_flags); 126 extern void async_send(io_future_t & future, int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags); 127 extern void async_recv(io_future_t & future, int sockfd, void * buf, size_t len, int flags, __u64 submit_flags); 128 extern void async_accept4(io_future_t & future, int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags, __u64 submit_flags); 129 extern void async_connect(io_future_t & future, int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen, __u64 submit_flags); 137 130 extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, __u64 submit_flags); 138 131 extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, __u64 submit_flags); 139 extern void async_madvise(io_future_t & future, void * addr, size_t length, int advice, __u64 submit_flags);140 extern void async_openat(io_future_t & future, int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags);132 extern void async_madvise(io_future_t & future, void * addr, size_t length, int advice, __u64 submit_flags); 133 extern void async_openat(io_future_t & future, int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags); 141 134 #if defined(CFA_HAVE_OPENAT2) 142 extern void async_openat2(io_future_t & future, int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);135 extern void async_openat2(io_future_t & future, int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags); 143 136 #endif 144 137 extern void async_close(io_future_t & future, int fd, __u64 submit_flags); 145 138 #if defined(CFA_HAVE_STATX) 146 extern void async_statx(io_future_t & future, int dirfd, const char * pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags);139 extern void async_statx(io_future_t & future, int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf, __u64 submit_flags); 147 140 #endif 148 141 void async_read(io_future_t & future, int fd, void * buf, size_t count, __u64 submit_flags); 149 142 extern void async_write(io_future_t & future, int fd, void * buf, size_t count, __u64 submit_flags); 150 extern void async_splice(io_future_t & future, int fd_in, __off64_t * off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags, __u64 submit_flags);143 extern void async_splice(io_future_t & future, int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags, __u64 submit_flags); 151 144 extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags); 152 145 -
libcfa/src/concurrency/kernel.cfa
r34b4268 r24d6572 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Nov 30 18:14:08 202213 // Update Count : 7 612 // Last Modified On : Mon Jan 9 08:42:05 2023 13 // Update Count : 77 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__ … … 258 257 __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this); 259 258 } 259 260 __cfa_io_flush( this ); 261 __cfa_io_drain( this ); 260 262 261 263 post( this->terminated ); -
libcfa/src/concurrency/kernel/cluster.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #include "bits/defs.hfa" … … 69 68 return max_cores_l; 70 69 } 71 72 #if defined(CFA_HAVE_LINUX_LIBRSEQ)73 // No forward declaration needed74 #define __kernel_rseq_register rseq_register_current_thread75 #define __kernel_rseq_unregister rseq_unregister_current_thread76 #elif defined(CFA_HAVE_LINUX_RSEQ_H)77 static void __kernel_raw_rseq_register (void);78 static void __kernel_raw_rseq_unregister(void);79 80 #define __kernel_rseq_register __kernel_raw_rseq_register81 #define __kernel_rseq_unregister __kernel_raw_rseq_unregister82 #else83 // No forward declaration needed84 // No initialization needed85 static inline void noop(void) {}86 87 #define __kernel_rseq_register noop88 #define __kernel_rseq_unregister noop89 #endif90 70 91 71 //======================================================================= … … 111 91 // Lock-Free registering/unregistering of threads 112 92 unsigned register_proc_id( void ) with(__scheduler_lock.lock) { 113 __kernel_rseq_register();114 115 93 bool * handle = (bool *)&kernelTLS().sched_lock; 116 94 … … 162 140 163 141 __atomic_store_n(cell, 0p, __ATOMIC_RELEASE); 164 165 __kernel_rseq_unregister();166 142 } 167 143 … … 505 481 /* paranoid */ verify( mock_head(this) == this.l.prev ); 506 482 } 507 508 #if defined(CFA_HAVE_LINUX_LIBRSEQ)509 // No definition needed510 #elif defined(CFA_HAVE_LINUX_RSEQ_H)511 512 #if defined( __x86_64 ) || defined( __i386 )513 #define RSEQ_SIG 0x53053053514 #elif defined( __ARM_ARCH )515 #ifdef __ARMEB__516 #define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */517 #else518 #define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */519 #endif520 #endif521 522 extern void __disable_interrupts_hard();523 extern void __enable_interrupts_hard();524 525 static void __kernel_raw_rseq_register (void) {526 /* paranoid */ verify( __cfaabi_rseq.cpu_id == RSEQ_CPU_ID_UNINITIALIZED );527 528 // int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), 0, (sigset_t *)0p, _NSIG / 8);529 int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), 0, RSEQ_SIG);530 if(ret != 0) {531 int e = errno;532 switch(e) {533 case EINVAL: abort("KERNEL ERROR: rseq register invalid argument");534 case ENOSYS: abort("KERNEL ERROR: rseq register no supported");535 case EFAULT: abort("KERNEL ERROR: rseq register with invalid argument");536 case EBUSY : abort("KERNEL ERROR: rseq register already registered");537 case EPERM : abort("KERNEL ERROR: rseq register sig argument on unregistration does not match the signature received on registration");538 default: abort("KERNEL ERROR: rseq register unexpected return %d", e);539 }540 }541 }542 543 static void __kernel_raw_rseq_unregister(void) {544 /* paranoid */ verify( __cfaabi_rseq.cpu_id >= 0 );545 546 // int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, (sigset_t *)0p, _NSIG / 8);547 int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, RSEQ_SIG);548 if(ret != 0) {549 int e = errno;550 switch(e) {551 case EINVAL: abort("KERNEL ERROR: rseq unregister invalid argument");552 case ENOSYS: abort("KERNEL ERROR: rseq unregister no supported");553 case EFAULT: abort("KERNEL ERROR: rseq unregister with invalid argument");554 case EBUSY : abort("KERNEL ERROR: rseq unregister already registered");555 case EPERM : abort("KERNEL ERROR: rseq unregister sig argument on unregistration does not match the signature received on registration");556 default: abort("KERNEL ERROR: rseq unregisteunexpected return %d", e);557 }558 }559 }560 #else561 // No definition needed562 #endif -
libcfa/src/concurrency/kernel/cluster.hfa
r34b4268 r24d6572 40 40 41 41 // convert to log2 scale but using double 42 static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2( intsc); }42 static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2((__readyQ_avg_t)intsc); } 43 43 44 44 #define warn_large_before warnf( !strict || old_avg < 35.0, "Suspiciously large previous average: %'lf, %'" PRId64 "ms \n", old_avg, program()`ms ) … … 146 146 } 147 147 148 static struct {149 constunsigned readyq;150 constunsigned io;148 const static struct { 149 unsigned readyq; 150 unsigned io; 151 151 } __shard_factor = { 2, 1 }; 152 152 -
libcfa/src/concurrency/kernel/private.hfa
r34b4268 r24d6572 10 10 // Created On : Mon Feb 13 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Aug 12 08:21:33 202013 // Update Count : 912 // Last Modified On : Thu Mar 2 16:04:46 2023 13 // Update Count : 11 14 14 // 15 15 … … 29 29 30 30 extern "C" { 31 #if defined(CFA_HAVE_LINUX_LIBRSEQ)32 #include <rseq/rseq.h>33 #elif defined(CFA_HAVE_LINUX_RSEQ_H)34 #include <linux/rseq.h>35 #else36 #ifndef _GNU_SOURCE37 #error kernel/private requires gnu_source38 #endif39 31 #include <sched.h> 40 #endif41 32 } 42 33 … … 110 101 // Hardware 111 102 112 #if defined(CFA_HAVE_LINUX_LIBRSEQ)113 // No data needed114 #elif defined(CFA_HAVE_LINUX_RSEQ_H)115 extern "Cforall" {116 extern __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq;117 }118 #else119 // No data needed120 #endif121 122 103 static inline int __kernel_getcpu() { 123 104 /* paranoid */ verify( ! __preemption_enabled() ); 124 #if defined(CFA_HAVE_LINUX_LIBRSEQ)125 return rseq_current_cpu();126 #elif defined(CFA_HAVE_LINUX_RSEQ_H)127 int r = __cfaabi_rseq.cpu_id;128 /* paranoid */ verify( r >= 0 );129 return r;130 #else131 105 return sched_getcpu(); 132 #endif133 106 } 134 107 -
libcfa/src/concurrency/kernel/startup.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__ 20 19 21 20 // C Includes 22 #include <errno.h> // errno21 #include <errno.h> // errno 23 22 #include <signal.h> 24 #include <string.h> // strerror25 #include <unistd.h> // sysconf26 23 #include <string.h> // strerror 24 #include <unistd.h> 25 #include <limits.h> // PTHREAD_STACK_MIN 27 26 extern "C" { 28 #include <limits.h> // PTHREAD_STACK_MIN 29 #include <unistd.h> // syscall 30 #include <sys/eventfd.h> // eventfd 31 #include <sys/mman.h> // mprotect 32 #include <sys/resource.h> // getrlimit 27 #include <sys/eventfd.h> // eventfd 28 #include <sys/mman.h> // mprotect 29 #include <sys/resource.h> // getrlimit 33 30 } 34 31 … … 36 33 #include "kernel/private.hfa" 37 34 #include "iofwd.hfa" 38 #include "startup.hfa" // STARTUP_PRIORITY_XXX35 #include "startup.hfa" // STARTUP_PRIORITY_XXX 39 36 #include "limits.hfa" 40 37 #include "math.hfa" … … 150 147 __scheduler_RWLock_t __scheduler_lock @= { 0 }; 151 148 152 #if defined(CFA_HAVE_LINUX_LIBRSEQ)153 // No data needed154 #elif defined(CFA_HAVE_LINUX_RSEQ_H)155 extern "Cforall" {156 __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq @= {157 .cpu_id : RSEQ_CPU_ID_UNINITIALIZED,158 };159 }160 #else161 // No data needed162 #endif163 164 149 //----------------------------------------------------------------------------- 165 150 // Struct to steal stack -
libcfa/src/concurrency/locks.cfa
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // locks. hfa -- LIBCFATHREAD7 // locks.cfa -- LIBCFATHREAD 8 8 // Runtime locks that used with the runtime thread system. 9 9 // … … 16 16 17 17 #define __cforall_thread__ 18 #define _GNU_SOURCE19 18 20 19 #include "locks.hfa" … … 80 79 // lock is held by some other thread 81 80 if ( owner != 0p && owner != thrd ) { 82 insert_last( blocked_threads, *thrd ); 81 select_node node; 82 insert_last( blocked_threads, node ); 83 83 wait_count++; 84 84 unlock( lock ); 85 85 park( ); 86 } 87 // multi acquisition lock is held by current thread 88 else if ( owner == thrd && multi_acquisition ) { 86 return; 87 } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread 89 88 recursion_count++; 90 unlock( lock ); 91 } 92 // lock isn't held 93 else { 89 } else { // lock isn't held 94 90 owner = thrd; 95 91 recursion_count = 1; 96 unlock( lock );97 } 92 } 93 unlock( lock ); 98 94 } 99 95 … … 118 114 } 119 115 120 static void pop_and_set_new_owner( blocking_lock & this ) with( this ) { 121 thread$ * t = &try_pop_front( blocked_threads ); 122 owner = t; 123 recursion_count = ( t ? 1 : 0 ); 124 if ( t ) wait_count--; 125 unpark( t ); 116 static inline void pop_node( blocking_lock & this ) with( this ) { 117 __handle_waituntil_OR( blocked_threads ); 118 select_node * node = &try_pop_front( blocked_threads ); 119 if ( node ) { 120 wait_count--; 121 owner = node->blocked_thread; 122 recursion_count = 1; 123 // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread ); 124 wake_one( blocked_threads, *node ); 125 } else { 126 owner = 0p; 127 recursion_count = 0; 128 } 126 129 } 127 130 … … 135 138 recursion_count--; 136 139 if ( recursion_count == 0 ) { 137 pop_ and_set_new_owner( this );140 pop_node( this ); 138 141 } 139 142 unlock( lock ); … … 148 151 // lock held 149 152 if ( owner != 0p ) { 150 insert_last( blocked_threads, * t);153 insert_last( blocked_threads, *(select_node *)t->link_node ); 151 154 wait_count++; 152 unlock( lock );153 155 } 154 156 // lock not held … … 157 159 recursion_count = 1; 158 160 unpark( t ); 159 unlock( lock );160 } 161 } 162 163 size_t on_wait( blocking_lock & this ) with( this ) {161 } 162 unlock( lock ); 163 } 164 165 size_t on_wait( blocking_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) with( this ) { 164 166 lock( lock __cfaabi_dbg_ctx2 ); 165 167 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); … … 168 170 size_t ret = recursion_count; 169 171 170 pop_and_set_new_owner( this ); 172 pop_node( this ); 173 174 select_node node; 175 active_thread()->link_node = (void *)&node; 171 176 unlock( lock ); 177 178 pre_park_then_park( pp_fn, pp_datum ); 179 172 180 return ret; 173 181 } … … 176 184 recursion_count = recursion; 177 185 } 186 187 // waituntil() support 188 bool register_select( blocking_lock & this, select_node & node ) with(this) { 189 lock( lock __cfaabi_dbg_ctx2 ); 190 thread$ * thrd = active_thread(); 191 192 // single acquisition lock is held by current thread 193 /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this ); 194 195 if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case 196 if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering 197 unlock( lock ); 198 return false; 199 } 200 } 201 202 // lock is held by some other thread 203 if ( owner != 0p && owner != thrd ) { 204 insert_last( blocked_threads, node ); 205 wait_count++; 206 unlock( lock ); 207 return false; 208 } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread 209 recursion_count++; 210 } else { // lock isn't held 211 owner = thrd; 212 recursion_count = 1; 213 } 214 215 if ( node.park_counter ) __make_select_node_available( node ); 216 unlock( lock ); 217 return true; 218 } 219 220 bool unregister_select( blocking_lock & this, select_node & node ) with(this) { 221 lock( lock __cfaabi_dbg_ctx2 ); 222 if ( node`isListed ) { 223 remove( node ); 224 wait_count--; 225 unlock( lock ); 226 return false; 227 } 228 229 if ( owner == active_thread() ) { 230 /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to unlock owner lock %p in waituntil unregister, which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count ); 231 // if recursion count is zero release lock and set new owner if one is waiting 232 recursion_count--; 233 if ( recursion_count == 0 ) { 234 pop_node( this ); 235 } 236 } 237 unlock( lock ); 238 return false; 239 } 240 241 void on_selected( blocking_lock & this, select_node & node ) {} 178 242 179 243 //----------------------------------------------------------------------------- … … 312 376 int counter( condition_variable(L) & this ) with(this) { return count; } 313 377 314 static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {378 static void enqueue_thread( condition_variable(L) & this, info_thread(L) * i ) with(this) { 315 379 // add info_thread to waiting queue 316 380 insert_last( blocked_threads, *i ); 317 381 count++; 318 size_t recursion_count = 0; 319 if (i->lock) { 320 // if lock was passed get recursion count to reset to after waking thread 321 recursion_count = on_wait( *i->lock ); 322 } 323 return recursion_count; 324 } 382 } 383 384 static size_t block_and_get_recursion( info_thread(L) & i, __cfa_pre_park pp_fn, void * pp_datum ) { 385 size_t recursion_count = 0; 386 if ( i.lock ) // if lock was passed get recursion count to reset to after waking thread 387 recursion_count = on_wait( *i.lock, pp_fn, pp_datum ); // this call blocks 388 else 389 pre_park_then_park( pp_fn, pp_datum ); 390 return recursion_count; 391 } 392 static size_t block_and_get_recursion( info_thread(L) & i ) { return block_and_get_recursion( i, pre_park_noop, 0p ); } 325 393 326 394 // helper for wait()'s' with no timeout 327 395 static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) { 328 396 lock( lock __cfaabi_dbg_ctx2 ); 329 size_t recursion_count = queue_and_get_recursion(this, &i);397 enqueue_thread( this, &i ); 330 398 unlock( lock ); 331 399 332 400 // blocks here 333 park();401 size_t recursion_count = block_and_get_recursion( i ); 334 402 335 403 // resets recursion count here after waking 336 if ( i.lock) on_wakeup(*i.lock, recursion_count);404 if ( i.lock ) on_wakeup( *i.lock, recursion_count ); 337 405 } 338 406 … … 341 409 queue_info_thread( this, i ); 342 410 411 static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); } 412 343 413 // helper for wait()'s' with a timeout 344 414 static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 345 415 lock( lock __cfaabi_dbg_ctx2 ); 346 size_t recursion_count = queue_and_get_recursion(this, &info);416 enqueue_thread( this, &info ); 347 417 alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 348 418 unlock( lock ); 349 419 350 // registers alarm outside cond lock to avoid deadlock 351 register_self( &node_wrap.alarm_node ); 352 353 // blocks here 354 park(); 420 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock 421 size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) ); 422 // park(); 355 423 356 424 // unregisters alarm so it doesn't go off if this happens first … … 358 426 359 427 // resets recursion count here after waking 360 if ( info.lock) on_wakeup(*info.lock, recursion_count);428 if ( info.lock ) on_wakeup( *info.lock, recursion_count ); 361 429 } 362 430 … … 418 486 info_thread( L ) i = { active_thread(), info, &l }; 419 487 insert_last( blocked_threads, i ); 420 size_t recursion_count = on_wait( *i.lock );421 park( );488 size_t recursion_count = on_wait( *i.lock, pre_park_noop, 0p ); // blocks here 489 // park( ); 422 490 on_wakeup(*i.lock, recursion_count); 423 491 } … … 460 528 bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; } 461 529 462 static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) {463 // add info_thread to waiting queue464 insert_last( blocked_threads, *i );465 size_t recursion_count = 0;466 recursion_count = on_wait( *i->lock );467 return recursion_count;468 }469 470 530 static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 471 531 lock( lock __cfaabi_dbg_ctx2 ); 472 size_t recursion_count = queue_and_get_recursion(this, &info);532 insert_last( blocked_threads, info ); 473 533 pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 474 534 unlock( lock ); 475 535 476 // registers alarm outside cond lock to avoid deadlock 477 register_self( &node_wrap.alarm_node ); 478 479 // blocks here 480 park(); 481 482 // unregisters alarm so it doesn't go off if this happens first 536 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock 537 size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) ); 538 539 // unregisters alarm so it doesn't go off if signal happens first 483 540 unregister_self( &node_wrap.alarm_node ); 484 541 485 542 // resets recursion count here after waking 486 if ( info.lock) on_wakeup(*info.lock, recursion_count);543 if ( info.lock ) on_wakeup( *info.lock, recursion_count ); 487 544 } 488 545 … … 494 551 lock( lock __cfaabi_dbg_ctx2 ); 495 552 info_thread( L ) i = { active_thread(), info, &l }; 496 size_t recursion_count = queue_and_get_recursion(this, &i); 497 unlock( lock ); 498 park( ); 499 on_wakeup(*i.lock, recursion_count); 553 insert_last( blocked_threads, i ); 554 unlock( lock ); 555 556 // blocks here 557 size_t recursion_count = block_and_get_recursion( i ); 558 559 on_wakeup( *i.lock, recursion_count ); 500 560 } 501 561 … … 585 645 return thrd != 0p; 586 646 } 647 -
libcfa/src/concurrency/locks.hfa
r34b4268 r24d6572 30 30 #include "time.hfa" 31 31 32 #include "select.hfa" 33 32 34 #include <fstream.hfa> 33 34 35 35 36 // futex headers … … 38 39 #include <unistd.h> 39 40 40 // undef to make a number of the locks not reacquire upon waking from a condlock 41 #define REACQ 1 41 typedef void (*__cfa_pre_park)( void * ); 42 43 static inline void pre_park_noop( void * ) {} 44 45 //----------------------------------------------------------------------------- 46 // is_blocking_lock 47 forall( L & | sized(L) ) 48 trait is_blocking_lock { 49 // For synchronization locks to use when acquiring 50 void on_notify( L &, struct thread$ * ); 51 52 // For synchronization locks to use when releasing 53 size_t on_wait( L &, __cfa_pre_park pp_fn, void * pp_datum ); 54 55 // to set recursion count after getting signalled; 56 void on_wakeup( L &, size_t recursion ); 57 }; 58 59 static inline void pre_park_then_park( __cfa_pre_park pp_fn, void * pp_datum ) { 60 pp_fn( pp_datum ); 61 park(); 62 } 63 64 // macros for default routine impls for is_blocking_lock trait that do not wait-morph 65 66 #define DEFAULT_ON_NOTIFY( lock_type ) \ 67 static inline void on_notify( lock_type & this, thread$ * t ){ unpark(t); } 68 69 #define DEFAULT_ON_WAIT( lock_type ) \ 70 static inline size_t on_wait( lock_type & this, __cfa_pre_park pp_fn, void * pp_datum ) { \ 71 unlock( this ); \ 72 pre_park_then_park( pp_fn, pp_datum ); \ 73 return 0; \ 74 } 75 76 // on_wakeup impl if lock should be reacquired after waking up 77 #define DEFAULT_ON_WAKEUP_REACQ( lock_type ) \ 78 static inline void on_wakeup( lock_type & this, size_t recursion ) { lock( this ); } 79 80 // on_wakeup impl if lock will not be reacquired after waking up 81 #define DEFAULT_ON_WAKEUP_NO_REACQ( lock_type ) \ 82 static inline void on_wakeup( lock_type & this, size_t recursion ) {} 83 84 42 85 43 86 //----------------------------------------------------------------------------- … … 66 109 static inline bool try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); } 67 110 static inline void unlock ( single_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 68 static inline size_t on_wait ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this); }111 static inline size_t on_wait ( single_acquisition_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); } 69 112 static inline void on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 70 113 static inline void on_notify( single_acquisition_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); } 114 static inline bool register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 115 static inline bool unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 116 static inline void on_selected( single_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } 71 117 72 118 //---------- … … 80 126 static inline bool try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); } 81 127 static inline void unlock ( owner_lock & this ) { unlock ( (blocking_lock &)this ); } 82 static inline size_t on_wait ( owner_lock & this ) { return on_wait ( (blocking_lock &)this); }128 static inline size_t on_wait ( owner_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); } 83 129 static inline void on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 84 130 static inline void on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); } 131 static inline bool register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 132 static inline bool unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 133 static inline void on_selected( owner_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); } 85 134 86 135 //----------------------------------------------------------------------------- … … 127 176 static inline void ?{}(mcs_spin_node & this) { this.next = 0p; this.locked = true; } 128 177 129 static inline mcs_spin_node * volatile & ?`next ( mcs_spin_node * node ) {130 return node->next;131 }132 133 178 struct mcs_spin_lock { 134 179 mcs_spin_queue queue; … … 136 181 137 182 static inline void lock(mcs_spin_lock & l, mcs_spin_node & n) { 183 n.locked = true; 138 184 mcs_spin_node * prev = __atomic_exchange_n(&l.queue.tail, &n, __ATOMIC_SEQ_CST); 139 n.locked = true; 140 if(prev == 0p) return; 185 if( prev == 0p ) return; 141 186 prev->next = &n; 142 while( __atomic_load_n(&n.locked, __ATOMIC_RELAXED)) Pause();187 while( __atomic_load_n(&n.locked, __ATOMIC_RELAXED) ) Pause(); 143 188 } 144 189 … … 146 191 mcs_spin_node * n_ptr = &n; 147 192 if (__atomic_compare_exchange_n(&l.queue.tail, &n_ptr, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return; 148 while (__atomic_load_n(&n.next, __ATOMIC_RELAXED) == 0p) {}193 while (__atomic_load_n(&n.next, __ATOMIC_RELAXED) == 0p) Pause(); 149 194 n.next->locked = false; 150 195 } … … 153 198 // futex_mutex 154 199 155 // - No cond var support156 200 // - Kernel thd blocking alternative to the spinlock 157 201 // - No ownership (will deadlock on reacq) 202 // - no reacq on wakeup 158 203 struct futex_mutex { 159 204 // lock state any state other than UNLOCKED is locked … … 169 214 } 170 215 171 static inline void ?{}( futex_mutex & this ) with(this) { val = 0; }172 173 static inline bool internal_try_lock( futex_mutex & this, int & compare_val) with(this) {216 static inline void ?{}( futex_mutex & this ) with(this) { val = 0; } 217 218 static inline bool internal_try_lock( futex_mutex & this, int & compare_val) with(this) { 174 219 return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); 175 220 } 176 221 177 static inline int internal_exchange( futex_mutex & this) with(this) {222 static inline int internal_exchange( futex_mutex & this ) with(this) { 178 223 return __atomic_exchange_n((int*)&val, 2, __ATOMIC_ACQUIRE); 179 224 } 180 225 181 226 // if this is called recursively IT WILL DEADLOCK!!!!! 182 static inline void lock( futex_mutex & this) with(this) {227 static inline void lock( futex_mutex & this ) with(this) { 183 228 int state; 184 229 185 186 // // linear backoff omitted for now 187 // for( int spin = 4; spin < 1024; spin += spin) { 188 // state = 0; 189 // // if unlocked, lock and return 190 // if (internal_try_lock(this, state)) return; 191 // if (2 == state) break; 192 // for (int i = 0; i < spin; i++) Pause(); 193 // } 194 195 // no contention try to acquire 196 if (internal_try_lock(this, state)) return; 230 for( int spin = 4; spin < 1024; spin += spin) { 231 state = 0; 232 // if unlocked, lock and return 233 if (internal_try_lock(this, state)) return; 234 if (2 == state) break; 235 for (int i = 0; i < spin; i++) Pause(); 236 } 197 237 198 238 // if not in contended state, set to be in contended state … … 207 247 208 248 static inline void unlock(futex_mutex & this) with(this) { 209 // if uncontended do atomic eunlock and then return210 if (__atomic_fetch_sub(&val, 1, __ATOMIC_RELEASE) == 1) return; // TODO: try acq/rel 249 // if uncontended do atomic unlock and then return 250 if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return; 211 251 212 252 // otherwise threads are blocked so we must wake one 213 __atomic_store_n((int *)&val, 0, __ATOMIC_RELEASE);214 253 futex((int *)&val, FUTEX_WAKE, 1); 215 254 } 216 255 217 static inline void on_notify( futex_mutex & f, thread$ * t){ unpark(t); } 218 static inline size_t on_wait( futex_mutex & f ) {unlock(f); return 0;} 219 220 // to set recursion count after getting signalled; 221 static inline void on_wakeup( futex_mutex & f, size_t recursion ) {} 222 223 //----------------------------------------------------------------------------- 224 // CLH Spinlock 225 // - No recursive acquisition 226 // - Needs to be released by owner 227 228 struct clh_lock { 229 volatile bool * volatile tail; 230 }; 231 232 static inline void ?{}( clh_lock & this ) { this.tail = malloc(); *this.tail = true; } 233 static inline void ^?{}( clh_lock & this ) { free(this.tail); } 234 235 static inline void lock(clh_lock & l) { 236 thread$ * curr_thd = active_thread(); 237 *(curr_thd->clh_node) = false; 238 volatile bool * prev = __atomic_exchange_n((bool **)(&l.tail), (bool *)(curr_thd->clh_node), __ATOMIC_SEQ_CST); 239 while(!__atomic_load_n(prev, __ATOMIC_ACQUIRE)) Pause(); 240 curr_thd->clh_prev = prev; 241 } 242 243 static inline void unlock(clh_lock & l) { 244 thread$ * curr_thd = active_thread(); 245 __atomic_store_n(curr_thd->clh_node, true, __ATOMIC_RELEASE); 246 curr_thd->clh_node = curr_thd->clh_prev; 247 } 248 249 static inline void on_notify(clh_lock & this, struct thread$ * t ) { unpark(t); } 250 static inline size_t on_wait(clh_lock & this) { unlock(this); return 0; } 251 static inline void on_wakeup(clh_lock & this, size_t recursion ) { 252 #ifdef REACQ 253 lock(this); 254 #endif 255 } 256 257 258 //----------------------------------------------------------------------------- 259 // Linear backoff Spinlock 260 struct linear_backoff_then_block_lock { 256 DEFAULT_ON_NOTIFY( futex_mutex ) 257 DEFAULT_ON_WAIT( futex_mutex ) 258 DEFAULT_ON_WAKEUP_NO_REACQ( futex_mutex ) 259 260 //----------------------------------------------------------------------------- 261 // go_mutex 262 263 // - Kernel thd blocking alternative to the spinlock 264 // - No ownership (will deadlock on reacq) 265 // - Golang's flavour of mutex 266 // - Impl taken from Golang: src/runtime/lock_futex.go 267 struct go_mutex { 268 // lock state any state other than UNLOCKED is locked 269 // enum LockState { UNLOCKED = 0, LOCKED = 1, SLEEPING = 2 }; 270 271 // stores a lock state 272 int val; 273 }; 274 static inline void ?{}( go_mutex & this ) with(this) { val = 0; } 275 // static inline void ?{}( go_mutex & this, go_mutex this2 ) = void; // these don't compile correctly at the moment so they should be omitted 276 // static inline void ?=?( go_mutex & this, go_mutex this2 ) = void; 277 278 static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) { 279 return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, new_val, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); 280 } 281 282 static inline int internal_exchange(go_mutex & this, int swap ) with(this) { 283 return __atomic_exchange_n((int*)&val, swap, __ATOMIC_ACQUIRE); 284 } 285 286 // if this is called recursively IT WILL DEADLOCK!!!!! 287 static inline void lock( go_mutex & this ) with( this ) { 288 int state, init_state; 289 290 // speculative grab 291 state = internal_exchange(this, 1); 292 if ( !state ) return; // state == 0 293 init_state = state; 294 for (;;) { 295 for( int i = 0; i < 4; i++ ) { 296 while( !val ) { // lock unlocked 297 state = 0; 298 if ( internal_try_lock( this, state, init_state ) ) return; 299 } 300 for (int i = 0; i < 30; i++) Pause(); 301 } 302 303 while( !val ) { // lock unlocked 304 state = 0; 305 if ( internal_try_lock( this, state, init_state ) ) return; 306 } 307 sched_yield(); 308 309 // if not in contended state, set to be in contended state 310 state = internal_exchange( this, 2 ); 311 if ( !state ) return; // state == 0 312 init_state = 2; 313 futex( (int*)&val, FUTEX_WAIT, 2 ); // if val is not 2 this returns with EWOULDBLOCK 314 } 315 } 316 317 static inline void unlock( go_mutex & this ) with(this) { 318 // if uncontended do atomic unlock and then return 319 if ( __atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1 ) return; 320 321 // otherwise threads are blocked so we must wake one 322 futex( (int *)&val, FUTEX_WAKE, 1 ); 323 } 324 325 DEFAULT_ON_NOTIFY( go_mutex ) 326 DEFAULT_ON_WAIT( go_mutex ) 327 DEFAULT_ON_WAKEUP_NO_REACQ( go_mutex ) 328 329 //----------------------------------------------------------------------------- 330 // Exponential backoff then block lock 331 struct exp_backoff_then_block_lock { 261 332 // Spin lock used for mutual exclusion 262 333 __spinlock_t spinlock; … … 269 340 }; 270 341 271 static inline void ?{}( linear_backoff_then_block_lock & this ) {342 static inline void ?{}( exp_backoff_then_block_lock & this ) { 272 343 this.spinlock{}; 273 344 this.blocked_threads{}; 274 345 this.lock_value = 0; 275 346 } 276 static inline void ^?{}( linear_backoff_then_block_lock & this ) {} 277 // static inline void ?{}( linear_backoff_then_block_lock & this, linear_backoff_then_block_lock this2 ) = void; 278 // static inline void ?=?( linear_backoff_then_block_lock & this, linear_backoff_then_block_lock this2 ) = void; 279 280 static inline bool internal_try_lock(linear_backoff_then_block_lock & this, size_t & compare_val) with(this) { 281 if (__atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { 282 return true; 283 } 284 return false; 285 } 286 287 static inline bool try_lock(linear_backoff_then_block_lock & this) { size_t compare_val = 0; return internal_try_lock(this, compare_val); } 288 289 static inline bool try_lock_contention(linear_backoff_then_block_lock & this) with(this) { 290 if (__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE) == 0) { 291 return true; 292 } 293 return false; 294 } 295 296 static inline bool block(linear_backoff_then_block_lock & this) with(this) { 297 lock( spinlock __cfaabi_dbg_ctx2 ); // TODO change to lockfree queue (MPSC) 298 if (lock_value != 2) { 299 unlock( spinlock ); 300 return true; 301 } 302 insert_last( blocked_threads, *active_thread() ); 303 unlock( spinlock ); 347 static inline void ?{}( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void; 348 static inline void ?=?( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void; 349 350 static inline void ^?{}( exp_backoff_then_block_lock & this ){} 351 352 static inline bool internal_try_lock( exp_backoff_then_block_lock & this, size_t & compare_val ) with(this) { 353 return __atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); 354 } 355 356 static inline bool try_lock( exp_backoff_then_block_lock & this ) { size_t compare_val = 0; return internal_try_lock( this, compare_val ); } 357 358 static inline bool try_lock_contention( exp_backoff_then_block_lock & this ) with(this) { 359 return !__atomic_exchange_n( &lock_value, 2, __ATOMIC_ACQUIRE ); 360 } 361 362 static inline bool block( exp_backoff_then_block_lock & this ) with(this) { 363 lock( spinlock __cfaabi_dbg_ctx2 ); 364 if (__atomic_load_n( &lock_value, __ATOMIC_SEQ_CST) != 2) { 365 unlock( spinlock ); 366 return true; 367 } 368 insert_last( blocked_threads, *active_thread() ); 369 unlock( spinlock ); 304 370 park( ); 305 371 return true; 306 372 } 307 373 308 static inline void lock( linear_backoff_then_block_lock & this) with(this) {374 static inline void lock( exp_backoff_then_block_lock & this ) with(this) { 309 375 size_t compare_val = 0; 310 376 int spin = 4; 377 311 378 // linear backoff 312 379 for( ;; ) { … … 324 391 } 325 392 326 static inline void unlock( linear_backoff_then_block_lock & this) with(this) {393 static inline void unlock( exp_backoff_then_block_lock & this ) with(this) { 327 394 if (__atomic_exchange_n(&lock_value, 0, __ATOMIC_RELEASE) == 1) return; 328 lock( spinlock __cfaabi_dbg_ctx2 ); 329 thread$ * t = &try_pop_front( blocked_threads ); 330 unlock( spinlock ); 331 unpark( t ); 332 } 333 334 static inline void on_notify(linear_backoff_then_block_lock & this, struct thread$ * t ) { unpark(t); } 335 static inline size_t on_wait(linear_backoff_then_block_lock & this) { unlock(this); return 0; } 336 static inline void on_wakeup(linear_backoff_then_block_lock & this, size_t recursion ) { 337 #ifdef REACQ 338 lock(this); 339 #endif 340 } 395 lock( spinlock __cfaabi_dbg_ctx2 ); 396 thread$ * t = &try_pop_front( blocked_threads ); 397 unlock( spinlock ); 398 unpark( t ); 399 } 400 401 DEFAULT_ON_NOTIFY( exp_backoff_then_block_lock ) 402 DEFAULT_ON_WAIT( exp_backoff_then_block_lock ) 403 DEFAULT_ON_WAKEUP_REACQ( exp_backoff_then_block_lock ) 341 404 342 405 //----------------------------------------------------------------------------- … … 368 431 369 432 // if this is called recursively IT WILL DEADLOCK!!!!! 370 static inline void lock( fast_block_lock & this) with(this) {433 static inline void lock( fast_block_lock & this ) with(this) { 371 434 lock( lock __cfaabi_dbg_ctx2 ); 372 435 if ( held ) { … … 380 443 } 381 444 382 static inline void unlock( fast_block_lock & this) with(this) {445 static inline void unlock( fast_block_lock & this ) with(this) { 383 446 lock( lock __cfaabi_dbg_ctx2 ); 384 447 /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this ); … … 389 452 } 390 453 391 static inline void on_notify(fast_block_lock & this, struct thread$ * t ) with(this) { 392 #ifdef REACQ 393 lock( lock __cfaabi_dbg_ctx2 ); 394 insert_last( blocked_threads, *t ); 395 unlock( lock ); 396 #else 397 unpark(t); 398 #endif 399 } 400 static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; } 401 static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { } 454 static inline void on_notify( fast_block_lock & this, struct thread$ * t ) with(this) { 455 lock( lock __cfaabi_dbg_ctx2 ); 456 insert_last( blocked_threads, *t ); 457 unlock( lock ); 458 } 459 DEFAULT_ON_WAIT( fast_block_lock ) 460 DEFAULT_ON_WAKEUP_NO_REACQ( fast_block_lock ) 402 461 403 462 //----------------------------------------------------------------------------- … … 410 469 struct simple_owner_lock { 411 470 // List of blocked threads 412 dlist( thread$) blocked_threads;471 dlist( select_node ) blocked_threads; 413 472 414 473 // Spin lock used for mutual exclusion … … 431 490 static inline void ?=?( simple_owner_lock & this, simple_owner_lock this2 ) = void; 432 491 433 static inline void lock( simple_owner_lock & this) with(this) {434 if ( owner == active_thread()) {492 static inline void lock( simple_owner_lock & this ) with(this) { 493 if ( owner == active_thread() ) { 435 494 recursion_count++; 436 495 return; … … 438 497 lock( lock __cfaabi_dbg_ctx2 ); 439 498 440 if (owner != 0p) { 441 insert_last( blocked_threads, *active_thread() ); 499 if ( owner != 0p ) { 500 select_node node; 501 insert_last( blocked_threads, node ); 442 502 unlock( lock ); 443 503 park( ); … … 449 509 } 450 510 451 // TODO: fix duplicate def issue and bring this back 452 // void pop_and_set_new_owner( simple_owner_lock & this ) with( this ) { 453 // thread$ * t = &try_pop_front( blocked_threads ); 454 // owner = t; 455 // recursion_count = ( t ? 1 : 0 ); 456 // unpark( t ); 457 // } 458 459 static inline void unlock(simple_owner_lock & this) with(this) { 511 static inline void pop_node( simple_owner_lock & this ) with(this) { 512 __handle_waituntil_OR( blocked_threads ); 513 select_node * node = &try_pop_front( blocked_threads ); 514 if ( node ) { 515 owner = node->blocked_thread; 516 recursion_count = 1; 517 // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread ); 518 wake_one( blocked_threads, *node ); 519 } else { 520 owner = 0p; 521 recursion_count = 0; 522 } 523 } 524 525 static inline void unlock( simple_owner_lock & this ) with(this) { 460 526 lock( lock __cfaabi_dbg_ctx2 ); 461 527 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); … … 464 530 recursion_count--; 465 531 if ( recursion_count == 0 ) { 466 // pop_and_set_new_owner( this ); 467 thread$ * t = &try_pop_front( blocked_threads ); 468 owner = t; 469 recursion_count = ( t ? 1 : 0 ); 470 unpark( t ); 532 pop_node( this ); 471 533 } 472 534 unlock( lock ); 473 535 } 474 536 475 static inline void on_notify( simple_owner_lock & this, structthread$ * t ) with(this) {537 static inline void on_notify( simple_owner_lock & this, thread$ * t ) with(this) { 476 538 lock( lock __cfaabi_dbg_ctx2 ); 477 539 // lock held 478 540 if ( owner != 0p ) { 479 insert_last( blocked_threads, * t);541 insert_last( blocked_threads, *(select_node *)t->link_node ); 480 542 } 481 543 // lock not held … … 488 550 } 489 551 490 static inline size_t on_wait( simple_owner_lock & this) with(this) {552 static inline size_t on_wait( simple_owner_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) with(this) { 491 553 lock( lock __cfaabi_dbg_ctx2 ); 492 554 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); … … 495 557 size_t ret = recursion_count; 496 558 497 // pop_and_set_new_owner( this ); 498 499 thread$ * t = &try_pop_front( blocked_threads ); 500 owner = t; 501 recursion_count = ( t ? 1 : 0 ); 502 unpark( t ); 503 559 pop_node( this ); 560 561 select_node node; 562 active_thread()->link_node = (void *)&node; 504 563 unlock( lock ); 564 565 pre_park_then_park( pp_fn, pp_datum ); 566 505 567 return ret; 506 568 } 507 569 508 static inline void on_wakeup(simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; } 570 static inline void on_wakeup( simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; } 571 572 // waituntil() support 573 static inline bool register_select( simple_owner_lock & this, select_node & node ) with(this) { 574 lock( lock __cfaabi_dbg_ctx2 ); 575 576 // check if we can complete operation. If so race to establish winner in special OR case 577 if ( !node.park_counter && ( owner == active_thread() || owner == 0p ) ) { 578 if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering 579 unlock( lock ); 580 return false; 581 } 582 } 583 584 if ( owner == active_thread() ) { 585 recursion_count++; 586 if ( node.park_counter ) __make_select_node_available( node ); 587 unlock( lock ); 588 return true; 589 } 590 591 if ( owner != 0p ) { 592 insert_last( blocked_threads, node ); 593 unlock( lock ); 594 return false; 595 } 596 597 owner = active_thread(); 598 recursion_count = 1; 599 600 if ( node.park_counter ) __make_select_node_available( node ); 601 unlock( lock ); 602 return true; 603 } 604 605 static inline bool unregister_select( simple_owner_lock & this, select_node & node ) with(this) { 606 lock( lock __cfaabi_dbg_ctx2 ); 607 if ( node`isListed ) { 608 remove( node ); 609 unlock( lock ); 610 return false; 611 } 612 613 if ( owner == active_thread() ) { 614 recursion_count--; 615 if ( recursion_count == 0 ) { 616 pop_node( this ); 617 } 618 } 619 unlock( lock ); 620 return false; 621 } 622 623 static inline void on_selected( simple_owner_lock & this, select_node & node ) {} 624 509 625 510 626 //----------------------------------------------------------------------------- … … 521 637 // flag showing if lock is held 522 638 volatile bool held; 523 524 #ifdef __CFA_DEBUG__525 // for deadlock detection526 struct thread$ * owner;527 #endif528 639 }; 529 640 … … 536 647 static inline void ?=?( spin_queue_lock & this, spin_queue_lock this2 ) = void; 537 648 538 // if this is called recursively IT WILL DEADLOCK! !!!!539 static inline void lock( spin_queue_lock & this) with(this) {649 // if this is called recursively IT WILL DEADLOCK! 650 static inline void lock( spin_queue_lock & this ) with(this) { 540 651 mcs_spin_node node; 541 652 lock( lock, node ); … … 545 656 } 546 657 547 static inline void unlock( spin_queue_lock & this) with(this) {658 static inline void unlock( spin_queue_lock & this ) with(this) { 548 659 __atomic_store_n(&held, false, __ATOMIC_RELEASE); 549 660 } 550 661 551 static inline void on_notify(spin_queue_lock & this, struct thread$ * t ) { 552 unpark(t); 553 } 554 static inline size_t on_wait(spin_queue_lock & this) { unlock(this); return 0; } 555 static inline void on_wakeup(spin_queue_lock & this, size_t recursion ) { 556 #ifdef REACQ 557 lock(this); 558 #endif 559 } 560 662 DEFAULT_ON_NOTIFY( spin_queue_lock ) 663 DEFAULT_ON_WAIT( spin_queue_lock ) 664 DEFAULT_ON_WAKEUP_REACQ( spin_queue_lock ) 561 665 562 666 //----------------------------------------------------------------------------- … … 584 688 585 689 // if this is called recursively IT WILL DEADLOCK!!!!! 586 static inline void lock( mcs_block_spin_lock & this) with(this) {690 static inline void lock( mcs_block_spin_lock & this ) with(this) { 587 691 mcs_node node; 588 692 lock( lock, node ); … … 596 700 } 597 701 598 static inline void on_notify(mcs_block_spin_lock & this, struct thread$ * t ) { unpark(t); } 599 static inline size_t on_wait(mcs_block_spin_lock & this) { unlock(this); return 0; } 600 static inline void on_wakeup(mcs_block_spin_lock & this, size_t recursion ) { 601 #ifdef REACQ 602 lock(this); 603 #endif 604 } 702 DEFAULT_ON_NOTIFY( mcs_block_spin_lock ) 703 DEFAULT_ON_WAIT( mcs_block_spin_lock ) 704 DEFAULT_ON_WAKEUP_REACQ( mcs_block_spin_lock ) 605 705 606 706 //----------------------------------------------------------------------------- … … 628 728 629 729 // if this is called recursively IT WILL DEADLOCK!!!!! 630 static inline void lock( block_spin_lock & this) with(this) {730 static inline void lock( block_spin_lock & this ) with(this) { 631 731 lock( lock ); 632 732 while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause(); … … 635 735 } 636 736 637 static inline void unlock( block_spin_lock & this) with(this) {737 static inline void unlock( block_spin_lock & this ) with(this) { 638 738 __atomic_store_n(&held, false, __ATOMIC_RELEASE); 639 739 } 640 740 641 static inline void on_notify(block_spin_lock & this, struct thread$ * t ) with(this.lock) { 642 #ifdef REACQ 741 static inline void on_notify( block_spin_lock & this, struct thread$ * t ) with(this.lock) { 643 742 // first we acquire internal fast_block_lock 644 743 lock( lock __cfaabi_dbg_ctx2 ); … … 652 751 unlock( lock ); 653 752 654 #endif655 753 unpark(t); 656 657 } 658 static inline size_t on_wait(block_spin_lock & this) { unlock(this); return 0; } 659 static inline void on_wakeup(block_spin_lock & this, size_t recursion ) with(this) { 660 #ifdef REACQ 754 } 755 DEFAULT_ON_WAIT( block_spin_lock ) 756 static inline void on_wakeup( block_spin_lock & this, size_t recursion ) with(this) { 661 757 // now we acquire the entire block_spin_lock upon waking up 662 758 while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause(); 663 759 __atomic_store_n(&held, true, __ATOMIC_RELEASE); 664 760 unlock( lock ); // Now we release the internal fast_spin_lock 665 #endif 666 } 667 668 //----------------------------------------------------------------------------- 669 // is_blocking_lock 670 trait is_blocking_lock(L & | sized(L)) { 671 // For synchronization locks to use when acquiring 672 void on_notify( L &, struct thread$ * ); 673 674 // For synchronization locks to use when releasing 675 size_t on_wait( L & ); 676 677 // to set recursion count after getting signalled; 678 void on_wakeup( L &, size_t recursion ); 679 }; 761 } 680 762 681 763 //----------------------------------------------------------------------------- … … 685 767 forall(L & | is_blocking_lock(L)) { 686 768 struct info_thread; 687 688 // // for use by sequence689 // info_thread(L) *& Back( info_thread(L) * this );690 // info_thread(L) *& Next( info_thread(L) * this );691 769 } 692 770 -
libcfa/src/concurrency/monitor.cfa
r34b4268 r24d6572 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 4 07:55:14 201913 // Update Count : 1 012 // Last Modified On : Sun Feb 19 17:00:59 2023 13 // Update Count : 12 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #include "monitor.hfa" -
libcfa/src/concurrency/monitor.hfa
r34b4268 r24d6572 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 4 07:55:32 201913 // Update Count : 1 112 // Last Modified On : Thu Feb 2 11:29:21 2023 13 // Update Count : 12 14 14 // 15 15 … … 22 22 #include "stdlib.hfa" 23 23 24 trait is_monitor(T &) { 24 forall( T & ) 25 trait is_monitor { 25 26 monitor$ * get_monitor( T & ); 26 27 void ^?{}( T & mutex ); -
libcfa/src/concurrency/mutex.cfa
r34b4268 r24d6572 12 12 // Created On : Fri May 25 01:37:11 2018 13 13 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Wed Dec 4 09:16:39 201915 // Update Count : 114 // Last Modified On : Sun Feb 19 17:01:36 2023 15 // Update Count : 3 16 16 // 17 17 18 18 #define __cforall_thread__ 19 #define _GNU_SOURCE20 19 21 20 #include "mutex.hfa" -
libcfa/src/concurrency/mutex.hfa
r34b4268 r24d6572 12 12 // Created On : Fri May 25 01:24:09 2018 13 13 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Wed Dec 4 09:16:53 201915 // Update Count : 114 // Last Modified On : Thu Feb 2 11:46:08 2023 15 // Update Count : 2 16 16 // 17 17 … … 70 70 void unlock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead"))); 71 71 72 trait is_lock(L & | sized(L)) { 72 forall( L & | sized(L) ) 73 trait is_lock { 73 74 void lock (L &); 74 75 void unlock(L &); -
libcfa/src/concurrency/mutex_stmt.hfa
r34b4268 r24d6572 1 #pragma once 2 1 3 #include "bits/algorithm.hfa" 2 4 #include "bits/defs.hfa" … … 4 6 //----------------------------------------------------------------------------- 5 7 // is_lock 6 trait is_lock(L & | sized(L)) { 8 forall(L & | sized(L)) 9 trait is_lock { 7 10 // For acquiring a lock 8 11 void lock( L & ); … … 11 14 void unlock( L & ); 12 15 }; 13 14 16 15 17 struct __mutex_stmt_lock_guard { … … 24 26 // Sort locks based on address 25 27 __libcfa_small_sort(this.lockarr, count); 26 27 // acquire locks in order28 // for ( size_t i = 0; i < count; i++ ) {29 // lock(*this.lockarr[i]);30 // }31 }32 33 static inline void ^?{}( __mutex_stmt_lock_guard & this ) with(this) {34 // for ( size_t i = count; i > 0; i-- ) {35 // unlock(*lockarr[i - 1]);36 // }37 28 } 38 29 39 30 forall(L & | is_lock(L)) { 40 41 struct scoped_lock { 42 L * internal_lock; 43 }; 44 45 static inline void ?{}( scoped_lock(L) & this, L & internal_lock ) { 46 this.internal_lock = &internal_lock; 47 lock(internal_lock); 48 } 49 50 static inline void ^?{}( scoped_lock(L) & this ) with(this) { 51 unlock(*internal_lock); 52 } 53 54 static inline void * __get_mutexstmt_lock_ptr( L & this ) { 55 return &this; 56 } 57 58 static inline L __get_mutexstmt_lock_type( L & this ); 59 60 static inline L __get_mutexstmt_lock_type( L * this ); 31 static inline void * __get_mutexstmt_lock_ptr( L & this ) { return &this; } 32 static inline L __get_mutexstmt_lock_type( L & this ) {} 33 static inline L __get_mutexstmt_lock_type( L * this ) {} 61 34 } -
libcfa/src/concurrency/preemption.cfa
r34b4268 r24d6572 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 17 11:18:57 202213 // Update Count : 5912 // Last Modified On : Mon Jan 9 08:42:59 2023 13 // Update Count : 60 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 // #define __CFA_DEBUG_PRINT_PREEMPTION__ … … 118 117 __cfadbg_print_buffer_decl( preemption, " KERNEL: preemption tick %lu\n", currtime.tn); 119 118 Duration period = node->period; 120 if( period == 0 ) {119 if( period == 0 ) { 121 120 node->set = false; // Node is one-shot, just mark it as not pending 122 121 } -
libcfa/src/concurrency/pthread.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #include <signal.h> … … 35 34 struct pthread_values{ 36 35 inline Seqable; 37 void * value;36 void * value; 38 37 bool in_use; 39 38 }; … … 51 50 struct pthread_keys { 52 51 bool in_use; 53 void (* destructor)( void * );52 void (* destructor)( void * ); 54 53 Sequence(pthread_values) threads; 55 54 }; 56 55 57 static void ?{}(pthread_keys& k) {56 static void ?{}(pthread_keys& k) { 58 57 k.threads{}; 59 58 } … … 62 61 static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16))); 63 62 64 static void init_pthread_storage() {65 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++){63 static void init_pthread_storage() { 64 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) { 66 65 cfa_pthread_keys_storage[i]{}; 67 66 } … … 96 95 97 96 /* condvar helper routines */ 98 static void init(pthread_cond_t * pcond){97 static void init(pthread_cond_t * pcond) { 99 98 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 100 cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t*)pcond;99 cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t *)pcond; 101 100 ?{}(*_cond); 102 101 } 103 102 104 static cfa2pthr_cond_var_t * get(pthread_cond_t* pcond){103 static cfa2pthr_cond_var_t * get(pthread_cond_t * pcond) { 105 104 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 106 return (cfa2pthr_cond_var_t *)pcond;107 } 108 109 static void destroy(pthread_cond_t * cond){105 return (cfa2pthr_cond_var_t *)pcond; 106 } 107 108 static void destroy(pthread_cond_t * cond) { 110 109 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 111 110 ^?{}(*get(cond)); … … 116 115 117 116 /* mutex helper routines */ 118 static void mutex_check(pthread_mutex_t * t){117 static void mutex_check(pthread_mutex_t * t) { 119 118 // Use double check to improve performance. 120 119 // Check is safe on x86; volatile prevents compiler reordering 121 volatile pthread_mutex_t * const mutex_ = t;120 volatile pthread_mutex_t * const mutex_ = t; 122 121 123 122 // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h … … 136 135 137 136 138 static void init(pthread_mutex_t * plock){137 static void init(pthread_mutex_t * plock) { 139 138 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 140 simple_owner_lock * _lock = (simple_owner_lock*)plock;139 simple_owner_lock * _lock = (simple_owner_lock *)plock; 141 140 ?{}(*_lock); 142 141 } 143 142 144 static simple_owner_lock * get(pthread_mutex_t* plock){143 static simple_owner_lock * get(pthread_mutex_t * plock) { 145 144 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 146 return (simple_owner_lock *)plock;147 } 148 149 static void destroy(pthread_mutex_t * plock){145 return (simple_owner_lock *)plock; 146 } 147 148 static void destroy(pthread_mutex_t * plock) { 150 149 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 151 150 ^?{}(*get(plock)); … … 153 152 154 153 //######################### Attr helpers ######################### 155 struct cfaPthread_attr_t {// thread attributes154 typedef struct cfaPthread_attr_t { // thread attributes 156 155 int contentionscope; 157 156 int detachstate; 158 157 size_t stacksize; 159 void * stackaddr;158 void * stackaddr; 160 159 int policy; 161 160 int inheritsched; 162 161 struct sched_param param; 163 } typedefcfaPthread_attr_t;164 165 static const cfaPthread_attr_t default_attrs {162 } cfaPthread_attr_t; 163 164 static const cfaPthread_attr_t default_attrs { 166 165 0, 167 166 0, 168 (size_t)65000,169 (void *)NULL,167 65_000, 168 NULL, 170 169 0, 171 170 0, … … 173 172 }; 174 173 175 static cfaPthread_attr_t * get(const pthread_attr_t* attr){176 static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t), "sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");177 return (cfaPthread_attr_t *)attr;174 static cfaPthread_attr_t * get(const pthread_attr_t * attr) { 175 static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t), "sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)"); 176 return (cfaPthread_attr_t *)attr; 178 177 } 179 178 … … 190 189 191 190 // pthreads return value 192 void * joinval;191 void * joinval; 193 192 194 193 // pthread attributes 195 194 pthread_attr_t pthread_attr; 196 195 197 void *(* start_routine)(void *);198 void * start_arg;196 void *(* start_routine)(void *); 197 void * start_arg; 199 198 200 199 // thread local data 201 pthread_values * pthreadData;200 pthread_values * pthreadData; 202 201 203 202 // flag used for tryjoin … … 207 206 /* thread part routines */ 208 207 // cfaPthread entry point 209 void main(cfaPthread & _thread) with(_thread){210 joinval = start_routine(start_arg);208 void main(cfaPthread & _thread) with(_thread) { 209 joinval = start_routine(start_arg); 211 210 isTerminated = true; 212 211 } 213 212 214 static cfaPthread * lookup( pthread_t p ){215 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *),"sizeof(pthread_t) < sizeof(cfaPthread*)");216 return (cfaPthread *)p;217 } 218 219 static void pthread_deletespecific_( pthread_values * values ) { // see uMachContext::invokeTask220 pthread_values * value;221 pthread_keys * key;213 static cfaPthread * lookup( pthread_t p ) { 214 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *),"sizeof(pthread_t) < sizeof(cfaPthread *)"); 215 return (cfaPthread *)p; 216 } 217 218 static void pthread_deletespecific_( pthread_values * values ) { // see uMachContext::invokeTask 219 pthread_values * value; 220 pthread_keys * key; 222 221 bool destcalled = true; 223 if (values != NULL) {222 if (values != NULL) { 224 223 for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) { 225 224 destcalled = false; 226 225 lock(key_lock); 227 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++){226 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) { 228 227 // for each valid key 229 if ( values[i].in_use) {228 if ( values[i].in_use) { 230 229 value = &values[i]; 231 230 key = &cfa_pthread_keys[i]; … … 234 233 // if a key value has a non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, 235 234 // the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument. 236 if (value->value != NULL && key->destructor != NULL) {235 if (value->value != NULL && key->destructor != NULL) { 237 236 unlock(key_lock); 238 237 key->destructor(value->value); // run destructor … … 249 248 } 250 249 251 static void ^?{}(cfaPthread & mutex t) {250 static void ^?{}(cfaPthread & mutex t) { 252 251 // delete pthread local storage 253 252 pthread_values * values = t.pthreadData; … … 255 254 } 256 255 257 static void ?{}(cfaPthread & t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {258 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread*)");256 static void ?{}(cfaPthread & t, pthread_t * _thread, const pthread_attr_t * _attr,void *(* start_routine)(void *), void * arg) { 257 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread *)"); 259 258 260 259 // set up user thread stackSize … … 278 277 //######################### Pthread Attrs ######################### 279 278 280 int pthread_attr_init(pthread_attr_t * attr) libcfa_public __THROW {281 cfaPthread_attr_t * _attr = get(attr);279 int pthread_attr_init(pthread_attr_t * attr) libcfa_public __THROW { 280 cfaPthread_attr_t * _attr = get(attr); 282 281 ?{}(*_attr, default_attrs); 283 282 return 0; 284 283 } 285 int pthread_attr_destroy(pthread_attr_t * attr) libcfa_public __THROW {284 int pthread_attr_destroy(pthread_attr_t * attr) libcfa_public __THROW { 286 285 ^?{}(*get(attr)); 287 286 return 0; 288 287 } 289 288 290 int pthread_attr_setscope( pthread_attr_t * attr, int contentionscope ) libcfa_public __THROW {289 int pthread_attr_setscope( pthread_attr_t * attr, int contentionscope ) libcfa_public __THROW { 291 290 get( attr )->contentionscope = contentionscope; 292 291 return 0; 293 292 } // pthread_attr_setscope 294 293 295 int pthread_attr_getscope( const pthread_attr_t * attr, int *contentionscope ) libcfa_public __THROW {294 int pthread_attr_getscope( const pthread_attr_t * attr, int * contentionscope ) libcfa_public __THROW { 296 295 *contentionscope = get( attr )->contentionscope; 297 296 return 0; 298 297 } // pthread_attr_getscope 299 298 300 int pthread_attr_setdetachstate( pthread_attr_t * attr, int detachstate ) libcfa_public __THROW {299 int pthread_attr_setdetachstate( pthread_attr_t * attr, int detachstate ) libcfa_public __THROW { 301 300 get( attr )->detachstate = detachstate; 302 301 return 0; 303 302 } // pthread_attr_setdetachstate 304 303 305 int pthread_attr_getdetachstate( const pthread_attr_t * attr, int *detachstate ) libcfa_public __THROW {304 int pthread_attr_getdetachstate( const pthread_attr_t * attr, int * detachstate ) libcfa_public __THROW { 306 305 *detachstate = get( attr )->detachstate; 307 306 return 0; 308 307 } // pthread_attr_getdetachstate 309 308 310 int pthread_attr_setstacksize( pthread_attr_t * attr, size_t stacksize ) libcfa_public __THROW {309 int pthread_attr_setstacksize( pthread_attr_t * attr, size_t stacksize ) libcfa_public __THROW { 311 310 get( attr )->stacksize = stacksize; 312 311 return 0; 313 312 } // pthread_attr_setstacksize 314 313 315 int pthread_attr_getstacksize( const pthread_attr_t * attr, size_t *stacksize ) libcfa_public __THROW {314 int pthread_attr_getstacksize( const pthread_attr_t * attr, size_t * stacksize ) libcfa_public __THROW { 316 315 *stacksize = get( attr )->stacksize; 317 316 return 0; … … 326 325 } // pthread_attr_setguardsize 327 326 328 int pthread_attr_setstackaddr( pthread_attr_t * attr, void *stackaddr ) libcfa_public __THROW {327 int pthread_attr_setstackaddr( pthread_attr_t * attr, void * stackaddr ) libcfa_public __THROW { 329 328 get( attr )->stackaddr = stackaddr; 330 329 return 0; 331 330 } // pthread_attr_setstackaddr 332 331 333 int pthread_attr_getstackaddr( const pthread_attr_t * attr, void **stackaddr ) libcfa_public __THROW {332 int pthread_attr_getstackaddr( const pthread_attr_t * attr, void ** stackaddr ) libcfa_public __THROW { 334 333 *stackaddr = get( attr )->stackaddr; 335 334 return 0; 336 335 } // pthread_attr_getstackaddr 337 336 338 int pthread_attr_setstack( pthread_attr_t * attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW {337 int pthread_attr_setstack( pthread_attr_t * attr, void * stackaddr, size_t stacksize ) libcfa_public __THROW { 339 338 get( attr )->stackaddr = stackaddr; 340 339 get( attr )->stacksize = stacksize; … … 342 341 } // pthread_attr_setstack 343 342 344 int pthread_attr_getstack( const pthread_attr_t * attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW {343 int pthread_attr_getstack( const pthread_attr_t * attr, void ** stackaddr, size_t * stacksize ) libcfa_public __THROW { 345 344 *stackaddr = get( attr )->stackaddr; 346 345 *stacksize = get( attr )->stacksize; … … 351 350 // already running thread threadID. It shall be called on unitialized attr 352 351 // and destroyed with pthread_attr_destroy when no longer needed. 353 int pthread_getattr_np( pthread_t threadID, pthread_attr_t * attr ) libcfa_public __THROW { // GNU extension352 int pthread_getattr_np( pthread_t threadID, pthread_attr_t * attr ) libcfa_public __THROW { // GNU extension 354 353 check_nonnull(attr); 355 354 … … 363 362 //######################### Threads ######################### 364 363 365 int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(* start_routine)(void *), void * arg) libcfa_public __THROW {366 cfaPthread * t = alloc();364 int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(* start_routine)(void *), void * arg) libcfa_public __THROW { 365 cfaPthread * t = alloc(); 367 366 (*t){_thread, attr, start_routine, arg}; 368 367 return 0; 369 368 } 370 369 371 372 int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 370 int pthread_join(pthread_t _thread, void ** value_ptr) libcfa_public __THROW { 373 371 // if thread is invalid 374 372 if (_thread == NULL) return EINVAL; … … 376 374 377 375 // get user thr pointer 378 cfaPthread * p = lookup(_thread);376 cfaPthread * p = lookup(_thread); 379 377 try { 380 378 join(*p); … … 389 387 } 390 388 391 int pthread_tryjoin_np(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {389 int pthread_tryjoin_np(pthread_t _thread, void ** value_ptr) libcfa_public __THROW { 392 390 // if thread is invalid 393 391 if (_thread == NULL) return EINVAL; 394 392 if (_thread == pthread_self()) return EDEADLK; 395 393 396 cfaPthread * p = lookup(_thread);394 cfaPthread * p = lookup(_thread); 397 395 398 396 // thread not finished ? … … 412 410 void pthread_exit(void * status) libcfa_public __THROW { 413 411 pthread_t pid = pthread_self(); 414 cfaPthread * _thread = (cfaPthread*)pid;412 cfaPthread * _thread = (cfaPthread *)pid; 415 413 _thread->joinval = status; // set return value 416 414 _thread->isTerminated = 1; // set terminated flag … … 426 424 //######################### Mutex ######################### 427 425 428 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t * attr) libcfa_public __THROW {426 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t * attr) libcfa_public __THROW { 429 427 check_nonnull(_mutex); 430 428 init(_mutex); … … 435 433 int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW { 436 434 check_nonnull(_mutex); 437 simple_owner_lock * _lock = get(_mutex);438 if (_lock->owner != NULL) {435 simple_owner_lock * _lock = get(_mutex); 436 if (_lock->owner != NULL) { 439 437 return EBUSY; 440 438 } … … 446 444 check_nonnull(_mutex); 447 445 mutex_check(_mutex); 448 simple_owner_lock * _lock = get(_mutex);446 simple_owner_lock * _lock = get(_mutex); 449 447 lock(*_lock); 450 448 return 0; … … 453 451 int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW { 454 452 check_nonnull(_mutex); 455 simple_owner_lock * _lock = get(_mutex);456 if (_lock->owner != active_thread()) {453 simple_owner_lock * _lock = get(_mutex); 454 if (_lock->owner != active_thread()) { 457 455 return EPERM; 458 456 } // current thread does not hold the mutex … … 463 461 int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW { 464 462 check_nonnull(_mutex); 465 simple_owner_lock * _lock = get(_mutex);466 if (_lock->owner != active_thread() && _lock->owner != NULL) {463 simple_owner_lock * _lock = get(_mutex); 464 if (_lock->owner != active_thread() && _lock->owner != NULL) { 467 465 return EBUSY; 468 466 } // if mutex is owned … … 474 472 475 473 /* conditional variable routines */ 476 int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *attr) libcfa_public __THROW {474 int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr) libcfa_public __THROW { 477 475 check_nonnull(cond); 478 476 init(cond); … … 480 478 } //pthread_cond_init 481 479 482 int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t *_mutex) libcfa_public __THROW {480 int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t *_mutex) libcfa_public __THROW { 483 481 check_nonnull(_mutex); 484 482 check_nonnull(cond); … … 494 492 } // pthread_cond_timedwait 495 493 496 int pthread_cond_signal(pthread_cond_t * cond) libcfa_public __THROW {494 int pthread_cond_signal(pthread_cond_t * cond) libcfa_public __THROW { 497 495 check_nonnull(cond); 498 496 return notify_one(*get(cond)); 499 497 } // pthread_cond_signal 500 498 501 int pthread_cond_broadcast(pthread_cond_t * cond) libcfa_public __THROW {499 int pthread_cond_broadcast(pthread_cond_t * cond) libcfa_public __THROW { 502 500 check_nonnull(cond); 503 501 return notify_all(*get(cond)); 504 502 } // pthread_cond_broadcast 505 503 506 int pthread_cond_destroy(pthread_cond_t * cond) libcfa_public __THROW {504 int pthread_cond_destroy(pthread_cond_t * cond) libcfa_public __THROW { 507 505 check_nonnull(cond); 508 506 destroy(cond); … … 514 512 //######################### Local storage ######################### 515 513 516 int pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) libcfa_public __THROW {514 int pthread_once(pthread_once_t * once_control, void (* init_routine)(void)) libcfa_public __THROW { 517 515 static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)"); 518 516 check_nonnull(once_control); … … 527 525 } // pthread_once 528 526 529 int pthread_key_create( pthread_key_t * key, void (*destructor)( void * ) ) libcfa_public __THROW {527 int pthread_key_create( pthread_key_t * key, void (* destructor)( void * ) ) libcfa_public __THROW { 530 528 lock(key_lock); 531 529 for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) { … … 562 560 } // pthread_key_delete 563 561 564 int pthread_setspecific( pthread_key_t key, const void * value ) libcfa_public __THROW {562 int pthread_setspecific( pthread_key_t key, const void * value ) libcfa_public __THROW { 565 563 // get current thread 566 cfaPthread * t = lookup(pthread_self());564 cfaPthread * t = lookup(pthread_self()); 567 565 // if current thread's pthreadData is NULL; initialize it 568 pthread_values * values;569 if (t->pthreadData == NULL) {566 pthread_values * values; 567 if (t->pthreadData == NULL) { 570 568 values = anew( PTHREAD_KEYS_MAX); 571 569 t->pthreadData = values; 572 for ( int i = 0;i < PTHREAD_KEYS_MAX; i++){570 for ( int i = 0;i < PTHREAD_KEYS_MAX; i++ ) { 573 571 t->pthreadData[i].in_use = false; 574 572 } // for … … 593 591 } //pthread_setspecific 594 592 595 void * pthread_getspecific(pthread_key_t key) libcfa_public __THROW {593 void * pthread_getspecific(pthread_key_t key) libcfa_public __THROW { 596 594 if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL; 597 595 598 596 // get current thread 599 cfaPthread * t = lookup(pthread_self());597 cfaPthread * t = lookup(pthread_self()); 600 598 if (t->pthreadData == NULL) return NULL; 601 599 lock(key_lock); 602 pthread_values & entry = ((pthread_values *)t->pthreadData)[key];600 pthread_values & entry = ((pthread_values *)t->pthreadData)[key]; 603 601 if ( ! entry.in_use ) { 604 602 unlock( key_lock ); 605 603 return NULL; 606 604 } // if 607 void * value = entry.value;605 void * value = entry.value; 608 606 unlock(key_lock); 609 607 … … 875 873 //######################### Parallelism ######################### 876 874 877 int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {878 abort( "pthread_setaffinity_np" );879 } // pthread_setaffinity_np880 881 int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {882 abort( "pthread_getaffinity_np" );883 } // pthread_getaffinity_np884 885 int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {886 abort( "pthread_attr_setaffinity_np" );887 } // pthread_attr_setaffinity_np888 889 int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {890 abort( "pthread_attr_getaffinity_np" );891 } // pthread_attr_getaffinity_np875 // int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 876 // abort( "pthread_setaffinity_np" ); 877 // } // pthread_setaffinity_np 878 879 // int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 880 // abort( "pthread_getaffinity_np" ); 881 // } // pthread_getaffinity_np 882 883 // int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 884 // abort( "pthread_attr_setaffinity_np" ); 885 // } // pthread_attr_setaffinity_np 886 887 // int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 888 // abort( "pthread_attr_getaffinity_np" ); 889 // } // pthread_attr_getaffinity_np 892 890 893 891 //######################### Cancellation ######################### … … 906 904 } // pthread_cancel 907 905 908 int pthread_setcancelstate( int state, int * oldstate ) libcfa_public __THROW {906 int pthread_setcancelstate( int state, int * oldstate ) libcfa_public __THROW { 909 907 abort("pthread_setcancelstate not implemented"); 910 908 return 0; 911 909 } // pthread_setcancelstate 912 910 913 int pthread_setcanceltype( int type, int * oldtype ) libcfa_public __THROW {911 int pthread_setcanceltype( int type, int * oldtype ) libcfa_public __THROW { 914 912 abort("pthread_setcanceltype not implemented"); 915 913 return 0; … … 918 916 919 917 #pragma GCC diagnostic pop 920 -
libcfa/src/concurrency/ready_queue.cfa
r34b4268 r24d6572 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 // #define __CFA_DEBUG_PRINT_READY_QUEUE__ -
libcfa/src/concurrency/thread.cfa
r34b4268 r24d6572 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 11 20:56:54 202213 // Update Count : 10 212 // Last Modified On : Mon Jan 9 08:42:33 2023 13 // Update Count : 103 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE18 17 19 18 #include "thread.hfa" … … 54 53 preferred = ready_queue_new_preferred(); 55 54 last_proc = 0p; 55 link_node = 0p; 56 56 PRNG_SET_SEED( random_state, __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl() ); 57 57 #if defined( __CFA_WITH_VERIFY__ ) … … 60 60 #endif 61 61 62 clh_node = malloc( );63 *clh_node = false;64 65 62 doregister(curr_cluster, this); 66 63 monitors{ &self_mon_p, 1, (fptr_t)0 }; … … 71 68 canary = 0xDEADDEADDEADDEADp; 72 69 #endif 73 free(clh_node);74 70 unregister(curr_cluster, this); 75 71 ^self_cor{}; -
libcfa/src/concurrency/thread.hfa
r34b4268 r24d6572 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Nov 22 22:18:34 202213 // Update Count : 3 512 // Last Modified On : Thu Feb 2 11:27:59 2023 13 // Update Count : 37 14 14 // 15 15 … … 27 27 //----------------------------------------------------------------------------- 28 28 // thread trait 29 trait is_thread(T &) { 29 forall( T & ) 30 trait is_thread { 30 31 void ^?{}(T& mutex this); 31 32 void main(T& this); -
libcfa/src/containers/array.hfa
r34b4268 r24d6572 9 9 10 10 11 // 12 // Single-dim array sruct (with explicit packing and atom) 13 // 14 11 // 12 // The `array` macro is the public interface. 13 // It computes the type of a dense (trivially strided) array. 14 // All user-declared objects are dense arrays. 15 // 16 // The `arpk` (ARray with PacKing info explicit) type is, generally, a slice with _any_ striding. 17 // This type is meant for internal use. 18 // CFA programmers should not instantiate it directly, nor access its field. 19 // CFA programmers should call ?[?] on it. 20 // Yet user-given `array(stuff)` expands to `arpk(stuff')`. 21 // The comments here explain the resulting internals. 22 // 23 // Just as a plain-C "multidimesional" array is really array-of-array-of-..., 24 // so does arpk generally show up as arpk-of-arpk-of... 25 // 26 // In the example of `array(float, 3, 4, 5) a;`, 27 // `typeof(a)` is an `arpk` instantiation. 28 // These comments explain _its_ arguments, i.e. those of the topmost `arpk` level. 29 // 30 // [N] : the number of elements in `a`; 3 in the example 31 // S : carries the stride size (distance in bytes between &myA[0] and &myA[1]), in sizeof(S); 32 // same as Timmed when striding is trivial, same as Timmed in the example 33 // Timmed : (T-immediate) the inner type; conceptually, `typeof(a)` is "arpk of Timmed"; 34 // array(float, 4, 5) in the example 35 // Tbase : (T-base) the deepest element type that is not arpk; float in the example 36 // 15 37 forall( [N], S & | sized(S), Timmed &, Tbase & ) { 38 39 // 40 // Single-dim array sruct (with explicit packing and atom) 41 // 16 42 struct arpk { 17 43 S strides[N]; -
libcfa/src/containers/list.hfa
r34b4268 r24d6572 9 9 // Author : Michael Brooks 10 10 // Created On : Wed Apr 22 18:00:00 2020 11 // Last Modified By : Michael Brooks12 // Last Modified On : Wed Apr 22 18:00:00 202013 // Update Count : 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 11:32:26 2023 13 // Update Count : 2 14 14 // 15 15 … … 23 23 }; 24 24 25 trait embedded( tOuter &, tMid &, tInner & ) { 25 forall( tOuter &, tMid &, tInner & ) 26 trait embedded { 26 27 tytagref( tMid, tInner ) ?`inner( tOuter & ); 27 28 }; … … 31 32 static inline tytagref(void, T) ?`inner ( T & this ) { tytagref( void, T ) ret = {this}; return ret; } 32 33 33 // use this on every case of plan-9 inheritance, to make embedded a closure of plan-9 inheritance 34 #define P9_EMBEDDED( derived, immedBase ) \ 35 forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \ 36 static inline tytagref(immedBase, Tbase) ?`inner( derived & this ) { \ 34 35 // 36 // P9_EMBEDDED: Use on every case of plan-9 inheritance, to make "implements embedded" be a closure of plan-9 inheritance. 37 // 38 // struct foo { 39 // int a, b, c; 40 // inline (bar); 41 // }; 42 // P9_EMBEDDED( foo, bar ) 43 // 44 45 // usual version, for structs that are top-level declarations 46 #define P9_EMBEDDED( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, static ) P9_EMBEDDED_BDY_( immedBase ) 47 48 // special version, for structs that are declared in functions 49 #define P9_EMBEDDED_INFUNC( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, ) P9_EMBEDDED_BDY_( immedBase ) 50 51 // forward declarations of both the above; generally not needed 52 // may help you control where the P9_EMBEEDED cruft goes, in case "right after the stuct" isn't where you want it 53 #define P9_EMBEDDED_FWD( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, static ) ; 54 #define P9_EMBEDDED_FWD_INFUNC( derived, immedBase ) auto P9_EMBEDDED_DECL_( derived, immedBase, ) ; 55 56 // private helpers 57 #define P9_EMBEDDED_DECL_( derived, immedBase, STORAGE ) \ 58 forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \ 59 STORAGE inline tytagref(immedBase, Tbase) ?`inner( derived & this ) 60 61 #define P9_EMBEDDED_BDY_( immedBase ) { \ 37 62 immedBase & ib = this; \ 38 63 Tbase & b = ib`inner; \ -
libcfa/src/containers/vector.hfa
r34b4268 r24d6572 10 10 // Created On : Tue Jul 5 18:00:07 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 17 11:02:46 202013 // Update Count : 412 // Last Modified On : Thu Feb 2 11:41:24 2023 13 // Update Count : 5 14 14 // 15 15 … … 50 50 //------------------------------------------------------------------------------ 51 51 //Declaration 52 trait allocator_c(T, allocator_t)53 {52 forall( T, allocator_t ) 53 trait allocator_c { 54 54 void realloc_storage(allocator_t*, size_t); 55 55 T* data(allocator_t*); -
libcfa/src/containers/vector2.hfa
r34b4268 r24d6572 9 9 // Author : Michael Brooks 10 10 // Created On : Thu Jun 23 22:00:00 2021 11 // Last Modified By : Michael Brooks 12 // Last Modified On : Thu Jun 23 22:00:00 2021 13 // Update Count : 1 14 // 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Mar 14 08:40:53 2023 13 // Update Count : 2 14 // 15 16 #pragma once 15 17 16 18 #include <stdlib.hfa> -
libcfa/src/exception.h
r34b4268 r24d6572 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:11:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Th r Apr 8 15:20:00 202113 // Update Count : 1 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 11:20:19 2023 13 // Update Count : 13 14 14 // 15 15 … … 101 101 // implemented in the .c file either so they all have to be inline. 102 102 103 trait is_exception(exceptT &, virtualT &) { 103 forall( exceptT &, virtualT & ) 104 trait is_exception { 104 105 /* The first field must be a pointer to a virtual table. 105 106 * That virtual table must be a decendent of the base exception virtual table. … … 109 110 }; 110 111 111 trait is_termination_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) { 112 forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) ) 113 trait is_termination_exception { 112 114 void defaultTerminationHandler(exceptT &); 113 115 }; 114 116 115 trait is_resumption_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) { 117 forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) ) 118 trait is_resumption_exception { 116 119 void defaultResumptionHandler(exceptT &); 117 120 }; -
libcfa/src/heap.cfa
r34b4268 r24d6572 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Oct 30 20:56:20202213 // Update Count : 1 58412 // Last Modified On : Fri Dec 30 08:37:37 2022 13 // Update Count : 1605 14 14 // 15 15 … … 17 17 #include <string.h> // memset, memcpy 18 18 #include <limits.h> // ULONG_MAX 19 #include <stdlib.h> // EXIT_FAILURE20 19 #include <errno.h> // errno, ENOMEM, EINVAL 21 #include <unistd.h> // STDERR_FILENO, sbrk, sysconf 22 #include <malloc.h> // memalign, malloc_usable_size 20 #include <unistd.h> // STDERR_FILENO, sbrk, sysconf, write 23 21 #include <sys/mman.h> // mmap, munmap 24 22 extern "C" { … … 26 24 } // extern "C" 27 25 26 #include "heap.hfa" 28 27 #include "bits/align.hfa" // libAlign 29 28 #include "bits/defs.hfa" // likely, unlikely … … 140 139 #endif 141 140 142 typedef volatile uintptr_t SpinLock_t CALIGN; // aligned addressable word-size141 typedef volatile uintptr_t SpinLock_t; 143 142 144 143 static inline __attribute__((always_inline)) void lock( volatile SpinLock_t & slock ) { … … 147 146 148 147 for ( unsigned int i = 1;; i += 1 ) { 149 if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_ SEQ_CST) == 0 ) break; // Fence148 if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_ACQUIRE ) == 0 ) break; // Fence 150 149 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause(); // exponential spin 151 150 spin += spin; // powers of 2 … … 156 155 157 156 static inline __attribute__((always_inline)) void unlock( volatile SpinLock_t & slock ) { 158 __atomic_clear( &slock, __ATOMIC_ SEQ_CST); // Fence157 __atomic_clear( &slock, __ATOMIC_RELEASE ); // Fence 159 158 } // spin_unlock 160 159 … … 261 260 static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" ); 262 261 263 struct __attribute__(( aligned (8) ))FreeHeader {264 size_t blockSize __attribute__(( aligned(8) ));// size of allocations on this list262 struct CALIGN FreeHeader { 263 size_t blockSize CALIGN; // size of allocations on this list 265 264 #ifdef OWNERSHIP 266 265 #ifdef RETURNSPIN … … 284 283 285 284 #ifdef __CFA_DEBUG__ 286 int64_t allocUnfreed; // running total of allocations minus frees; can be negative285 ptrdiff_t allocUnfreed; // running total of allocations minus frees; can be negative 287 286 #endif // __CFA_DEBUG__ 288 287 … … 369 368 // Thread-local storage is allocated lazily when the storage is accessed. 370 369 static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing 371 static __thread Heap * volatileheapManager CALIGN TLSMODEL;370 static __thread Heap * heapManager CALIGN TLSMODEL; 372 371 static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing 373 372 … … 443 442 // 12K ~= 120K byte superblock. Where 128-heap superblock handles a medium sized multi-processor server. 444 443 size_t remaining = heapManagersStorageEnd - heapManagersStorage; // remaining free heaps in superblock 445 if ( ! heapManagersStorage || remaining != 0 ) {444 if ( ! heapManagersStorage || remaining == 0 ) { 446 445 // Each block of heaps is a multiple of the number of cores on the computer. 447 446 int HeapDim = get_nprocs(); // get_nprocs_conf does not work … … 562 561 // allocUnfreed is set to 0 when a heap is created and it accumulates any unfreed storage during its multiple thread 563 562 // usages. At the end, add up each heap allocUnfreed value across all heaps to get the total unfreed storage. 564 int64_t allocUnfreed = 0;563 ptrdiff_t allocUnfreed = 0; 565 564 for ( Heap * heap = heapMaster.heapManagersList; heap; heap = heap->nextHeapManager ) { 566 565 allocUnfreed += heap->allocUnfreed; … … 572 571 char helpText[512]; 573 572 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), 574 "CFA warning (UNIX pid:%ld) : program terminating with % ju(0x%jx) bytes of storage allocated but not freed.\n"573 "CFA warning (UNIX pid:%ld) : program terminating with %td(%#tx) bytes of storage allocated but not freed.\n" 575 574 "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n", 576 575 (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid … … 806 805 807 806 ptrdiff_t rem = heapRemaining - size; 808 if ( unlikely( rem < 0 ) ) { 807 if ( unlikely( rem < 0 ) ) { // negative ? 809 808 // If the size requested is bigger than the current remaining storage, increase the size of the heap. 810 809 … … 842 841 ptrdiff_t rem = heapReserve - size; 843 842 844 if ( unlikely( rem < 0 ) ) { // negative 843 if ( unlikely( rem < 0 ) ) { // negative ? 845 844 // If the size requested is bigger than the current remaining reserve, use the current reserve to populate 846 845 // smaller freeLists, and increase the reserve. … … 848 847 rem = heapReserve; // positive 849 848 850 if ( rem >= bucketSizes[0] ) {// minimal size ? otherwise ignore849 if ( (unsigned int)rem >= bucketSizes[0] ) { // minimal size ? otherwise ignore 851 850 size_t bucket; 852 851 #ifdef FASTLOOKUP … … 857 856 Heap.FreeHeader * freeHead = &(freeLists[bucket]); 858 857 859 // The remaining storage ma ny not be bucket size, whereas all other allocations are. Round down to previous858 // The remaining storage may not be bucket size, whereas all other allocations are. Round down to previous 860 859 // bucket size in this case. 861 860 if ( unlikely( freeHead->blockSize > (size_t)rem ) ) freeHead -= 1; … … 950 949 block = freeHead->freeList; // remove node from stack 951 950 if ( unlikely( block == 0p ) ) { // no free block ? 952 // Freelist for this size is empty, so check return list (OWNERSHIP), carve it out of the heap,if there951 // Freelist for this size is empty, so check return list (OWNERSHIP), or carve it out of the heap if there 953 952 // is enough left, or get some more heap storage and carve it off. 954 953 #ifdef OWNERSHIP … … 1115 1114 while ( ! __atomic_compare_exchange_n( &freeHead->returnList, &header->kind.real.next, (Heap.Storage *)header, 1116 1115 false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ); 1116 1117 #ifdef __STATISTICS__ 1118 stats.return_pushes += 1; 1119 stats.return_storage_request += rsize; 1120 stats.return_storage_alloc += size; 1121 #endif // __STATISTICS__ 1117 1122 #endif // RETURNSPIN 1118 1123 } // if … … 1125 1130 freeHead->freeList = (Heap.Storage *)header; 1126 1131 #endif // ! OWNERSHIP 1127 1128 #ifdef __U_STATISTICS__1129 stats.return_pushes += 1;1130 stats.return_storage_request += rsize;1131 stats.return_storage_alloc += size;1132 #endif // __U_STATISTICS__1133 1132 1134 1133 // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED. … … 1180 1179 1181 1180 #ifdef __STATISTICS__ 1182 static void incCalls( intptr_t statName ) libcfa_nopreempt {1181 static void incCalls( size_t statName ) libcfa_nopreempt { 1183 1182 heapManager->stats.counters[statName].calls += 1; 1184 1183 } // incCalls 1185 1184 1186 static void incZeroCalls( intptr_t statName ) libcfa_nopreempt {1185 static void incZeroCalls( size_t statName ) libcfa_nopreempt { 1187 1186 heapManager->stats.counters[statName].calls_0 += 1; 1188 1187 } // incZeroCalls … … 1456 1455 // 0p, no operation is performed. 1457 1456 void free( void * addr ) libcfa_public { 1458 // verify( heapManager );1459 1460 1457 if ( unlikely( addr == 0p ) ) { // special case 1461 1458 #ifdef __STATISTICS__ -
libcfa/src/interpose.cfa
r34b4268 r24d6572 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Mar 13 17:35:37 2020 13 // Update Count : 178 14 // 15 16 #include <stdarg.h> // va_start, va_end 12 // Last Modified On : Mon Mar 27 21:09:03 2023 13 // Update Count : 196 14 // 15 17 16 #include <stdio.h> 18 #include <string.h> // strlen19 17 #include <unistd.h> // _exit, getpid 20 #define __USE_GNU21 #include <signal.h>22 #undef __USE_GNU23 18 extern "C" { 24 19 #include <dlfcn.h> // dlopen, dlsym … … 26 21 } 27 22 28 #include "bits/debug.hfa"29 23 #include "bits/defs.hfa" 30 24 #include "bits/signal.hfa" // sigHandler_? … … 42 36 43 37 typedef void (* generic_fptr_t)(void); 38 44 39 static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) { 45 const char * error;46 47 40 union { generic_fptr_t fptr; void * ptr; } originalFunc; 48 41 49 42 #if defined( _GNU_SOURCE ) 50 if ( version ) {51 originalFunc.ptr = dlvsym( library, symbol, version );52 } else {53 originalFunc.ptr = dlsym( library, symbol );54 }43 if ( version ) { 44 originalFunc.ptr = dlvsym( library, symbol, version ); 45 } else { 46 originalFunc.ptr = dlsym( library, symbol ); 47 } // if 55 48 #else 56 originalFunc.ptr = dlsym( library, symbol );49 originalFunc.ptr = dlsym( library, symbol ); 57 50 #endif // _GNU_SOURCE 58 51 59 error = dlerror();60 if ( error ) abort( "interpose_symbol : internal error, %s\n", error);61 52 if ( ! originalFunc.ptr ) { // == nullptr 53 abort( "interpose_symbol : internal error, %s\n", dlerror() ); 54 } // if 62 55 return originalFunc.fptr; 63 56 } 64 57 65 58 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) { 66 const char * error; 67 68 static void * library; 69 static void * pthread_library; 70 if ( ! library ) { 71 #if defined( RTLD_NEXT ) 72 library = RTLD_NEXT; 73 #else 74 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 75 library = dlopen( "libc.so.6", RTLD_LAZY ); 76 error = dlerror(); 77 if ( error ) { 78 abort( "interpose_symbol : failed to open libc, %s\n", error ); 79 } 80 #endif 59 void * library; 60 61 #if defined( RTLD_NEXT ) 62 library = RTLD_NEXT; 63 #else 64 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 65 library = dlopen( "libc.so.6", RTLD_LAZY ); 66 if ( ! library ) { // == nullptr 67 abort( "interpose_symbol : failed to open libc, %s\n", dlerror() ); 81 68 } // if 82 if ( ! pthread_library ) { 83 #if defined( RTLD_NEXT ) 84 pthread_library = RTLD_NEXT; 85 #else 86 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 87 pthread_library = dlopen( "libpthread.so", RTLD_LAZY ); 88 error = dlerror(); 89 if ( error ) { 90 abort( "interpose_symbol : failed to open libpthread, %s\n", error ); 91 } 92 #endif 93 } // if 94 95 return do_interpose_symbol(library, symbol, version); 69 #endif // RTLD_NEXT 70 71 return do_interpose_symbol( library, symbol, version ); 96 72 } 97 73 … … 123 99 preload_libgcc(); 124 100 125 #pragma GCC diagnostic push126 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"101 #pragma GCC diagnostic push 102 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 127 103 INTERPOSE_LIBC( abort, version ); 128 104 INTERPOSE_LIBC( exit , version ); 129 #pragma GCC diagnostic pop105 #pragma GCC diagnostic pop 130 106 131 107 if(__cfathreadabi_interpose_startup) __cfathreadabi_interpose_startup( do_interpose_symbol ); 108 109 // SKULLDUGGERY: In Ubuntu 22.04, someone augmented signal.h to allow SIGSTKSZ to be "sysconf(_SC_SIGSTKSZ)" in 110 // sigstksz.h, as well as 8192 in sigstack.h. HOWEVER, they forgot to provide a mechanism to tell signal.h to 111 // use sigstack.h rather than sigstksz.h. (I'm not happy.) By undefining _GNU_SOURCE before signal.h and 112 // redefining it afterwards, you can get 8192, but then nothing works correctly inside of signal.h without 113 // _GNU_SOURCE defined. So what is needed is a way to get signal.h to use sigstack.h WITH _GNU_SOURCE defined. 114 // Basically something is wrong with features.h and its use in signal.h. 115 116 #undef SIGSTKSZ 117 #define SIGSTKSZ 8192 132 118 133 119 // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because … … 295 281 va_start( args, fmt ); 296 282 __abort( false, fmt, args ); 297 // CONTROL NEVER REACHES HERE!283 // CONTROL NEVER REACHES HERE! 298 284 va_end( args ); 299 285 } 300 286 301 287 void abort( bool signalAbort, const char fmt[], ... ) { 302 va_list args;303 va_start( args, fmt );304 __abort( signalAbort, fmt, args );305 // CONTROL NEVER REACHES HERE!306 va_end( args );288 va_list args; 289 va_start( args, fmt ); 290 __abort( signalAbort, fmt, args ); 291 // CONTROL NEVER REACHES HERE! 292 va_end( args ); 307 293 } 308 294 -
libcfa/src/interpose_thread.cfa
r34b4268 r24d6572 14 14 // 15 15 16 #include <stdarg.h> // va_start, va_end 17 #include <stdio.h> 18 #include <string.h> // strlen 16 // BUG in 32-bit gcc with interpose: fixed in >= gcc-9.5, gcc-10.4, gcc-12.2 17 #ifdef __i386__ // 32-bit architecture 18 #undef _GNU_SOURCE 19 #endif // __i386__ 20 19 21 #include <signal.h> 20 22 #include <pthread.h> 23 #include <signal.h> 21 24 extern "C" { 22 25 #include <dlfcn.h> // dlopen, dlsym 23 #include <execinfo.h> // backtrace, messages24 26 } 25 27 26 #include "bits/debug.hfa"27 28 #include "bits/defs.hfa" 28 #include <assert.h>29 29 30 30 //============================================================================================= … … 34 34 typedef void (* generic_fptr_t)(void); 35 35 36 generic_fptr_t interpose_symbol(36 generic_fptr_t libcfa_public interpose_symbol( 37 37 generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ), 38 38 const char symbol[], 39 39 const char version[] 40 ) libcfa_public{41 const char * error;40 ) { 41 void * library; 42 42 43 static void * library; 44 if ( ! library ) { 45 #if defined( RTLD_NEXT ) 46 library = RTLD_NEXT; 47 #else 48 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 49 library = dlopen( "libpthread.so", RTLD_LAZY ); 50 error = dlerror(); 51 if ( error ) { 52 abort( "interpose_symbol : failed to open libpthread, %s\n", error ); 53 } 54 #endif 43 #if defined( RTLD_NEXT ) 44 library = RTLD_NEXT; 45 #else 46 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 47 library = dlopen( "libpthread.so", RTLD_LAZY ); 48 if ( ! library ) { // == nullptr 49 abort( "interpose_symbol : failed to open libpthread, %s\n", dlerror() ); 55 50 } // if 51 #endif // RTLD_NEXT 56 52 57 return do_interpose_symbol( library, symbol, version);53 return do_interpose_symbol( library, symbol, version ); 58 54 } 59 55 … … 83 79 #pragma GCC diagnostic push 84 80 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 85 INTERPOSE( pthread_create , version );86 INTERPOSE( pthread_join , version );87 INTERPOSE( pthread_self , version );88 INTERPOSE( pthread_attr_init , version );89 INTERPOSE( pthread_attr_destroy , version );90 INTERPOSE( pthread_attr_setstack , version );91 INTERPOSE( pthread_attr_getstacksize , version );92 INTERPOSE( pthread_sigmask , version );93 INTERPOSE( pthread_sigqueue , version );94 INTERPOSE( pthread_once , version );81 INTERPOSE( pthread_create, version ); 82 INTERPOSE( pthread_join, version ); 83 INTERPOSE( pthread_self, version ); 84 INTERPOSE( pthread_attr_init, version ); 85 INTERPOSE( pthread_attr_destroy, version ); 86 INTERPOSE( pthread_attr_setstack, version ); 87 INTERPOSE( pthread_attr_getstacksize, version ); 88 INTERPOSE( pthread_sigmask, version ); 89 INTERPOSE( pthread_sigqueue, version ); 90 INTERPOSE( pthread_once, version ); 95 91 #pragma GCC diagnostic pop 96 92 } -
libcfa/src/iostream.cfa
r34b4268 r24d6572 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 27 15:04:15 202213 // Update Count : 13 5812 // Last Modified On : Mon Jan 9 09:27:58 2023 13 // Update Count : 1361 14 14 // 15 15 … … 667 667 } /* if */ \ 668 668 if ( ! f.flags.nobsdp || (exp10 < SUFFIXES_START) || (exp10 > SUFFIXES_END) ) { \ 669 len2 = snprintf( &buf[len], size - len, "e%d", exp10); \669 len2 = snprintf( &buf[len], size - len, "e%d", (int)exp10 /* ambiguity with function exp10 */ ); \ 670 670 } else { \ 671 671 len2 = snprintf( &buf[len], size - len, "%s", suffixes[(exp10 - SUFFIXES_START) / 3] ); \ -
libcfa/src/iostream.hfa
r34b4268 r24d6572 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Oct 10 10:02:07 202113 // Update Count : 4 0712 // Last Modified On : Thu Feb 2 11:25:39 2023 13 // Update Count : 410 14 14 // 15 15 … … 22 22 23 23 24 trait basic_ostream( ostype & ) { 24 forall( ostype & ) 25 trait basic_ostream { 25 26 // private 26 27 bool sepPrt$( ostype & ); // get separator state (on/off) … … 51 52 }; // basic_ostream 52 53 53 trait ostream( ostype & | basic_ostream( ostype ) ) { 54 forall( ostype & | basic_ostream( ostype ) ) 55 trait ostream { 54 56 bool fail( ostype & ); // operation failed? 55 57 void clear( ostype & ); … … 60 62 }; // ostream 61 63 62 // trait writeable( T ) { 64 // forall( T ) 65 // trait writeable { 63 66 // forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype &, T ); 64 67 // }; // writeable 65 68 66 trait writeable( T, ostype & | ostream( ostype ) ) { 69 forall( T, ostype & | ostream( ostype ) ) 70 trait writeable { 67 71 ostype & ?|?( ostype &, T ); 68 72 }; // writeable … … 290 294 291 295 292 trait basic_istream( istype & ) { 296 forall( istype & ) 297 trait basic_istream { 293 298 // private 294 299 bool getANL$( istype & ); // get scan newline (on/off) … … 302 307 }; // basic_istream 303 308 304 trait istream( istype & | basic_istream( istype ) ) { 309 forall( istype & | basic_istream( istype ) ) 310 trait istream { 305 311 bool fail( istype & ); 306 312 void clear( istype & ); … … 310 316 }; // istream 311 317 312 trait readable( T ) { 318 forall( T ) 319 trait readable { 313 320 forall( istype & | istream( istype ) ) istype & ?|?( istype &, T ); 314 321 }; // readable -
libcfa/src/iterator.hfa
r34b4268 r24d6572 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 7 08:37:25 201713 // Update Count : 1 012 // Last Modified On : Thu Feb 2 11:21:50 2023 13 // Update Count : 11 14 14 // 15 15 … … 17 17 18 18 // An iterator can be used to traverse a data structure. 19 trait iterator( iterator_type, elt_type ) { 19 forall( iterator_type, elt_type ) 20 trait iterator { 20 21 // point to the next element 21 22 // iterator_type ?++( iterator_type & ); … … 31 32 }; 32 33 33 trait iterator_for( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) ) { 34 forall( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) ) 35 trait iterator_for { 34 36 // [ iterator_type begin, iterator_type end ] get_iterators( collection_type ); 35 37 iterator_type begin( collection_type ); -
libcfa/src/limits.cfa
r34b4268 r24d6572 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 1 16:22:51 201813 // Update Count : 7412 // Last Modified On : Fri Feb 17 12:25:39 2023 13 // Update Count : 87 14 14 // 15 15 16 16 #include <limits.h> 17 17 #include <float.h> 18 #define __USE_GNU // get M_* constants19 18 #include <math.h> 20 19 #include <complex.h> -
libcfa/src/math.trait.hfa
r34b4268 r24d6572 10 10 // Created On : Fri Jul 16 15:40:52 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Jul 20 17:47:19 202113 // Update Count : 1912 // Last Modified On : Thu Feb 2 11:36:56 2023 13 // Update Count : 20 14 14 // 15 15 16 16 #pragma once 17 17 18 trait Not( U ) { 18 forall( U ) 19 trait Not { 19 20 void ?{}( U &, zero_t ); 20 21 int !?( U ); 21 22 }; // Not 22 23 23 trait Equality( T | Not( T ) ) { 24 forall( T | Not( T ) ) 25 trait Equality { 24 26 int ?==?( T, T ); 25 27 int ?!=?( T, T ); 26 28 }; // Equality 27 29 28 trait Relational( U | Equality( U ) ) { 30 forall( U | Equality( U ) ) 31 trait Relational { 29 32 int ?<?( U, U ); 30 33 int ?<=?( U, U ); … … 33 36 }; // Relational 34 37 35 trait Signed( T ) { 38 forall ( T ) 39 trait Signed { 36 40 T +?( T ); 37 41 T -?( T ); … … 39 43 }; // Signed 40 44 41 trait Additive( U | Signed( U ) ) { 45 forall( U | Signed( U ) ) 46 trait Additive { 42 47 U ?+?( U, U ); 43 48 U ?-?( U, U ); … … 46 51 }; // Additive 47 52 48 trait Incdec( T | Additive( T ) ) { 53 forall( T | Additive( T ) ) 54 trait Incdec { 49 55 void ?{}( T &, one_t ); 50 56 // T ?++( T & ); … … 54 60 }; // Incdec 55 61 56 trait Multiplicative( U | Incdec( U ) ) { 62 forall( U | Incdec( U ) ) 63 trait Multiplicative { 57 64 U ?*?( U, U ); 58 65 U ?/?( U, U ); … … 61 68 }; // Multiplicative 62 69 63 trait Arithmetic( T | Relational( T ) | Multiplicative( T ) ) { 70 forall( T | Relational( T ) | Multiplicative( T ) ) 71 trait Arithmetic { 64 72 }; // Arithmetic 65 73 -
libcfa/src/stdlib.cfa
r34b4268 r24d6572 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 9 15:11:30 202213 // Update Count : 63 112 // Last Modified On : Thu Feb 16 16:31:34 2023 13 // Update Count : 633 14 14 // 15 15 … … 20 20 //--------------------------------------- 21 21 22 #define _XOPEN_SOURCE 600 // posix_memalign, *rand4823 22 #include <string.h> // memcpy, memset 24 23 //#include <math.h> // fabsf, fabs, fabsl -
libcfa/src/stdlib.hfa
r34b4268 r24d6572 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 11 18:25:53 202213 // Update Count : 76 512 // Last Modified On : Thu Feb 2 11:30:04 2023 13 // Update Count : 766 14 14 // 15 15 … … 367 367 368 368 char random( void ) { return (unsigned long int)random(); } 369 char random( char u ) { return random( (unsigned long int)u ); } // [0,u)369 char random( char u ) { return (unsigned long int)random( (unsigned long int)u ); } // [0,u) 370 370 char random( char l, char u ) { return random( (unsigned long int)l, (unsigned long int)u ); } // [l,u) 371 371 int random( void ) { return (long int)random(); } 372 int random( int u ) { return random( (long int)u ); } // [0,u]372 int random( int u ) { return (long int)random( (long int)u ); } // [0,u] 373 373 int random( int l, int u ) { return random( (long int)l, (long int)u ); } // [l,u) 374 374 unsigned int random( void ) { return (unsigned long int)random(); } 375 unsigned int random( unsigned int u ) { return random( (unsigned long int)u ); } // [0,u]375 unsigned int random( unsigned int u ) { return (unsigned long int)random( (unsigned long int)u ); } // [0,u] 376 376 unsigned int random( unsigned int l, unsigned int u ) { return random( (unsigned long int)l, (unsigned long int)u ); } // [l,u) 377 377 } // distribution … … 404 404 // calls( sprng ); 405 405 406 trait basic_prng( PRNG &, R ) { 406 forall( PRNG &, R ) 407 trait basic_prng { 407 408 void set_seed( PRNG & prng, R seed ); // set seed 408 409 R get_seed( PRNG & prng ); // get seed -
libcfa/src/vec/vec.hfa
r34b4268 r24d6572 18 18 #include <math.hfa> 19 19 20 trait fromint(T) { 20 forall(T) 21 trait fromint { 21 22 void ?{}(T&, int); 22 23 }; 23 trait zeroinit(T) { 24 forall(T) 25 trait zeroinit { 24 26 void ?{}(T&, zero_t); 25 27 }; 26 trait zero_assign(T) { 28 forall(T) 29 trait zero_assign { 27 30 T ?=?(T&, zero_t); 28 31 }; 29 trait subtract(T) { 32 forall(T) 33 trait subtract { 30 34 T ?-?(T, T); 31 35 }; 32 trait negate(T) { 36 forall(T) 37 trait negate { 33 38 T -?(T); 34 39 }; 35 trait add(T) { 40 forall(T) 41 trait add { 36 42 T ?+?(T, T); 37 43 }; 38 trait multiply(T) { 44 forall(T) 45 trait multiply { 39 46 T ?*?(T, T); 40 47 }; 41 trait divide(T) { 48 forall(T) 49 trait divide { 42 50 T ?/?(T, T); 43 51 }; 44 trait lessthan(T) { 52 forall(T) 53 trait lessthan { 45 54 int ?<?(T, T); 46 55 }; 47 trait equality(T) { 56 forall(T) 57 trait equality { 48 58 int ?==?(T, T); 49 59 }; 50 trait sqrt(T) { 60 forall(T) 61 trait sqrt { 51 62 T sqrt(T); 52 63 }; -
src/AST/Attribute.hpp
r34b4268 r24d6572 27 27 class Expr; 28 28 29 /// An entry in an attribute list: `__attribute__(( ... ))` 29 30 class Attribute final : public Node { 30 31 public: -
src/AST/Convert.cpp
r34b4268 r24d6572 559 559 auto stmt = new SuspendStmt(); 560 560 stmt->then = get<CompoundStmt>().accept1( node->then ); 561 switch (node->type) {561 switch (node->kind) { 562 562 case ast::SuspendStmt::None : stmt->type = SuspendStmt::None ; break; 563 563 case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break; … … 565 565 } 566 566 return stmtPostamble( stmt, node ); 567 } 568 569 const ast::WhenClause * visit( const ast::WhenClause * node ) override final { 570 // There is no old-AST WhenClause, so this should never be called. 571 assert( !node ); 572 return nullptr; 567 573 } 568 574 … … 573 579 for ( auto clause : node->clauses ) { 574 580 stmt->clauses.push_back({{ 575 get<Expression>().accept1( clause->target _func),581 get<Expression>().accept1( clause->target ), 576 582 get<Expression>().acceptL( clause->target_args ), 577 583 }, 578 584 get<Statement>().accept1( clause->stmt ), 579 get<Expression>().accept1( clause-> cond ),585 get<Expression>().accept1( clause->when_cond ), 580 586 }); 581 587 } … … 594 600 const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final { 595 601 // There is no old-AST WaitForClause, so this should never be called. 602 assert( !node ); 603 return nullptr; 604 } 605 606 const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final { 607 // There is no old-AST WaitUntilStmt, so this should never be called. 596 608 assert( !node ); 597 609 return nullptr; … … 1683 1695 GET_ACCEPT_V(attributes, Attribute), 1684 1696 { old->get_funcSpec().val }, 1685 old->type->isVarArgs1697 (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1686 1698 }; 1687 1699 … … 1989 2001 GET_ACCEPT_1(else_, Stmt), 1990 2002 GET_ACCEPT_V(initialization, Stmt), 1991 old->isDoWhile,2003 (old->isDoWhile) ? ast::DoWhile : ast::While, 1992 2004 GET_LABELS_V(old->labels) 1993 2005 ); … … 2131 2143 virtual void visit( const SuspendStmt * old ) override final { 2132 2144 if ( inCache( old ) ) return; 2133 ast::SuspendStmt:: Typetype;2145 ast::SuspendStmt::Kind type; 2134 2146 switch (old->type) { 2135 2147 case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break; … … 2158 2170 auto clause = new ast::WaitForClause( old->location ); 2159 2171 2160 clause->target _func= GET_ACCEPT_1(clauses[i].target.function, Expr);2172 clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr); 2161 2173 clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr); 2162 2174 clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt); 2163 clause-> cond = GET_ACCEPT_1(clauses[i].condition, Expr);2175 clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr); 2164 2176 2165 2177 stmt->clauses.push_back( clause ); -
src/AST/Create.cpp
r34b4268 r24d6572 20 20 #include "AST/Decl.hpp" 21 21 #include "AST/Type.hpp" 22 #include "Common/Iterate.hpp" 22 23 23 24 namespace ast { -
src/AST/Decl.cpp
r34b4268 r24d6572 20 20 #include <unordered_map> 21 21 22 #include "Common/ utility.h"22 #include "Common/Eval.h" // for eval 23 23 24 24 #include "Fwd.hpp" // for UniqueId … … 57 57 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 58 58 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 60 60 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), 61 61 type_params(std::move(forall)), assertions(), 62 62 params(std::move(params)), returns(std::move(returns)), stmts( stmts ) { 63 FunctionType * ftype = new FunctionType( static_cast<ArgumentFlag>(isVarArgs));63 FunctionType * ftype = new FunctionType( isVarArgs ); 64 64 for (auto & param : this->params) { 65 65 ftype->params.emplace_back(param->get_type()); … … 81 81 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 82 82 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 84 84 : DeclWithType( location, name, storage, linkage, std::move(attrs), fs ), 85 85 type_params( std::move( forall) ), assertions( std::move( assertions ) ), 86 86 params( std::move(params) ), returns( std::move(returns) ), 87 87 type( nullptr ), stmts( stmts ) { 88 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );88 FunctionType * type = new FunctionType( isVarArgs ); 89 89 for ( auto & param : this->params ) { 90 90 type->params.emplace_back( param->get_type() ); -
src/AST/Decl.hpp
r34b4268 r24d6572 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:44:00 202213 // Update Count : 3 412 // Last Modified On : Wed Apr 5 10:42:00 2023 13 // Update Count : 35 14 14 // 15 15 … … 122 122 }; 123 123 124 /// Function variable arguments flag 125 enum ArgumentFlag { FixedArgs, VariableArgs }; 126 124 127 /// Object declaration `int foo()` 125 128 class FunctionDecl : public DeclWithType { … … 144 147 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 145 148 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);149 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 147 150 148 151 FunctionDecl( const CodeLocation & location, const std::string & name, … … 150 153 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 151 154 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);155 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 153 156 154 157 const Type * get_type() const override; … … 313 316 public: 314 317 bool isTyped; // isTyped indicated if the enum has a declaration like: 315 // enum (type_optional) Name {...} 318 // enum (type_optional) Name {...} 316 319 ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum 317 320 enum class EnumHiding { Visible, Hide } hide; … … 371 374 }; 372 375 376 /// Assembly declaration: `asm ... ( "..." : ... )` 373 377 class AsmDecl : public Decl { 374 378 public: -
src/AST/Expr.cpp
r34b4268 r24d6572 30 30 #include "Common/SemanticError.h" 31 31 #include "GenPoly/Lvalue.h" // for referencesPermissable 32 #include "ResolvExpr/ typeops.h"// for extractResultType32 #include "ResolvExpr/Unify.h" // for extractResultType 33 33 #include "Tuples/Tuples.h" // for makeTupleType 34 34 -
src/AST/Expr.hpp
r34b4268 r24d6572 256 256 }; 257 257 258 /// A name qualified by a namespace or type. 258 259 class QualifiedNameExpr final : public Expr { 259 260 public: … … 261 262 std::string name; 262 263 263 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 264 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 264 265 : Expr( loc ), type_decl( d ), name( n ) {} 265 266 … … 631 632 }; 632 633 634 /// A name that refers to a generic dimension parameter. 633 635 class DimensionExpr final : public Expr { 634 636 public: … … 920 922 }; 921 923 922 923 924 } 924 925 -
src/AST/Fwd.hpp
r34b4268 r24d6572 15 15 16 16 #pragma once 17 18 template<typename> struct bitfield; 17 19 18 20 #include "AST/Node.hpp" … … 56 58 class FinallyClause; 57 59 class SuspendStmt; 60 class WhenClause; 58 61 class WaitForStmt; 59 62 class WaitForClause; 63 class WaitUntilStmt; 60 64 class WithStmt; 61 65 class DeclStmt; … … 147 151 class TranslationGlobal; 148 152 153 // For the following types, only use the using type. 154 namespace CV { 155 struct qualifier_flags; 156 using Qualifiers = bitfield<qualifier_flags>; 149 157 } 158 namespace Function { 159 struct spec_flags; 160 using Specs = bitfield<spec_flags>; 161 } 162 namespace Storage { 163 struct class_flags; 164 using Classes = bitfield<class_flags>; 165 } 166 namespace Linkage { 167 struct spec_flags; 168 using Spec = bitfield<spec_flags>; 169 } 170 171 } -
src/AST/Init.hpp
r34b4268 r24d6572 117 117 ptr<Init> init; 118 118 119 ConstructorInit( 119 ConstructorInit( 120 120 const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init ) 121 121 : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {} -
src/AST/Inspect.cpp
r34b4268 r24d6572 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Oct 3 11:04:00 202213 // Update Count : 312 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 168 168 } 169 169 170 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) { 171 return obj && obj->name.empty() && obj->bitfieldWidth; 172 } 173 170 174 } // namespace ast -
src/AST/Inspect.hpp
r34b4268 r24d6572 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Sep 22 13:44:00 202213 // Update Count : 212 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 3 14 14 // 15 15 … … 38 38 const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr ); 39 39 40 /// Returns true if obj's name is the empty string and it has a bitfield width. 41 bool isUnnamedBitfield( const ObjectDecl * obj ); 42 40 43 } -
src/AST/Node.cpp
r34b4268 r24d6572 174 174 template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >; 175 175 template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >; 176 template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::weak >; 177 template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::strong >; 176 178 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >; 177 179 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >; 178 180 template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >; 179 181 template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >; 182 template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::weak >; 183 template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::strong >; 180 184 template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >; 181 185 template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >; -
src/AST/Node.hpp
r34b4268 r24d6572 19 19 #include <cstddef> // for nullptr_t 20 20 #include <iosfwd> 21 #include <type_traits> // for remove_reference22 21 23 22 #include "Common/ErrorObjects.h" // for SemanticErrorException … … 36 35 Node(const Node&) : strong_count(0), weak_count(0) {} 37 36 Node(Node&&) : strong_count(0), weak_count(0) {} 38 Node& operator= (const Node&) = delete;39 Node& operator= (Node&&) = delete;37 Node& operator=(const Node&) = delete; 38 Node& operator=(Node&&) = delete; 40 39 virtual ~Node() {} 41 40 -
src/AST/ParseNode.hpp
r34b4268 r24d6572 40 40 template<typename node_t> 41 41 friend node_t * mutate(const node_t * node); 42 template<typename node_t> 43 friend node_t * shallowCopy(const node_t * node); 42 44 }; 43 45 -
src/AST/Pass.hpp
r34b4268 r24d6572 66 66 // 67 67 // Other Special Members: 68 // | beginScope - A method with no parameters or return value, called each time the 69 // visitor enters a block. 70 // | endScope - A method with no parameters or return value, called each time the 71 // visitor leaves a block. 68 72 // | result - Either a method that takes no parameters or a field. If a method (or 69 73 // callable field) get_result calls it, otherwise the value is returned. … … 82 86 { 83 87 // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor 84 type * const * visitor = __pass::visitor( core, 0);85 if (visitor) {88 type * const * visitor = __pass::visitor( core, 0 ); 89 if ( visitor ) { 86 90 *const_cast<type **>( visitor ) = this; 87 91 } … … 94 98 95 99 /// If the core defines a result, call it if possible, otherwise return it. 96 inline auto get_result() -> decltype( __pass:: get_result( core, '0' ) ) {97 return __pass:: get_result( core, '0' );100 inline auto get_result() -> decltype( __pass::result::get( core, '0' ) ) { 101 return __pass::result::get( core, '0' ); 98 102 } 99 103 … … 158 162 const ast::FinallyClause * visit( const ast::FinallyClause * ) override final; 159 163 const ast::Stmt * visit( const ast::SuspendStmt * ) override final; 164 const ast::WhenClause * visit( const ast::WhenClause * ) override final; 160 165 const ast::Stmt * visit( const ast::WaitForStmt * ) override final; 161 166 const ast::WaitForClause * visit( const ast::WaitForClause * ) override final; 167 const ast::Stmt * visit( const ast::WaitUntilStmt * ) override final; 162 168 const ast::Decl * visit( const ast::WithStmt * ) override final; 163 169 const ast::NullStmt * visit( const ast::NullStmt * ) override final; -
src/AST/Pass.impl.hpp
r34b4268 r24d6572 20 20 #include <unordered_map> 21 21 22 #include "AST/Copy.hpp" 22 23 #include "AST/TranslationUnit.hpp" 23 24 #include "AST/TypeSubstitution.hpp" … … 45 46 46 47 #ifdef PEDANTIC_PASS_ASSERT 47 #define __pedantic_pass_assert(...) assert (__VA_ARGS__)48 #define __pedantic_pass_assert(...) assert(__VA_ARGS__) 48 49 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 49 50 #else … … 124 125 return !new_val.empty(); 125 126 } 126 }127 128 template< typename node_t >129 template< typename object_t, typename super_t, typename field_t >130 void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {131 object->*field = value;132 127 } 133 128 … … 233 228 234 229 return {true, compound}; 235 }236 237 template< template <class...> class container_t >238 template< typename object_t, typename super_t, typename field_t >239 void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {240 auto & container = object->*field;241 __pedantic_pass_assert( container.size() <= values.size() );242 243 auto cit = enumerate(container).begin();244 245 container_t<ptr<Stmt>> nvals;246 for (delta & d : values) {247 if ( d.is_old ) {248 __pedantic_pass_assert( cit.idx <= d.old_idx );249 std::advance( cit, d.old_idx - cit.idx );250 nvals.push_back( std::move( (*cit).val) );251 } else {252 nvals.push_back( std::move(d.new_val) );253 }254 }255 256 container = std::move(nvals);257 }258 259 template< template <class...> class container_t >260 template< template <class...> class incontainer_t >261 void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {262 if (!stmts || stmts->empty()) return;263 264 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),265 [](ast::ptr<ast::Stmt>& stmt) -> delta {266 return delta( stmt.release(), -1, false );267 });268 stmts->clear();269 differs = true;270 }271 272 template< template<class...> class container_t >273 template< template<class...> class incontainer_t >274 void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {275 if (!decls || decls->empty()) return;276 277 std::transform(decls->begin(), decls->end(), std::back_inserter( values ),278 [](ast::ptr<ast::Decl>& decl) -> delta {279 auto loc = decl->location;280 auto stmt = new DeclStmt( loc, decl.release() );281 return delta( stmt, -1, false );282 });283 decls->clear();284 differs = true;285 230 } 286 231 … … 352 297 353 298 return new_kids; 354 }355 356 template< template <class...> class container_t, typename node_t >357 template< typename object_t, typename super_t, typename field_t >358 void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {359 auto & container = object->*field;360 __pedantic_pass_assert( container.size() == values.size() );361 362 for(size_t i = 0; i < container.size(); i++) {363 // Take all the elements that are different in 'values'364 // and swap them into 'container'365 if( values[i] != nullptr ) swap(container[i], values[i]);366 }367 368 // Now the original containers should still have the unchanged values369 // but also contain the new values370 299 } 371 300 … … 836 765 if ( enterScope ) { 837 766 __pass::symtab::enter(core, 0); 838 __pass::scope::enter(core, 0);839 767 } 840 768 }, [this, leaveScope = !this->atFunctionTop]() { 841 769 if ( leaveScope ) { 842 770 __pass::symtab::leave(core, 0); 843 __pass::scope::leave(core, 0);844 771 } 845 772 }); … … 1067 994 1068 995 //-------------------------------------------------------------------------- 996 // WhenClause 997 template< typename core_t > 998 const ast::WhenClause * ast::Pass< core_t >::visit( const ast::WhenClause * node ) { 999 VISIT_START( node ); 1000 1001 if ( __visit_children() ) { 1002 maybe_accept( node, &WhenClause::target ); 1003 maybe_accept( node, &WhenClause::stmt ); 1004 maybe_accept( node, &WhenClause::when_cond ); 1005 } 1006 1007 VISIT_END( WhenClause, node ); 1008 } 1009 1010 //-------------------------------------------------------------------------- 1069 1011 // WaitForStmt 1070 1012 template< typename core_t > … … 1091 1033 1092 1034 if ( __visit_children() ) { 1093 maybe_accept( node, &WaitForClause::target _func);1035 maybe_accept( node, &WaitForClause::target ); 1094 1036 maybe_accept( node, &WaitForClause::target_args ); 1095 1037 maybe_accept( node, &WaitForClause::stmt ); 1096 maybe_accept( node, &WaitForClause:: cond );1038 maybe_accept( node, &WaitForClause::when_cond ); 1097 1039 } 1098 1040 1099 1041 VISIT_END( WaitForClause, node ); 1042 } 1043 1044 //-------------------------------------------------------------------------- 1045 // WaitUntilStmt 1046 template< typename core_t > 1047 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitUntilStmt * node ) { 1048 VISIT_START( node ); 1049 1050 if ( __visit_children() ) { 1051 maybe_accept( node, &WaitUntilStmt::clauses ); 1052 maybe_accept( node, &WaitUntilStmt::timeout_time ); 1053 maybe_accept( node, &WaitUntilStmt::timeout_stmt ); 1054 maybe_accept( node, &WaitUntilStmt::timeout_cond ); 1055 maybe_accept( node, &WaitUntilStmt::else_stmt ); 1056 maybe_accept( node, &WaitUntilStmt::else_cond ); 1057 } 1058 1059 VISIT_END( Stmt, node ); 1100 1060 } 1101 1061 … … 2043 2003 if ( __visit_children() ) { 2044 2004 maybe_accept( node, &TupleType::types ); 2045 maybe_accept( node, &TupleType::members );2046 2005 } 2047 2006 … … 2205 2164 } 2206 2165 2166 #undef __pedantic_pass_assertf 2167 #undef __pedantic_pass_assert 2207 2168 #undef VISIT_START 2208 2169 #undef VISIT_END -
src/AST/Pass.proto.hpp
r34b4268 r24d6572 17 17 // IWYU pragma: private, include "Pass.hpp" 18 18 19 #include "Common/Iterate.hpp" 19 20 #include "Common/Stats/Heap.h" 20 21 21 namespace ast { 22 template<typename core_t> 23 class Pass; 24 25 class TranslationUnit; 26 27 struct PureVisitor; 28 29 template<typename node_t> 30 node_t * deepCopy( const node_t * localRoot ); 31 32 namespace __pass { 33 typedef std::function<void( void * )> cleanup_func_t; 34 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 35 36 37 // boolean reference that may be null 38 // either refers to a boolean value or is null and returns true 39 class bool_ref { 40 public: 41 bool_ref() = default; 42 ~bool_ref() = default; 43 44 operator bool() { return m_ref ? *m_ref : true; } 45 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 46 47 private: 48 49 friend class visit_children_guard; 50 51 bool * set( bool * val ) { 52 bool * prev = m_ref; 53 m_ref = val; 54 return prev; 55 } 56 57 bool * m_ref = nullptr; 22 template<typename core_t> class Pass; 23 class TranslationUnit; 24 struct PureVisitor; 25 template<typename node_t> node_t * deepCopy( const node_t * ); 26 } 27 28 #ifdef PEDANTIC_PASS_ASSERT 29 #define __pedantic_pass_assert(...) assert(__VA_ARGS__) 30 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 31 #else 32 #define __pedantic_pass_assert(...) 33 #define __pedantic_pass_assertf(...) 34 #endif 35 36 namespace ast::__pass { 37 38 typedef std::function<void( void * )> cleanup_func_t; 39 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 40 41 // boolean reference that may be null 42 // either refers to a boolean value or is null and returns true 43 class bool_ref { 44 public: 45 bool_ref() = default; 46 ~bool_ref() = default; 47 48 operator bool() { return m_ref ? *m_ref : true; } 49 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 50 51 private: 52 53 friend class visit_children_guard; 54 55 bool * set( bool * val ) { 56 bool * prev = m_ref; 57 m_ref = val; 58 return prev; 59 } 60 61 bool * m_ref = nullptr; 62 }; 63 64 // Implementation of the guard value 65 // Created inside the visit scope 66 class guard_value { 67 public: 68 /// Push onto the cleanup 69 guard_value( at_cleanup_t * at_cleanup ) { 70 if( at_cleanup ) { 71 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 72 push( std::move( func ), val ); 73 }; 74 } 75 } 76 77 ~guard_value() { 78 while( !cleanups.empty() ) { 79 auto& cleanup = cleanups.top(); 80 cleanup.func( cleanup.val ); 81 cleanups.pop(); 82 } 83 } 84 85 void push( cleanup_func_t && func, void* val ) { 86 cleanups.emplace( std::move(func), val ); 87 } 88 89 private: 90 struct cleanup_t { 91 cleanup_func_t func; 92 void * val; 93 94 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 58 95 }; 59 96 60 // Implementation of the guard value 61 // Created inside the visit scope 62 class guard_value { 63 public: 64 /// Push onto the cleanup 65 guard_value( at_cleanup_t * at_cleanup ) { 66 if( at_cleanup ) { 67 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 68 push( std::move( func ), val ); 69 }; 97 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups; 98 }; 99 100 // Guard structure implementation for whether or not children should be visited 101 class visit_children_guard { 102 public: 103 104 visit_children_guard( bool_ref * ref ) 105 : m_val ( true ) 106 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 107 , m_ref ( ref ) 108 {} 109 110 ~visit_children_guard() { 111 if( m_ref ) { 112 m_ref->set( m_prev ); 113 } 114 } 115 116 operator bool() { return m_val; } 117 118 private: 119 bool m_val; 120 bool * m_prev; 121 bool_ref * m_ref; 122 }; 123 124 /// "Short hand" to check if this is a valid previsit function 125 /// Mostly used to make the static_assert look (and print) prettier 126 template<typename core_t, typename node_t> 127 struct is_valid_previsit { 128 using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) ); 129 130 static constexpr bool value = std::is_void< ret_t >::value || 131 std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value; 132 }; 133 134 /// The result is a single node. 135 template< typename node_t > 136 struct result1 { 137 bool differs = false; 138 const node_t * value = nullptr; 139 140 template< typename object_t, typename super_t, typename field_t > 141 void apply( object_t * object, field_t super_t::* field ) { 142 object->*field = value; 143 } 144 }; 145 146 /// The result is a container of statements. 147 template< template<class...> class container_t > 148 struct resultNstmt { 149 /// The delta/change on a single node. 150 struct delta { 151 ptr<Stmt> new_val; 152 ssize_t old_idx; 153 bool is_old; 154 155 delta(const Stmt * s, ssize_t i, bool old) : 156 new_val(s), old_idx(i), is_old(old) {} 157 }; 158 159 bool differs = false; 160 container_t< delta > values; 161 162 template< typename object_t, typename super_t, typename field_t > 163 void apply( object_t * object, field_t super_t::* field ) { 164 field_t & container = object->*field; 165 __pedantic_pass_assert( container.size() <= values.size() ); 166 167 auto cit = enumerate(container).begin(); 168 169 container_t<ptr<Stmt>> nvals; 170 for ( delta & d : values ) { 171 if ( d.is_old ) { 172 __pedantic_pass_assert( cit.idx <= d.old_idx ); 173 std::advance( cit, d.old_idx - cit.idx ); 174 nvals.push_back( std::move( (*cit).val ) ); 175 } else { 176 nvals.push_back( std::move( d.new_val ) ); 70 177 } 71 178 } 72 179 73 ~guard_value() { 74 while( !cleanups.empty() ) { 75 auto& cleanup = cleanups.top(); 76 cleanup.func( cleanup.val ); 77 cleanups.pop(); 78 } 79 } 80 81 void push( cleanup_func_t && func, void* val ) { 82 cleanups.emplace( std::move(func), val ); 83 } 84 85 private: 86 struct cleanup_t { 87 cleanup_func_t func; 88 void * val; 89 90 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 91 }; 92 93 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups; 94 }; 95 96 // Guard structure implementation for whether or not children should be visited 97 class visit_children_guard { 98 public: 99 100 visit_children_guard( bool_ref * ref ) 101 : m_val ( true ) 102 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 103 , m_ref ( ref ) 104 {} 105 106 ~visit_children_guard() { 107 if( m_ref ) { 108 m_ref->set( m_prev ); 109 } 110 } 111 112 operator bool() { return m_val; } 113 114 private: 115 bool m_val; 116 bool * m_prev; 117 bool_ref * m_ref; 118 }; 119 120 /// "Short hand" to check if this is a valid previsit function 121 /// Mostly used to make the static_assert look (and print) prettier 180 container = std::move(nvals); 181 } 182 183 template< template<class...> class incontainer_t > 184 void take_all( incontainer_t<ptr<Stmt>> * stmts ) { 185 if ( !stmts || stmts->empty() ) return; 186 187 std::transform( stmts->begin(), stmts->end(), std::back_inserter( values ), 188 [](ast::ptr<ast::Stmt>& stmt) -> delta { 189 return delta( stmt.release(), -1, false ); 190 }); 191 stmts->clear(); 192 differs = true; 193 } 194 195 template< template<class...> class incontainer_t > 196 void take_all( incontainer_t<ptr<Decl>> * decls ) { 197 if ( !decls || decls->empty() ) return; 198 199 std::transform( decls->begin(), decls->end(), std::back_inserter( values ), 200 [](ast::ptr<ast::Decl>& decl) -> delta { 201 ast::Decl const * d = decl.release(); 202 return delta( new DeclStmt( d->location, d ), -1, false ); 203 }); 204 decls->clear(); 205 differs = true; 206 } 207 }; 208 209 /// The result is a container of nodes. 210 template< template<class...> class container_t, typename node_t > 211 struct resultN { 212 bool differs = false; 213 container_t<ptr<node_t>> values; 214 215 template< typename object_t, typename super_t, typename field_t > 216 void apply( object_t * object, field_t super_t::* field ) { 217 field_t & container = object->*field; 218 __pedantic_pass_assert( container.size() == values.size() ); 219 220 for ( size_t i = 0; i < container.size(); ++i ) { 221 // Take all the elements that are different in 'values' 222 // and swap them into 'container' 223 if ( values[i] != nullptr ) swap(container[i], values[i]); 224 } 225 // Now the original containers should still have the unchanged values 226 // but also contain the new values. 227 } 228 }; 229 230 /// Used by previsit implementation 231 /// We need to reassign the result to 'node', unless the function 232 /// returns void, then we just leave 'node' unchanged 233 template<bool is_void> 234 struct __assign; 235 236 template<> 237 struct __assign<true> { 122 238 template<typename core_t, typename node_t> 123 struct is_valid_previsit { 124 using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) ); 125 126 static constexpr bool value = std::is_void< ret_t >::value || 127 std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value; 128 }; 129 130 /// The result is a single node. 131 template< typename node_t > 132 struct result1 { 133 bool differs = false; 134 const node_t * value = nullptr; 135 136 template< typename object_t, typename super_t, typename field_t > 137 void apply( object_t *, field_t super_t::* field ); 138 }; 139 140 /// The result is a container of statements. 141 template< template<class...> class container_t > 142 struct resultNstmt { 143 /// The delta/change on a single node. 144 struct delta { 145 ptr<Stmt> new_val; 146 ssize_t old_idx; 147 bool is_old; 148 149 delta(const Stmt * s, ssize_t i, bool old) : 150 new_val(s), old_idx(i), is_old(old) {} 151 }; 152 153 bool differs = false; 154 container_t< delta > values; 155 156 template< typename object_t, typename super_t, typename field_t > 157 void apply( object_t *, field_t super_t::* field ); 158 159 template< template<class...> class incontainer_t > 160 void take_all( incontainer_t<ptr<Stmt>> * stmts ); 161 162 template< template<class...> class incontainer_t > 163 void take_all( incontainer_t<ptr<Decl>> * decls ); 164 }; 165 166 /// The result is a container of nodes. 167 template< template<class...> class container_t, typename node_t > 168 struct resultN { 169 bool differs = false; 170 container_t<ptr<node_t>> values; 171 172 template< typename object_t, typename super_t, typename field_t > 173 void apply( object_t *, field_t super_t::* field ); 174 }; 175 176 /// Used by previsit implementation 177 /// We need to reassign the result to 'node', unless the function 178 /// returns void, then we just leave 'node' unchanged 179 template<bool is_void> 180 struct __assign; 181 182 template<> 183 struct __assign<true> { 184 template<typename core_t, typename node_t> 185 static inline void result( core_t & core, const node_t * & node ) { 186 core.previsit( node ); 187 } 188 }; 189 190 template<> 191 struct __assign<false> { 192 template<typename core_t, typename node_t> 193 static inline void result( core_t & core, const node_t * & node ) { 194 node = core.previsit( node ); 195 assertf(node, "Previsit must not return NULL"); 196 } 197 }; 198 199 /// Used by postvisit implementation 200 /// We need to return the result unless the function 201 /// returns void, then we just return the original node 202 template<bool is_void> 203 struct __return; 204 205 template<> 206 struct __return<true> { 207 template<typename core_t, typename node_t> 208 static inline const node_t * result( core_t & core, const node_t * & node ) { 209 core.postvisit( node ); 210 return node; 211 } 212 }; 213 214 template<> 215 struct __return<false> { 216 template<typename core_t, typename node_t> 217 static inline auto result( core_t & core, const node_t * & node ) { 218 return core.postvisit( node ); 219 } 220 }; 221 222 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 223 // Deep magic (a.k.a template meta programming) to make the templated visitor work 224 // Basically the goal is to make 2 previsit 225 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 226 // 'pass.previsit( node )' that compiles will be used for that node for that type 227 // This requires that this option only compile for passes that actually define an appropriate visit. 228 // SFINAE will make sure the compilation errors in this function don't halt the build. 229 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 230 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 231 // This is needed only to eliminate the need for passes to specify any kind of handlers. 232 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 233 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 234 // the first implementation takes priority in regards to overloading. 235 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 236 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 239 static inline void result( core_t & core, const node_t * & node ) { 240 core.previsit( node ); 241 } 242 }; 243 244 template<> 245 struct __assign<false> { 237 246 template<typename core_t, typename node_t> 238 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) { 239 static_assert( 240 is_valid_previsit<core_t, node_t>::value, 241 "Previsit may not change the type of the node. It must return its paremeter or void." 242 ); 243 244 __assign< 245 std::is_void< 246 decltype( core.previsit( node ) ) 247 >::value 248 >::result( core, node ); 249 } 250 247 static inline void result( core_t & core, const node_t * & node ) { 248 node = core.previsit( node ); 249 assertf(node, "Previsit must not return NULL"); 250 } 251 }; 252 253 /// Used by postvisit implementation 254 /// We need to return the result unless the function 255 /// returns void, then we just return the original node 256 template<bool is_void> 257 struct __return; 258 259 template<> 260 struct __return<true> { 251 261 template<typename core_t, typename node_t> 252 static inline auto previsit( core_t &, const node_t *, long ) {} 253 254 // PostVisit : never mutates the passed pointer but may return a different node 262 static inline const node_t * result( core_t & core, const node_t * & node ) { 263 core.postvisit( node ); 264 return node; 265 } 266 }; 267 268 template<> 269 struct __return<false> { 255 270 template<typename core_t, typename node_t> 256 static inline auto postvisit( core_t & core, const node_t * node, int ) -> 257 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 258 { 259 return __return< 260 std::is_void< 261 decltype( core.postvisit( node ) ) 262 >::value 263 >::result( core, node ); 264 } 265 266 template<typename core_t, typename node_t> 267 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; } 268 269 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 270 // Deep magic (a.k.a template meta programming) continued 271 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 272 // from in order to get extra functionallity for example 273 // class ErrorChecker : WithShortCircuiting { ... }; 274 // Pass<ErrorChecker> checker; 275 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 276 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 277 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 278 // For several accessories, the feature is enabled by detecting that a specific field is present 279 // Use a macro the encapsulate the logic of detecting a particular field 280 // The type is not strictly enforced but does match the accessory 281 #define FIELD_PTR( name, default_type ) \ 282 template< typename core_t > \ 283 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \ 271 static inline auto result( core_t & core, const node_t * & node ) { 272 return core.postvisit( node ); 273 } 274 }; 275 276 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 277 // Deep magic (a.k.a template meta programming) to make the templated visitor work 278 // Basically the goal is to make 2 previsit 279 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 280 // 'pass.previsit( node )' that compiles will be used for that node for that type 281 // This requires that this option only compile for passes that actually define an appropriate visit. 282 // SFINAE will make sure the compilation errors in this function don't halt the build. 283 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 284 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 285 // This is needed only to eliminate the need for passes to specify any kind of handlers. 286 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 287 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 288 // the first implementation takes priority in regards to overloading. 289 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 290 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 291 template<typename core_t, typename node_t> 292 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) { 293 static_assert( 294 is_valid_previsit<core_t, node_t>::value, 295 "Previsit may not change the type of the node. It must return its paremeter or void." 296 ); 297 298 __assign< 299 std::is_void< 300 decltype( core.previsit( node ) ) 301 >::value 302 >::result( core, node ); 303 } 304 305 template<typename core_t, typename node_t> 306 static inline auto previsit( core_t &, const node_t *, long ) {} 307 308 // PostVisit : never mutates the passed pointer but may return a different node 309 template<typename core_t, typename node_t> 310 static inline auto postvisit( core_t & core, const node_t * node, int ) -> 311 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 312 { 313 return __return< 314 std::is_void< 315 decltype( core.postvisit( node ) ) 316 >::value 317 >::result( core, node ); 318 } 319 320 template<typename core_t, typename node_t> 321 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; } 322 323 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 324 // Deep magic (a.k.a template meta programming) continued 325 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 326 // from in order to get extra functionallity for example 327 // class ErrorChecker : WithShortCircuiting { ... }; 328 // Pass<ErrorChecker> checker; 329 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 330 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 331 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 332 // For several accessories, the feature is enabled by detecting that a specific field is present 333 // Use a macro the encapsulate the logic of detecting a particular field 334 // The type is not strictly enforced but does match the accessory 335 #define FIELD_PTR( name, default_type ) \ 336 template< typename core_t > \ 337 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \ 338 \ 339 template< typename core_t > \ 340 static inline default_type * name( core_t &, long ) { return nullptr; } 341 342 // List of fields and their expected types 343 FIELD_PTR( typeSubs, const ast::TypeSubstitution * ) 344 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 345 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 346 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 347 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 348 FIELD_PTR( visit_children, __pass::bool_ref ) 349 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 350 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 351 352 // Remove the macro to make sure we don't clash 353 #undef FIELD_PTR 354 355 template< typename core_t > 356 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 357 // Stats::Heap::stacktrace_push(core_t::traceId); 358 } 359 360 template< typename core_t > 361 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 362 // Stats::Heap::stacktrace_pop(); 363 } 364 365 template< typename core_t > 366 static void beginTrace(core_t &, long) {} 367 368 template< typename core_t > 369 static void endTrace(core_t &, long) {} 370 371 // Allows visitor to handle an error on top-level declarations, and possibly suppress the error. 372 // If on_error() returns false, the error will be ignored. By default, it returns true. 373 374 template< typename core_t > 375 static bool on_error (core_t &, ptr<Decl> &, long) { return true; } 376 377 template< typename core_t > 378 static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) { 379 return core.on_error(decl); 380 } 381 382 template< typename core_t, typename node_t > 383 static auto make_location_guard( core_t & core, node_t * node, int ) 384 -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) { 385 ValueGuardPtr<const CodeLocation *> guard( &core.location ); 386 core.location = &node->location; 387 return guard; 388 } 389 390 template< typename core_t, typename node_t > 391 static auto make_location_guard( core_t &, node_t *, long ) -> int { 392 return 0; 393 } 394 395 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 396 // All passes which have such functions are assumed desire this behaviour 397 // detect it using the same strategy 398 namespace scope { 399 template<typename core_t> 400 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) { 401 core.beginScope(); 402 } 403 404 template<typename core_t> 405 static inline void enter( core_t &, long ) {} 406 407 template<typename core_t> 408 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) { 409 core.endScope(); 410 } 411 412 template<typename core_t> 413 static inline void leave( core_t &, long ) {} 414 } // namespace scope 415 416 // Certain passes desire an up to date symbol table automatically 417 // detect the presence of a member name `symtab` and call all the members appropriately 418 namespace symtab { 419 // Some simple scoping rules 420 template<typename core_t> 421 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) { 422 core.symtab.enterScope(); 423 } 424 425 template<typename core_t> 426 static inline auto enter( core_t &, long ) {} 427 428 template<typename core_t> 429 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) { 430 core.symtab.leaveScope(); 431 } 432 433 template<typename core_t> 434 static inline auto leave( core_t &, long ) {} 435 436 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 437 // Create macro to condense these common patterns 438 #define SYMTAB_FUNC1( func, type ) \ 439 template<typename core_t> \ 440 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\ 441 core.symtab.func( arg ); \ 442 } \ 284 443 \ 285 template< typename core_t > \ 286 static inline default_type * name( core_t &, long ) { return nullptr; } 287 288 // List of fields and their expected types 289 FIELD_PTR( typeSubs, const ast::TypeSubstitution * ) 290 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 291 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 292 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 293 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 294 FIELD_PTR( visit_children, __pass::bool_ref ) 295 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 296 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 297 298 // Remove the macro to make sure we don't clash 299 #undef FIELD_PTR 300 301 template< typename core_t > 302 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 303 // Stats::Heap::stacktrace_push(core_t::traceId); 304 } 305 306 template< typename core_t > 307 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 308 // Stats::Heap::stacktrace_pop(); 309 } 310 311 template< typename core_t > 312 static void beginTrace(core_t &, long) {} 313 314 template< typename core_t > 315 static void endTrace(core_t &, long) {} 316 317 // Allows visitor to handle an error on top-level declarations, and possibly suppress the error. 318 // If onError() returns false, the error will be ignored. By default, it returns true. 319 320 template< typename core_t > 321 static bool on_error (core_t &, ptr<Decl> &, long) { return true; } 322 323 template< typename core_t > 324 static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) { 325 return core.on_error(decl); 326 } 327 328 template< typename core_t, typename node_t > 329 static auto make_location_guard( core_t & core, node_t * node, int ) 330 -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) { 331 ValueGuardPtr<const CodeLocation *> guard( &core.location ); 332 core.location = &node->location; 333 return guard; 334 } 335 336 template< typename core_t, typename node_t > 337 static auto make_location_guard( core_t &, node_t *, long ) -> int { 338 return 0; 339 } 340 341 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 342 // All passes which have such functions are assumed desire this behaviour 343 // detect it using the same strategy 344 namespace scope { 345 template<typename core_t> 346 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) { 347 core.beginScope(); 348 } 349 350 template<typename core_t> 351 static inline void enter( core_t &, long ) {} 352 353 template<typename core_t> 354 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) { 355 core.endScope(); 356 } 357 358 template<typename core_t> 359 static inline void leave( core_t &, long ) {} 360 } // namespace scope 361 362 // Certain passes desire an up to date symbol table automatically 363 // detect the presence of a member name `symtab` and call all the members appropriately 364 namespace symtab { 365 // Some simple scoping rules 366 template<typename core_t> 367 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) { 368 core.symtab.enterScope(); 369 } 370 371 template<typename core_t> 372 static inline auto enter( core_t &, long ) {} 373 374 template<typename core_t> 375 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) { 376 core.symtab.leaveScope(); 377 } 378 379 template<typename core_t> 380 static inline auto leave( core_t &, long ) {} 381 382 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 383 // Create macro to condense these common patterns 384 #define SYMTAB_FUNC1( func, type ) \ 385 template<typename core_t> \ 386 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\ 387 core.symtab.func( arg ); \ 388 } \ 389 \ 390 template<typename core_t> \ 391 static inline void func( core_t &, long, type ) {} 392 393 #define SYMTAB_FUNC2( func, type1, type2 ) \ 394 template<typename core_t> \ 395 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\ 396 core.symtab.func( arg1, arg2 ); \ 397 } \ 398 \ 399 template<typename core_t> \ 400 static inline void func( core_t &, long, type1, type2 ) {} 401 402 SYMTAB_FUNC1( addId , const DeclWithType * ); 403 SYMTAB_FUNC1( addType , const NamedTypeDecl * ); 404 SYMTAB_FUNC1( addStruct , const StructDecl * ); 405 SYMTAB_FUNC1( addEnum , const EnumDecl * ); 406 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 407 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 408 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl * ); 409 410 // A few extra functions have more complicated behaviour, they are hand written 411 template<typename core_t> 412 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) { 413 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 414 for ( const auto & param : decl->params ) { 415 fwd->params.push_back( deepCopy( param.get() ) ); 416 } 417 core.symtab.addStruct( fwd ); 418 } 419 420 template<typename core_t> 421 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {} 422 423 template<typename core_t> 424 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) { 425 ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name ); 426 for ( const auto & param : decl->params ) { 427 fwd->params.push_back( deepCopy( param.get() ) ); 428 } 429 core.symtab.addUnion( fwd ); 430 } 431 432 template<typename core_t> 433 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {} 434 435 template<typename core_t> 436 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) { 437 if ( ! core.symtab.lookupStruct( str ) ) { 438 core.symtab.addStruct( str ); 439 } 440 } 441 442 template<typename core_t> 443 static inline void addStruct( core_t &, long, const std::string & ) {} 444 445 template<typename core_t> 446 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) { 447 if ( ! core.symtab.lookupUnion( str ) ) { 448 core.symtab.addUnion( str ); 449 } 450 } 451 452 template<typename core_t> 453 static inline void addUnion( core_t &, long, const std::string & ) {} 454 455 #undef SYMTAB_FUNC1 456 #undef SYMTAB_FUNC2 457 } // namespace symtab 458 459 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 460 // Detect the presence of a member name `subs` and call all members appropriately 461 namespace forall { 462 // Some simple scoping rules 463 template<typename core_t> 464 static inline auto enter( core_t & core, int, const ast::FunctionType * type ) 465 -> decltype( core.subs, void() ) { 466 if ( ! type->forall.empty() ) core.subs.beginScope(); 467 } 468 469 template<typename core_t> 470 static inline auto enter( core_t &, long, const ast::FunctionType * ) {} 471 472 template<typename core_t> 473 static inline auto leave( core_t & core, int, const ast::FunctionType * type ) 474 -> decltype( core.subs, void() ) { 475 if ( ! type->forall.empty() ) { core.subs.endScope(); } 476 } 477 478 template<typename core_t> 479 static inline auto leave( core_t &, long, const ast::FunctionType * ) {} 480 481 // Replaces a TypeInstType's base TypeDecl according to the table 482 template<typename core_t> 483 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst ) 484 -> decltype( core.subs, void() ) { 485 inst = ast::mutate_field( 486 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) ); 487 } 488 489 template<typename core_t> 490 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {} 491 492 } // namespace forall 493 494 // For passes that need access to the global context. Sreaches `translationUnit` 495 namespace translation_unit { 496 template<typename core_t> 497 static inline auto get_cptr( core_t & core, int ) 498 -> decltype( &core.translationUnit ) { 499 return &core.translationUnit; 500 } 501 502 template<typename core_t> 503 static inline const TranslationUnit ** get_cptr( core_t &, long ) { 504 return nullptr; 505 } 506 } 507 508 template<typename core_t> 509 static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) { 444 template<typename core_t> \ 445 static inline void func( core_t &, long, type ) {} 446 447 #define SYMTAB_FUNC2( func, type1, type2 ) \ 448 template<typename core_t> \ 449 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\ 450 core.symtab.func( arg1, arg2 ); \ 451 } \ 452 \ 453 template<typename core_t> \ 454 static inline void func( core_t &, long, type1, type2 ) {} 455 456 SYMTAB_FUNC1( addId , const DeclWithType * ); 457 SYMTAB_FUNC1( addType , const NamedTypeDecl * ); 458 SYMTAB_FUNC1( addStruct , const StructDecl * ); 459 SYMTAB_FUNC1( addEnum , const EnumDecl * ); 460 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 461 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 462 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl * ); 463 464 // A few extra functions have more complicated behaviour, they are hand written 465 template<typename core_t> 466 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) { 467 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 468 for ( const auto & param : decl->params ) { 469 fwd->params.push_back( deepCopy( param.get() ) ); 470 } 471 core.symtab.addStruct( fwd ); 472 } 473 474 template<typename core_t> 475 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {} 476 477 template<typename core_t> 478 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) { 479 ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name ); 480 for ( const auto & param : decl->params ) { 481 fwd->params.push_back( deepCopy( param.get() ) ); 482 } 483 core.symtab.addUnion( fwd ); 484 } 485 486 template<typename core_t> 487 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {} 488 489 template<typename core_t> 490 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) { 491 if ( ! core.symtab.lookupStruct( str ) ) { 492 core.symtab.addStruct( str ); 493 } 494 } 495 496 template<typename core_t> 497 static inline void addStruct( core_t &, long, const std::string & ) {} 498 499 template<typename core_t> 500 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) { 501 if ( ! core.symtab.lookupUnion( str ) ) { 502 core.symtab.addUnion( str ); 503 } 504 } 505 506 template<typename core_t> 507 static inline void addUnion( core_t &, long, const std::string & ) {} 508 509 #undef SYMTAB_FUNC1 510 #undef SYMTAB_FUNC2 511 } // namespace symtab 512 513 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 514 // Detect the presence of a member name `subs` and call all members appropriately 515 namespace forall { 516 // Some simple scoping rules 517 template<typename core_t> 518 static inline auto enter( core_t & core, int, const ast::FunctionType * type ) 519 -> decltype( core.subs, void() ) { 520 if ( ! type->forall.empty() ) core.subs.beginScope(); 521 } 522 523 template<typename core_t> 524 static inline auto enter( core_t &, long, const ast::FunctionType * ) {} 525 526 template<typename core_t> 527 static inline auto leave( core_t & core, int, const ast::FunctionType * type ) 528 -> decltype( core.subs, void() ) { 529 if ( ! type->forall.empty() ) { core.subs.endScope(); } 530 } 531 532 template<typename core_t> 533 static inline auto leave( core_t &, long, const ast::FunctionType * ) {} 534 535 // Replaces a TypeInstType's base TypeDecl according to the table 536 template<typename core_t> 537 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst ) 538 -> decltype( core.subs, void() ) { 539 inst = ast::mutate_field( 540 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) ); 541 } 542 543 template<typename core_t> 544 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {} 545 } // namespace forall 546 547 // For passes that need access to the global context. Searches `translationUnit` 548 namespace translation_unit { 549 template<typename core_t> 550 static inline auto get_cptr( core_t & core, int ) 551 -> decltype( &core.translationUnit ) { 552 return &core.translationUnit; 553 } 554 555 template<typename core_t> 556 static inline const TranslationUnit ** get_cptr( core_t &, long ) { 557 return nullptr; 558 } 559 } 560 561 // For passes, usually utility passes, that have a result. 562 namespace result { 563 template<typename core_t> 564 static inline auto get( core_t & core, char ) -> decltype( core.result() ) { 510 565 return core.result(); 511 566 } 512 567 513 568 template<typename core_t> 514 static inline auto get _result( core_t & core, int ) -> decltype( core.result ) {569 static inline auto get( core_t & core, int ) -> decltype( core.result ) { 515 570 return core.result; 516 571 } 517 572 518 573 template<typename core_t> 519 static inline void get_result( core_t &, long ) {} 520 } // namespace __pass 521 } // namespace ast 574 static inline void get( core_t &, long ) {} 575 } 576 577 } // namespace ast::__pass 578 579 #undef __pedantic_pass_assertf 580 #undef __pedantic_pass_assert -
src/AST/Print.cpp
r34b4268 r24d6572 16 16 #include "Print.hpp" 17 17 18 #include "Attribute.hpp" 18 19 #include "Decl.hpp" 19 20 #include "Expr.hpp" 21 #include "Init.hpp" 20 22 #include "Stmt.hpp" 21 23 #include "Type.hpp" 22 24 #include "TypeSubstitution.hpp" 23 25 #include "CompilationState.h" 24 25 #include "Common/utility.h" // for group_iterate 26 #include "Common/Iterate.hpp" 26 27 27 28 using namespace std; … … 29 30 namespace ast { 30 31 31 template <typename C, typename... T> 32 constexpr array<C,sizeof...(T)> make_array(T&&... values) 33 { 34 return array<C,sizeof...(T)>{ 35 std::forward<T>(values)... 36 }; 32 namespace { 33 34 template<typename C, typename... T> 35 constexpr array<C, sizeof...(T)> make_array( T&&... values ) { 36 return array<C, sizeof...(T)>{ std::forward<T>( values )... }; 37 } 38 39 namespace Names { 40 static constexpr auto FuncSpecifiers = make_array<const char*>( 41 "inline", "_Noreturn", "fortran" 42 ); 43 44 static constexpr auto StorageClasses = make_array<const char*>( 45 "extern", "static", "auto", "register", "__thread", "_Thread_local" 46 ); 47 48 static constexpr auto Qualifiers = make_array<const char*>( 49 "const", "restrict", "volatile", "mutex", "_Atomic" 50 ); 51 } 52 53 template<typename bits_t, size_t N> 54 void print( ostream & os, const bits_t & bits, 55 const array<const char *, N> & names ) { 56 if ( !bits.any() ) return; 57 for ( size_t i = 0 ; i < N ; i += 1 ) { 58 if ( bits[i] ) { 59 os << names[i] << ' '; 60 } 61 } 37 62 } 38 63 … … 80 105 static const char* Names[]; 81 106 82 struct Names {83 static constexpr auto FuncSpecifiers = make_array<const char*>(84 "inline", "_Noreturn", "fortran"85 );86 87 static constexpr auto StorageClasses = make_array<const char*>(88 "extern", "static", "auto", "register", "__thread", "_Thread_local"89 );90 91 static constexpr auto Qualifiers = make_array<const char*>(92 "const", "restrict", "volatile", "mutex", "_Atomic"93 );94 };95 96 template<typename storage_t, size_t N>97 void print(const storage_t & storage, const array<const char *, N> & Names ) {98 if ( storage.any() ) {99 for ( size_t i = 0; i < Names.size(); i += 1 ) {100 if ( storage[i] ) {101 os << Names[i] << ' ';102 }103 }104 }105 }106 107 void print( const ast::Function::Specs & specs ) {108 print(specs, Names::FuncSpecifiers);109 }110 111 void print( const ast::Storage::Classes & storage ) {112 print(storage, Names::StorageClasses);113 }114 115 void print( const ast::CV::Qualifiers & qualifiers ) {116 print(qualifiers, Names::Qualifiers);117 }118 119 107 void print( const std::vector<ast::Label> & labels ) { 120 108 if ( labels.empty() ) return; … … 221 209 } 222 210 211 void print( const ast::WaitStmt * node ) { 212 if ( node->timeout_time ) { 213 os << indent-1 << "timeout of:" << endl; 214 node->timeout_time->accept( *this ); 215 216 if ( node->timeout_stmt ) { 217 os << indent-1 << "... with statment:" << endl; 218 node->timeout_stmt->accept( *this ); 219 } 220 221 if ( node->timeout_cond ) { 222 os << indent-1 << "... with condition:" << endl; 223 node->timeout_cond->accept( *this ); 224 } 225 } 226 227 if ( node->else_stmt ) { 228 os << indent-1 << "else:" << endl; 229 node->else_stmt->accept( *this ); 230 231 if ( node->else_cond ) { 232 os << indent-1 << "... with condition:" << endl; 233 node->else_cond->accept( *this ); 234 } 235 } 236 } 237 223 238 void preprint( const ast::NamedTypeDecl * node ) { 224 239 if ( ! node->name.empty() ) { … … 230 245 } 231 246 232 print(node->storage );247 ast::print( os, node->storage ); 233 248 os << node->typeString(); 234 249 … … 272 287 273 288 void preprint( const ast::Type * node ) { 274 print(node->qualifiers );289 ast::print( os, node->qualifiers ); 275 290 } 276 291 … … 278 293 print( node->forall ); 279 294 print( node->assertions ); 280 print(node->qualifiers );295 ast::print( os, node->qualifiers ); 281 296 } 282 297 283 298 void preprint( const ast::BaseInstType * node ) { 284 299 print( node->attributes ); 285 print(node->qualifiers );300 ast::print( os, node->qualifiers ); 286 301 } 287 302 … … 294 309 } 295 310 296 print(node->storage );311 ast::print( os, node->storage ); 297 312 298 313 if ( node->type ) { … … 338 353 if ( ! short_mode ) printAll( node->attributes ); 339 354 340 print( node->storage ); 341 print( node->funcSpec ); 342 343 355 ast::print( os, node->storage ); 356 ast::print( os, node->funcSpec ); 344 357 345 358 if ( node->type && node->isTypeFixed ) { … … 384 397 --indent; 385 398 } 399 } 400 401 if ( ! node->withExprs.empty() ) { 402 // Not with a clause, but the 'with clause'. 403 ++indent; 404 os << " with clause" << endl << indent; 405 printAll( node->withExprs ); 406 --indent; 386 407 } 387 408 … … 746 767 virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final { 747 768 os << "Suspend Statement"; 748 switch (node-> type) {749 case ast::SuspendStmt::None : os << " with implicit target"; break;750 case ast::SuspendStmt::Generator: os << " for generator"; break;751 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;769 switch (node->kind) { 770 case ast::SuspendStmt::None : os << " with implicit target"; break; 771 case ast::SuspendStmt::Generator: os << " for generator"; break; 772 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break; 752 773 } 753 774 os << endl; … … 759 780 } 760 781 ++indent; 782 783 return node; 784 } 785 786 virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final { 787 os << indent-1 << "target: "; 788 safe_print( node->target ); 789 790 if ( node->stmt ) { 791 os << indent-1 << "... with statment:" << endl; 792 node->stmt->accept( *this ); 793 } 794 795 if ( node->when_cond ) { 796 os << indent-1 << "... with when condition:" << endl; 797 node->when_cond->accept( *this ); 798 } 761 799 762 800 return node; … … 800 838 virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final { 801 839 os << indent-1 << "target function: "; 802 safe_print( node->target _func);840 safe_print( node->target ); 803 841 804 842 if ( !node->target_args.empty() ) { … … 814 852 } 815 853 816 if ( node-> cond ) {854 if ( node->when_cond ) { 817 855 os << indent-1 << "... with condition:" << endl; 818 node->cond->accept( *this ); 819 } 820 856 node->when_cond->accept( *this ); 857 } 858 859 return node; 860 } 861 862 virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final { 863 os << "Waituntil Statement" << endl; 864 indent += 2; 865 for( const auto & clause : node->clauses ) { 866 clause->accept( *this ); 867 } 868 print(node); // calls print( const ast::WaitStmt * node ) 821 869 return node; 822 870 } … … 1627 1675 }; 1628 1676 1677 } // namespace 1678 1629 1679 void print( ostream & os, const ast::Node * node, Indenter indent ) { 1630 1680 Printer printer { os, indent, false }; … … 1637 1687 } 1638 1688 1639 // Annoyingly these needed to be defined out of line to avoid undefined references. 1640 // The size here needs to be explicit but at least the compiler will produce an error 1641 // if the wrong size is specified 1642 constexpr array<const char*, 3> Printer::Names::FuncSpecifiers; 1643 constexpr array<const char*, 6> Printer::Names::StorageClasses; 1644 constexpr array<const char*, 5> Printer::Names::Qualifiers; 1689 void print( ostream & os, Function::Specs specs ) { 1690 print( os, specs, Names::FuncSpecifiers ); 1645 1691 } 1692 1693 void print( ostream & os, Storage::Classes storage ) { 1694 print( os, storage, Names::StorageClasses ); 1695 } 1696 1697 void print( ostream & os, CV::Qualifiers qualifiers ) { 1698 print( os, qualifiers, Names::Qualifiers ); 1699 } 1700 1701 } // namespace ast -
src/AST/Print.hpp
r34b4268 r24d6572 16 16 #pragma once 17 17 18 #include <iostream> 19 #include <utility> // for forward 18 #include <iosfwd> 20 19 21 #include "AST/ Node.hpp"20 #include "AST/Fwd.hpp" 22 21 #include "Common/Indenter.h" 23 22 24 23 namespace ast { 25 26 class Decl;27 24 28 25 /// Print a node with the given indenter … … 44 41 } 45 42 43 /// Print each cv-qualifier used in the set, followed by a space. 44 void print( std::ostream & os, CV::Qualifiers ); 45 /// Print each function specifier used in the set, followed by a space. 46 void print( std::ostream & os, Function::Specs ); 47 /// Print each storage class used in the set, followed by a space. 48 void print( std::ostream & os, Storage::Classes ); 49 46 50 } -
src/AST/Stmt.hpp
r34b4268 r24d6572 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 20 14:34:00 202213 // Update Count : 3 612 // Last Modified On : Wed Apr 5 10:34:00 2023 13 // Update Count : 37 14 14 // 15 15 … … 205 205 }; 206 206 207 // A while loop or a do-while loop: 208 enum WhileDoKind { While, DoWhile }; 209 207 210 // While loop: while (...) ... else ... or do ... while (...) else ...; 208 211 class WhileDoStmt final : public Stmt { … … 212 215 ptr<Stmt> else_; 213 216 std::vector<ptr<Stmt>> inits; 214 boolisDoWhile;217 WhileDoKind isDoWhile; 215 218 216 219 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 217 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 218 221 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 219 222 220 223 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 221 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 222 225 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 223 226 … … 364 367 public: 365 368 ptr<CompoundStmt> then; 366 enum Type { None, Coroutine, Generator } type= None;367 368 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )369 : Stmt(loc, std::move(labels)), then(then), type(type) {}369 enum Kind { None, Coroutine, Generator } kind = None; 370 371 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} ) 372 : Stmt(loc, std::move(labels)), then(then), kind(kind) {} 370 373 371 374 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 375 378 }; 376 379 377 // Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...378 class WaitForStmt final : public Stmt { 379 public: 380 std::vector<ptr<WaitForClause>> clauses; 381 ptr<Expr> timeout_time;380 // Base class of WaitFor/WaitUntil statements 381 // form: KEYWORD(...) ... timeout(...) ... else ... 382 class WaitStmt : public Stmt { 383 public: 384 ptr<Expr> timeout_time; 382 385 ptr<Stmt> timeout_stmt; 383 386 ptr<Expr> timeout_cond; … … 385 388 ptr<Expr> else_cond; 386 389 390 WaitStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 391 : Stmt(loc, std::move(labels)) {} 392 393 private: 394 WaitStmt * clone() const override = 0; 395 MUTATE_FRIEND 396 }; 397 398 // Base class for WaitFor/WaitUntil clauses 399 // form: when( when_cond ) KEYWORD( target ) stmt 400 class WhenClause : public StmtClause { 401 public: 402 ptr<Expr> target; 403 ptr<Stmt> stmt; 404 ptr<Expr> when_cond; 405 406 WhenClause( const CodeLocation & loc ) 407 : StmtClause( loc ) {} 408 409 const WhenClause * accept( Visitor & v ) const override { return v.visit( this ); } 410 private: 411 WhenClause * clone() const override { return new WhenClause{ *this }; } 412 MUTATE_FRIEND 413 }; 414 415 // Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ... 416 class WaitForStmt final : public WaitStmt { 417 public: 418 std::vector<ptr<WaitForClause>> clauses; 419 387 420 WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 388 : Stmt(loc, std::move(labels)) {}421 : WaitStmt(loc, std::move(labels)) {} 389 422 390 423 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 394 427 }; 395 428 396 class WaitForClause final : public StmtClause { 397 public: 398 ptr<Expr> target_func; 429 // Clause in a waitfor statement: waitfor (..., ...) ... 430 class WaitForClause final : public WhenClause { 431 public: 399 432 std::vector<ptr<Expr>> target_args; 400 ptr<Stmt> stmt;401 ptr<Expr> cond;402 433 403 434 WaitForClause( const CodeLocation & loc ) 404 : StmtClause( loc ) {}435 : WhenClause( loc ) {} 405 436 406 437 const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); } 407 438 private: 408 439 WaitForClause * clone() const override { return new WaitForClause{ *this }; } 440 MUTATE_FRIEND 441 }; 442 443 // waituntil statement: when (...) waituntil (...) ... timeout(...) ... else ... 444 class WaitUntilStmt final : public WaitStmt { 445 public: 446 // Non-ast node used during compilation to store data needed to generate predicates 447 // and set initial status values for clauses 448 // Used to create a tree corresponding to the structure of the clauses in a WaitUntil 449 struct ClauseNode { 450 enum Op { AND, OR, LEFT_OR, LEAF, ELSE, TIMEOUT } op; // operation/type tag 451 // LEFT_OR used with TIMEOUT/ELSE to indicate that we ignore right hand side after parsing 452 453 ClauseNode * left; 454 ClauseNode * right; 455 WhenClause * leaf; // only set if this node is a leaf (points into vector of clauses) 456 457 bool ambiguousWhen; // used to paint nodes of predicate tree based on when() clauses 458 bool whenState; // used to track if when_cond is toggled on or off for generating init values 459 bool childOfAnd; // true on leaf nodes that are children of AND, false otherwise 460 461 ClauseNode( Op op, ClauseNode * left, ClauseNode * right ) 462 : op(op), left(left), right(right), leaf(nullptr), 463 ambiguousWhen(false), whenState(true), childOfAnd(false) {} 464 ClauseNode( Op op, WhenClause * leaf ) 465 : op(op), left(nullptr), right(nullptr), leaf(leaf), 466 ambiguousWhen(false), whenState(true), childOfAnd(false) {} 467 ClauseNode( WhenClause * leaf ) : ClauseNode(LEAF, leaf) {} 468 469 ~ClauseNode() { 470 if ( left ) delete left; 471 if ( right ) delete right; 472 } 473 }; 474 475 std::vector<ptr<WhenClause>> clauses; 476 ClauseNode * predicateTree; 477 478 WaitUntilStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 479 : WaitStmt(loc, std::move(labels)) {} 480 481 ~WaitUntilStmt() { delete predicateTree; } 482 483 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } 484 private: 485 WaitUntilStmt * clone() const override { return new WaitUntilStmt{ *this }; } 409 486 MUTATE_FRIEND 410 487 }; … … 454 531 MUTATE_FRIEND 455 532 }; 533 456 534 } // namespace ast 457 535 -
src/AST/SymbolTable.cpp
r34b4268 r24d6572 18 18 #include <cassert> 19 19 20 #include "Copy.hpp" 21 #include <iostream> 22 #include <algorithm> 23 20 24 #include "Decl.hpp" 21 25 #include "Expr.hpp" 22 26 #include "Inspect.hpp" 23 27 #include "Type.hpp" 24 #include "CodeGen/OperatorTable.h" // for isCtorDtorAssign28 #include "CodeGen/OperatorTable.h" // for isCtorDtorAssign 25 29 #include "Common/SemanticError.h" 26 30 #include "Common/Stats/Counter.h" … … 28 32 #include "InitTweak/InitTweak.h" 29 33 #include "ResolvExpr/Cost.h" 30 #include "ResolvExpr/typeops.h" 34 #include "ResolvExpr/CandidateFinder.hpp" // for referenceToRvalueConversion 35 #include "ResolvExpr/Unify.h" 31 36 #include "SymTab/Mangler.h" 32 37 … … 69 74 if ( baseExpr ) { 70 75 if (baseExpr->env) { 71 Expr * base = shallowCopy(baseExpr);76 Expr * base = deepCopy(baseExpr); 72 77 const TypeSubstitution * subs = baseExpr->env; 73 78 base->env = nullptr; … … 193 198 out.push_back(decl.second); 194 199 } 200 201 // std::cerr << otypeKey << ' ' << out.size() << std::endl; 195 202 } 196 203 … … 259 266 void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) { 260 267 // default handling of conflicts is to raise an error 261 addId ( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );268 addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 262 269 } 263 270 264 271 void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) { 265 272 // default handling of conflicts is to raise an error 266 addId ( decl, OnConflict::error(), nullptr, deleter );273 addIdCommon( decl, OnConflict::error(), nullptr, deleter ); 267 274 } 268 275 … … 276 283 } else { 277 284 // typedef redeclarations are errors only if types are different 278 if ( ! ResolvExpr::typesCompatible( existing->base, added->base , SymbolTable{}) ) {285 if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) { 279 286 SemanticError( added->location, "redeclaration of " + added->name ); 280 287 } … … 641 648 } else if ( existing.id->linkage.is_mangled 642 649 || ResolvExpr::typesCompatible( 643 added->get_type(), existing.id->get_type() , SymbolTable{}) ) {650 added->get_type(), existing.id->get_type() ) ) { 644 651 645 652 // it is a conflict if one declaration is deleted and the other is not … … 676 683 } 677 684 678 void SymbolTable::addId (679 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,680 const Decl * deleter ) {685 void SymbolTable::addIdCommon( 686 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, 687 const Expr * baseExpr, const Decl * deleter ) { 681 688 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 682 689 if (kind == NUMBER_OF_KINDS) { // not a special decl 683 addId (decl, decl->name, idTable, handleConflicts, baseExpr, deleter);690 addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter); 684 691 } 685 692 else { … … 694 701 assertf(false, "special decl with non-function type"); 695 702 } 696 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 697 } 698 } 699 700 void SymbolTable::addId( 701 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 702 const Decl * deleter ) { 703 addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 704 } 705 } 706 707 void SymbolTable::addIdToTable( 708 const DeclWithType * decl, const std::string & lookupKey, 709 IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, 710 const Expr * baseExpr, const Decl * deleter ) { 703 711 ++*stats().add_calls; 704 712 const std::string &name = decl->name; … … 777 785 void SymbolTable::addMembers( 778 786 const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) { 779 for ( const Decl *decl : aggr->members ) {780 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {781 addId( dwt, handleConflicts, expr );782 if ( dwt->name == "" ) {783 const Type * t = dwt->get_type()->stripReferences();784 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {785 if ( ! dynamic_cast<const StructInstType *>(rty)786 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;787 ResolvExpr::Cost cost = ResolvExpr::Cost::zero;788 ast::ptr<ast::TypeSubstitution> tmp = expr->env;789 expr = mutate_field(expr, &Expr::env, nullptr);790 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );791 base = mutate_field(base, &Expr::env, tmp);792 793 addMembers(794 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 795 }796 }787 for ( const ptr<Decl> & decl : aggr->members ) { 788 auto dwt = decl.as<DeclWithType>(); 789 if ( nullptr == dwt ) continue; 790 addIdCommon( dwt, handleConflicts, expr ); 791 // Inline through unnamed struct/union members. 792 if ( "" != dwt->name ) continue; 793 const Type * t = dwt->get_type()->stripReferences(); 794 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 795 if ( ! dynamic_cast<const StructInstType *>(rty) 796 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; 797 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; 798 ast::ptr<ast::TypeSubstitution> tmp = expr->env; 799 expr = mutate_field(expr, &Expr::env, nullptr); 800 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost ); 801 base = mutate_field(base, &Expr::env, tmp); 802 803 addMembers( 804 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 797 805 } 798 806 } -
src/AST/SymbolTable.hpp
r34b4268 r24d6572 192 192 193 193 /// common code for addId, addDeletedId, etc. 194 void addId (195 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,196 const Decl * deleter = nullptr );194 void addIdCommon( 195 const DeclWithType * decl, OnConflict handleConflicts, 196 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr ); 197 197 198 198 /// common code for addId when special decls are placed into separate tables 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 199 void addIdToTable( 200 const DeclWithType * decl, const std::string & lookupKey, 201 IdTable::Ptr & idTable, OnConflict handleConflicts, 201 202 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 202 203 203 204 /// adds all of the members of the Aggregate (addWith helper) 204 205 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/TranslationUnit.hpp
r34b4268 r24d6572 10 10 // Created On : Tue Jun 11 15:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Mar 11 11:19:00 202213 // Update Count : 112 // Last Modified On : Thr Mar 9 16:41:00 2023 13 // Update Count : 2 14 14 // 15 15 … … 17 17 18 18 #include <map> 19 #include < vector>19 #include <list> 20 20 21 21 #include "Fwd.hpp" … … 28 28 29 29 ptr<Type> sizeType; 30 const FunctionDecl * dereference ;31 const StructDecl * dtorStruct ;32 const FunctionDecl * dtorDestroy ;30 const FunctionDecl * dereference = nullptr; 31 const StructDecl * dtorStruct = nullptr; 32 const FunctionDecl * dtorDestroy = nullptr; 33 33 }; 34 34 -
src/AST/Type.cpp
r34b4268 r24d6572 10 10 // Created On : Mon May 13 15:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:49:00 202213 // Update Count : 612 // Last Modified On : Thu Apr 6 15:59:00 2023 13 // Update Count : 7 14 14 // 15 15 … … 199 199 200 200 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 201 : Type( q ), types( std::move(ts) ), members() { 202 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 203 // named, but members without initializer nodes end up getting constructors, which breaks 204 // things. This happens because the object decls have to be visited so that their types are 205 // kept in sync with the types listed here. Ultimately, the types listed here should perhaps 206 // be eliminated and replaced with a list-view over members. The temporary solution is to 207 // make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not 208 // constructed. Potential better solutions include: 209 // a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`, 210 // similar to the aggregate types. 211 // b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced 212 // by `genInit`, rather than the current boolean flag. 213 members.reserve( types.size() ); 214 for ( const Type * ty : types ) { 215 members.emplace_back( new ObjectDecl{ 216 CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ), 217 Storage::Classes{}, Linkage::Cforall } ); 218 } 219 } 201 : Type( q ), types( std::move(ts) ) {} 220 202 221 203 bool isUnboundType(const Type * type) { -
src/AST/Type.hpp
r34b4268 r24d6572 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:47:00 202213 // Update Count : 812 // Last Modified On : Thu Apr 6 15:58:00 2023 13 // Update Count : 9 14 14 // 15 15 … … 265 265 }; 266 266 267 /// Function variable arguments flag268 enum ArgumentFlag { FixedArgs, VariableArgs };269 270 267 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 271 268 class FunctionType final : public Type { … … 462 459 public: 463 460 std::vector<ptr<Type>> types; 464 std::vector<ptr<Decl>> members;465 461 466 462 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} ); -
src/AST/TypeEnvironment.cpp
r34b4268 r24d6572 178 178 179 179 bool TypeEnvironment::combine( 180 const TypeEnvironment & o, OpenVarSet & open , const SymbolTable & symtab) {180 const TypeEnvironment & o, OpenVarSet & open ) { 181 181 // short-circuit easy cases 182 182 if ( o.empty() ) return true; … … 201 201 EqvClass & r = *rt; 202 202 // merge bindings 203 if ( ! mergeBound( r, c, open , symtab) ) return false;203 if ( ! mergeBound( r, c, open ) ) return false; 204 204 // merge previous unbound variables into this class, checking occurs if needed 205 205 if ( r.bound ) for ( const auto & u : c.vars ) { … … 216 216 } else if ( st != rt ) { 217 217 // bound, but not to the same class 218 if ( ! mergeClasses( rt, st, open , symtab) ) return false;218 if ( ! mergeClasses( rt, st, open ) ) return false; 219 219 } // ignore bound into the same class 220 220 } … … 280 280 bool TypeEnvironment::bindVar( 281 281 const TypeInstType * typeInst, const Type * bindTo, const TypeData & data, 282 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 283 const SymbolTable & symtab 282 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen 284 283 ) { 285 284 // remove references from bound type, so that type variables can only bind to value types … … 300 299 if ( unifyInexact( 301 300 newType, target, *this, need, have, open, 302 widen & WidenMode{ it->allowWidening, true }, symtab,common ) ) {301 widen & WidenMode{ it->allowWidening, true }, common ) ) { 303 302 if ( common ) { 304 303 it->bound = std::move(common); … … 321 320 const TypeInstType * var1, const TypeInstType * var2, TypeData && data, 322 321 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 323 WidenMode widen , const SymbolTable & symtab322 WidenMode widen 324 323 ) { 325 324 auto c1 = internal_lookup( *var1 ); … … 358 357 359 358 if ( unifyInexact( 360 newType1, newType2, *this, need, have, open, newWidenMode, symtab,common ) ) {359 newType1, newType2, *this, need, have, open, newWidenMode, common ) ) { 361 360 c1->vars.insert( c2->vars.begin(), c2->vars.end() ); 362 361 c1->allowWidening = widen1 && widen2; … … 409 408 410 409 bool TypeEnvironment::mergeBound( 411 EqvClass & to, const EqvClass & from, OpenVarSet & open , const SymbolTable & symtab) {410 EqvClass & to, const EqvClass & from, OpenVarSet & open ) { 412 411 if ( from.bound ) { 413 412 if ( to.bound ) { … … 419 418 420 419 if ( unifyInexact( 421 toType, fromType, *this, need, have, open, widen, symtab,common ) ) {420 toType, fromType, *this, need, have, open, widen, common ) ) { 422 421 // unifies, set common type if necessary 423 422 if ( common ) { … … 437 436 438 437 bool TypeEnvironment::mergeClasses( 439 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open , const SymbolTable & symtab438 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open 440 439 ) { 441 440 EqvClass & r = *to, & s = *from; 442 441 443 442 // ensure bounds match 444 if ( ! mergeBound( r, s, open , symtab) ) return false;443 if ( ! mergeBound( r, s, open ) ) return false; 445 444 446 445 // check safely bindable -
src/AST/TypeEnvironment.hpp
r34b4268 r24d6572 63 63 64 64 int cmp = d1->var->name.compare( d2->var->name ); 65 return cmp <0 || ( cmp == 0 && d1->result < d2->result );65 return cmp > 0 || ( cmp == 0 && d1->result < d2->result ); 66 66 } 67 67 }; … … 169 169 /// Merge environment with this one, checking compatibility. 170 170 /// Returns false if fails, but does NOT roll back partial changes. 171 bool combine( const TypeEnvironment & o, OpenVarSet & openVars , const SymbolTable & symtab);171 bool combine( const TypeEnvironment & o, OpenVarSet & openVars ); 172 172 173 173 /// Add all type variables in environment to open var list … … 183 183 const TypeInstType * typeInst, const Type * bindTo, const TypeData & data, 184 184 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 185 ResolvExpr::WidenMode widen , const SymbolTable & symtab);185 ResolvExpr::WidenMode widen ); 186 186 187 187 /// Binds the type classes represented by `var1` and `var2` together; will add one or both … … 190 190 const TypeInstType * var1, const TypeInstType * var2, TypeData && data, 191 191 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 192 ResolvExpr::WidenMode widen , const SymbolTable & symtab);192 ResolvExpr::WidenMode widen ); 193 193 194 194 /// Disallows widening for all bindings in the environment … … 205 205 /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails 206 206 bool mergeBound( 207 EqvClass & to, const EqvClass & from, OpenVarSet & openVars , const SymbolTable & symtab);207 EqvClass & to, const EqvClass & from, OpenVarSet & openVars ); 208 208 209 209 /// Merges two type classes from local environment, returning false if fails 210 210 bool mergeClasses( 211 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 212 const SymbolTable & symtab ); 211 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars); 213 212 214 213 /// Private lookup API; returns array index of string, or env.size() for not found -
src/AST/TypeSubstitution.cpp
r34b4268 r24d6572 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:26:00 2017 13 // Update Count : 5 14 // 12 // Last Modified On : Thr May 25 11:24:00 2023 13 // Update Count : 6 14 // 15 16 #include "TypeSubstitution.hpp" 15 17 16 18 #include "Type.hpp" // for TypeInstType, Type, StructInstType, UnionInstType 17 #include " TypeSubstitution.hpp"19 #include "Pass.hpp" // for Pass, PureVisitor, WithGuards, WithVisitorRef 18 20 19 21 namespace ast { 20 21 22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");23 22 24 23 TypeSubstitution::TypeSubstitution() { … … 119 118 } 120 119 120 // definitition must happen after PassVisitor is included so that WithGuards can be used 121 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor { 122 //static size_t traceId; 123 124 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 125 126 const Type * postvisit( const TypeInstType * aggregateUseType ); 127 128 /// Records type variable bindings from forall-statements 129 void previsit( const FunctionType * type ); 130 /// Records type variable bindings from forall-statements and instantiations of generic types 131 // void handleAggregateType( const BaseInstType * type ); 132 133 // void previsit( const StructInstType * aggregateUseType ); 134 // void previsit( const UnionInstType * aggregateUseType ); 135 136 const TypeSubstitution & sub; 137 int subCount = 0; 138 bool freeOnly; 139 typedef std::unordered_set< TypeEnvKey > BoundVarsType; 140 BoundVarsType boundVars; 141 }; 142 143 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution"); 144 121 145 void TypeSubstitution::normalize() { 122 146 Pass<Substituter> sub( *this, true ); … … 128 152 } 129 153 } while ( sub.core.subCount ); 154 } 155 156 TypeSubstitution::ApplyResult<Node> TypeSubstitution::applyBase( 157 const Node * input, bool isFree ) const { 158 assert( input ); 159 Pass<Substituter> sub( *this, isFree ); 160 const Node * output = input->accept( sub ); 161 return { output, sub.core.subCount }; 130 162 } 131 163 -
src/AST/TypeSubstitution.hpp
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue Apr 30 22:52:47 201913 // Update Count : 911 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 25 12:31:00 2023 13 // Update Count : 10 14 14 // 15 15 … … 46 46 TypeSubstitution &operator=( const TypeSubstitution &other ); 47 47 48 template< typename SynTreeClass>48 template< typename node_t > 49 49 struct ApplyResult { 50 ast::ptr< SynTreeClass> node;50 ast::ptr<node_t> node; 51 51 int count; 52 52 }; 53 53 54 template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const; 55 template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const; 54 template< typename node_t > 55 ApplyResult<node_t> apply( const node_t * input ) const { 56 ApplyResult<Node> ret = applyBase( input, false ); 57 return { ret.node.strict_as<node_t>(), ret.count }; 58 } 56 59 57 60 template< typename node_t, enum Node::ref_type ref_t > 58 61 int apply( ptr_base< node_t, ref_t > & input ) const { 59 const node_t * p = input.get(); 60 auto ret = apply(p); 61 input = ret.node; 62 ApplyResult<Node> ret = applyBase( input.get(), false ); 63 input = ret.node.strict_as<node_t>(); 62 64 return ret.count; 65 } 66 67 template< typename node_t > 68 ApplyResult<node_t> applyFree( const node_t * input ) const { 69 ApplyResult<Node> ret = applyBase( input, true ); 70 return { ret.node.strict_as<node_t>(), ret.count }; 63 71 } 64 72 65 73 template< typename node_t, enum Node::ref_type ref_t > 66 74 int applyFree( ptr_base< node_t, ref_t > & input ) const { 67 const node_t * p = input.get(); 68 auto ret = applyFree(p); 69 input = ret.node; 75 ApplyResult<Node> ret = applyBase( input.get(), true ); 76 input = ret.node.strict_as<node_t>(); 70 77 return ret.count; 71 78 } … … 97 104 // Mutator that performs the substitution 98 105 struct Substituter; 106 ApplyResult<Node> applyBase( const Node * input, bool isFree ) const; 99 107 100 108 // TODO: worry about traversing into a forall-qualified function type or type decl with assertions … … 158 166 } // namespace ast 159 167 160 // include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and161 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.162 #include "Pass.hpp"163 #include "Copy.hpp"164 165 namespace ast {166 167 // definitition must happen after PassVisitor is included so that WithGuards can be used168 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {169 static size_t traceId;170 171 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}172 173 const Type * postvisit( const TypeInstType * aggregateUseType );174 175 /// Records type variable bindings from forall-statements176 void previsit( const FunctionType * type );177 /// Records type variable bindings from forall-statements and instantiations of generic types178 // void handleAggregateType( const BaseInstType * type );179 180 // void previsit( const StructInstType * aggregateUseType );181 // void previsit( const UnionInstType * aggregateUseType );182 183 const TypeSubstitution & sub;184 int subCount = 0;185 bool freeOnly;186 typedef std::unordered_set< TypeEnvKey > BoundVarsType;187 BoundVarsType boundVars;188 189 };190 191 template< typename SynTreeClass >192 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {193 assert( input );194 Pass<Substituter> sub( *this, false );195 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );196 return { input, sub.core.subCount };197 }198 199 template< typename SynTreeClass >200 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {201 assert( input );202 Pass<Substituter> sub( *this, true );203 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );204 return { input, sub.core.subCount };205 }206 207 } // namespace ast208 209 168 // Local Variables: // 210 169 // tab-width: 4 // -
src/AST/Visitor.hpp
r34b4268 r24d6572 50 50 virtual const ast::FinallyClause * visit( const ast::FinallyClause * ) = 0; 51 51 virtual const ast::Stmt * visit( const ast::SuspendStmt * ) = 0; 52 virtual const ast::WhenClause * visit( const ast::WhenClause * ) = 0; 52 53 virtual const ast::Stmt * visit( const ast::WaitForStmt * ) = 0; 53 54 virtual const ast::WaitForClause * visit( const ast::WaitForClause * ) = 0; 55 virtual const ast::Stmt * visit( const ast::WaitUntilStmt * ) = 0; 54 56 virtual const ast::Decl * visit( const ast::WithStmt * ) = 0; 55 57 virtual const ast::NullStmt * visit( const ast::NullStmt * ) = 0; -
src/AST/porting.md
r34b4268 r24d6572 213 213 * `get_statement()` exclusively used for code location, replaced with `CodeLocation` field 214 214 215 `CaseStmt` 215 `CaseStmt` => `CaseClause` 216 216 * `_isDefault` has been removed 217 217 * `isDefault` calculates value from `cond` … … 227 227 * `block` -> `body` and `finallyBlock` -> `finally` 228 228 229 `ThrowStmt` `CatchStmt`229 `ThrowStmt` and `CatchStmt` => `CatchClause` 230 230 * moved `Kind` enums to shared `ast::ExceptionKind` enum 231 231 232 `FinallyStmt` 232 `FinallyStmt` => `FinallyClause` 233 233 * `block` -> `body` 234 234 … … 280 280 * Template class, with specializations and using to implement some other types: 281 281 * `StructInstType`, `UnionInstType` & `EnumInstType` 282 * `baseStruct`, `baseUnion` & `baseEnum` => `base` 282 283 283 284 `TypeInstType` -
src/CodeGen/CodeGenerator.cc
r34b4268 r24d6572 17 17 #include <cassert> // for assert, assertf 18 18 #include <list> // for _List_iterator, list, list<>::it... 19 #include <sstream> // for stringstream 19 20 20 21 #include "AST/Decl.hpp" // for DeclWithType 21 22 #include "Common/UniqueName.h" // for UniqueName 22 #include "Common/utility.h" // for CodeLocation, toString23 23 #include "GenType.h" // for genType 24 24 #include "InitTweak/InitTweak.h" // for getPointerBase … … 273 273 } 274 274 275 template<typename pass_type> 276 inline void genEnumInitializer( PassVisitor<pass_type> * visitor, Type * baseType, std::ostream & output, 277 Initializer * init, long long * cur_val, Options options) { 278 auto baseTypeAsBasic = baseType ? dynamic_cast<BasicType *>( baseType ) : nullptr; 279 if ( init ) { // If value has an explicit initiazatior 280 output << " = "; 281 output << "(" << genType(baseType, "", options) << ")"; 282 init->accept( *visitor ); 283 if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // if it is an integral type and initilizer offered, 284 // need to update the cur_val 285 Expression* expr = ((SingleInit *)(init))->value; 286 while ( auto temp = dynamic_cast<CastExpr *>(expr) ) { // unwrap introduced cast 287 expr = temp->arg; 288 } 289 *cur_val = ((ConstantExpr *)expr)->constant.get_ival()+1; 290 } 291 } else if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // integral implicitly init to cur_val + 1 292 output << " = " << "(" << genType(baseType, "", options) << ")"; 293 output << (*cur_val)++; 294 } 295 } 296 275 297 void CodeGenerator::postvisit( EnumDecl * enumDecl ) { 276 298 extension( enumDecl ); 277 299 std::list< Declaration* > &memb = enumDecl->get_members(); 278 300 if (enumDecl->base && ! memb.empty()) { 279 unsigned long long last_val = -1; // if the first enum value has no explicit initializer, 280 // as other 301 long long cur_val = 0; 281 302 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) { 282 303 ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i ); 283 304 assert( obj ); 284 305 output << "static "; 285 output << genType(enumDecl->base, "", options) << " const "; 286 output << mangleName( obj ) << " "; 287 output << " = "; 288 output << "(" << genType(enumDecl->base, "", options) << ")"; 289 if ( (BasicType *)(enumDecl->base) && ((BasicType *)(enumDecl->base))->isWholeNumber() ) { 290 if ( obj->get_init() ) { 291 obj->get_init()->accept( *visitor ); 292 Expression* expr = ((SingleInit *)(obj->init))->value; 293 while ( auto temp = dynamic_cast<CastExpr *>(expr) ) { 294 expr = temp->arg; 295 } 296 last_val = ((ConstantExpr *)expr)->constant.get_ival(); 297 } else { 298 output << ++last_val; 299 } // if 300 } else { 301 if ( obj->get_init() ) { 302 obj->get_init()->accept( *visitor ); 303 } else { 304 // Should not reach here! 305 } 306 } 306 output << genType(enumDecl->base, mangleName( obj ), options); 307 genEnumInitializer( visitor, enumDecl->base, output, obj->get_init(), &cur_val, options); 307 308 output << ";" << endl; 308 309 } // for -
src/CodeGen/GenType.cc
r34b4268 r24d6572 255 255 void GenType::postvisit( EnumInstType * enumInst ) { 256 256 if ( enumInst->baseEnum && enumInst->baseEnum->base ) { 257 typeString = genType(enumInst->baseEnum->base, "", options) + typeString;257 typeString = genType(enumInst->baseEnum->base, typeString, options); 258 258 } else { 259 259 typeString = enumInst->name + " " + typeString; -
src/Common/CodeLocationTools.cpp
r34b4268 r24d6572 128 128 macro(FinallyClause, FinallyClause) \ 129 129 macro(SuspendStmt, Stmt) \ 130 macro(WhenClause, WhenClause) \ 130 131 macro(WaitForStmt, Stmt) \ 131 132 macro(WaitForClause, WaitForClause) \ 133 macro(WaitUntilStmt, Stmt) \ 132 134 macro(WithStmt, Decl) \ 133 135 macro(NullStmt, NullStmt) \ … … 208 210 209 211 struct LeafKindVisitor : public ast::Visitor { 210 LeafKind kind;212 LeafKind result; 211 213 212 214 #define VISIT(node_type, return_type) \ 213 215 const ast::return_type * visit( const ast::node_type * ) final { \ 214 kind= LeafKind::node_type; \216 result = LeafKind::node_type; \ 215 217 return nullptr; \ 216 218 } … … 222 224 223 225 LeafKind get_leaf_kind( ast::Node const * node ) { 224 LeafKindVisitor visitor; 225 node->accept( visitor ); 226 return visitor.kind; 226 return ast::Pass<LeafKindVisitor>::read( node ); 227 227 } 228 228 -
src/Common/DeclStats.cpp
r34b4268 r24d6572 23 23 #include <iostream> 24 24 #include <map> 25 #include <sstream> 25 26 #include <unordered_map> 26 27 #include <unordered_set> -
src/Common/Eval.cc
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h --7 // Eval.cc -- Evaluate parts of the ast at compile time. 8 8 // 9 9 // Author : Richard C. Bilson … … 13 13 // Update Count : 119 14 14 // 15 16 #include "Eval.h" 15 17 16 18 #include <utility> // for pair -
src/Common/ResolvProtoDump.cpp
r34b4268 r24d6572 19 19 #include <iostream> 20 20 #include <set> 21 #include <sstream> 21 22 #include <unordered_set> 22 23 … … 26 27 #include "AST/Type.hpp" 27 28 #include "CodeGen/OperatorTable.h" 28 #include "Common/utility.h"29 29 30 30 namespace { -
src/Common/ScopedMap.h
r34b4268 r24d6572 37 37 template<typename N> 38 38 Scope(N && n) : map(), note(std::forward<N>(n)) {} 39 39 40 40 Scope() = default; 41 41 Scope(const Scope &) = default; … … 46 46 typedef std::vector< Scope > ScopeList; 47 47 48 ScopeList scopes; ///< scoped list of maps 48 /// Scoped list of maps. 49 ScopeList scopes; 49 50 public: 50 51 typedef typename MapType::key_type key_type; … … 58 59 typedef typename MapType::const_pointer const_pointer; 59 60 60 class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > { 61 friend class ScopedMap; 62 friend class const_iterator; 63 typedef typename ScopedMap::MapType::iterator wrapped_iterator; 64 typedef typename ScopedMap::ScopeList scope_list; 65 typedef typename scope_list::size_type size_type; 66 67 /// Checks if this iterator points to a valid item 68 bool is_valid() const { 69 return it != (*scopes)[level].map.end(); 70 } 71 72 /// Increments on invalid 73 iterator & next_valid() { 74 if ( ! is_valid() ) { ++(*this); } 75 return *this; 76 } 77 78 /// Decrements on invalid 79 iterator & prev_valid() { 80 if ( ! is_valid() ) { --(*this); } 81 return *this; 82 } 83 84 iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel) 85 : scopes(&_scopes), it(_it), level(inLevel) {} 86 public: 87 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 88 iterator & operator= (const iterator & that) { 89 scopes = that.scopes; level = that.level; it = that.it; 90 return *this; 91 } 92 93 reference operator* () { return *it; } 94 pointer operator-> () const { return it.operator->(); } 95 96 iterator & operator++ () { 97 if ( it == (*scopes)[level].map.end() ) { 98 if ( level == 0 ) return *this; 99 --level; 100 it = (*scopes)[level].map.begin(); 101 } else { 102 ++it; 103 } 104 return next_valid(); 105 } 106 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } 107 108 iterator & operator-- () { 109 // may fail if this is the begin iterator; allowed by STL spec 110 if ( it == (*scopes)[level].map.begin() ) { 111 ++level; 112 it = (*scopes)[level].map.end(); 113 } 114 --it; 115 return prev_valid(); 116 } 117 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; } 118 119 bool operator== (const iterator & that) const { 120 return scopes == that.scopes && level == that.level && it == that.it; 121 } 122 bool operator!= (const iterator & that) const { return !( *this == that ); } 123 124 size_type get_level() const { return level; } 125 126 Note & get_note() { return (*scopes)[level].note; } 127 const Note & get_note() const { return (*scopes)[level].note; } 128 129 private: 130 scope_list *scopes; 131 wrapped_iterator it; 132 size_type level; 133 }; 134 135 class const_iterator : public std::iterator< std::bidirectional_iterator_tag, 136 value_type > { 137 friend class ScopedMap; 138 typedef typename ScopedMap::MapType::iterator wrapped_iterator; 139 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator; 140 typedef typename ScopedMap::ScopeList scope_list; 141 typedef typename scope_list::size_type size_type; 142 143 /// Checks if this iterator points to a valid item 144 bool is_valid() const { 145 return it != (*scopes)[level].map.end(); 146 } 147 148 /// Increments on invalid 149 const_iterator & next_valid() { 150 if ( ! is_valid() ) { ++(*this); } 151 return *this; 152 } 153 154 /// Decrements on invalid 155 const_iterator & prev_valid() { 156 if ( ! is_valid() ) { --(*this); } 157 return *this; 158 } 159 160 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel) 161 : scopes(&_scopes), it(_it), level(inLevel) {} 162 public: 163 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 164 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 165 const_iterator & operator= (const iterator & that) { 166 scopes = that.scopes; level = that.level; it = that.it; 167 return *this; 168 } 169 const_iterator & operator= (const const_iterator & that) { 170 scopes = that.scopes; level = that.level; it = that.it; 171 return *this; 172 } 173 174 const_reference operator* () { return *it; } 175 const_pointer operator-> () { return it.operator->(); } 176 177 const_iterator & operator++ () { 178 if ( it == (*scopes)[level].map.end() ) { 179 if ( level == 0 ) return *this; 180 --level; 181 it = (*scopes)[level].map.begin(); 182 } else { 183 ++it; 184 } 185 return next_valid(); 186 } 187 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } 188 189 const_iterator & operator-- () { 190 // may fail if this is the begin iterator; allowed by STL spec 191 if ( it == (*scopes)[level].map.begin() ) { 192 ++level; 193 it = (*scopes)[level].map.end(); 194 } 195 --it; 196 return prev_valid(); 197 } 198 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } 199 200 bool operator== (const const_iterator & that) const { 201 return scopes == that.scopes && level == that.level && it == that.it; 202 } 203 bool operator!= (const const_iterator & that) const { return !( *this == that ); } 204 205 size_type get_level() const { return level; } 206 207 const Note & get_note() const { return (*scopes)[level].note; } 208 209 private: 210 scope_list const *scopes; 211 wrapped_const_iterator it; 212 size_type level; 213 }; 61 // Both iterator types are complete bidrectional iterators, see below. 62 class iterator; 63 class const_iterator; 214 64 215 65 /// Starts a new scope … … 297 147 } 298 148 299 template< typename value_type_t >300 std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {301 MapType & scope = (*at.scopes)[ at.level ].map;302 std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );303 return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );304 }305 306 149 template< typename value_t > 307 150 std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); } … … 324 167 } 325 168 326 iterator erase( iterator pos ) { 327 MapType & scope = (*pos.scopes)[ pos.level ].map; 328 const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it ); 329 iterator it( *pos.scopes, new_it, pos.level ); 330 return it.next_valid(); 169 /// Erases element with key in the innermost scope that has it. 170 size_type erase( const Key & key ) { 171 for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) { 172 size_type i = it->map.erase( key ); 173 if ( 0 != i ) return i; 174 } 175 return 0; 331 176 } 332 177 … … 343 188 return c; 344 189 } 190 191 bool contains( const Key & key ) const { 192 return find( key ) != cend(); 193 } 194 }; 195 196 template<typename Key, typename Value, typename Note> 197 class ScopedMap<Key, Value, Note>::iterator : 198 public std::iterator< std::bidirectional_iterator_tag, value_type > { 199 friend class ScopedMap; 200 friend class const_iterator; 201 typedef typename ScopedMap::MapType::iterator wrapped_iterator; 202 typedef typename ScopedMap::ScopeList scope_list; 203 typedef typename scope_list::size_type size_type; 204 205 /// Checks if this iterator points to a valid item 206 bool is_valid() const { 207 return it != (*scopes)[level].map.end(); 208 } 209 210 /// Increments on invalid 211 iterator & next_valid() { 212 if ( ! is_valid() ) { ++(*this); } 213 return *this; 214 } 215 216 /// Decrements on invalid 217 iterator & prev_valid() { 218 if ( ! is_valid() ) { --(*this); } 219 return *this; 220 } 221 222 iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel) 223 : scopes(&_scopes), it(_it), level(inLevel) {} 224 public: 225 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 226 iterator & operator= (const iterator & that) { 227 scopes = that.scopes; level = that.level; it = that.it; 228 return *this; 229 } 230 231 reference operator* () { return *it; } 232 pointer operator-> () const { return it.operator->(); } 233 234 iterator & operator++ () { 235 if ( it == (*scopes)[level].map.end() ) { 236 if ( level == 0 ) return *this; 237 --level; 238 it = (*scopes)[level].map.begin(); 239 } else { 240 ++it; 241 } 242 return next_valid(); 243 } 244 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } 245 246 iterator & operator-- () { 247 // may fail if this is the begin iterator; allowed by STL spec 248 if ( it == (*scopes)[level].map.begin() ) { 249 ++level; 250 it = (*scopes)[level].map.end(); 251 } 252 --it; 253 return prev_valid(); 254 } 255 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; } 256 257 bool operator== (const iterator & that) const { 258 return scopes == that.scopes && level == that.level && it == that.it; 259 } 260 bool operator!= (const iterator & that) const { return !( *this == that ); } 261 262 size_type get_level() const { return level; } 263 264 Note & get_note() { return (*scopes)[level].note; } 265 const Note & get_note() const { return (*scopes)[level].note; } 266 267 private: 268 scope_list *scopes; 269 wrapped_iterator it; 270 size_type level; 271 }; 272 273 template<typename Key, typename Value, typename Note> 274 class ScopedMap<Key, Value, Note>::const_iterator : 275 public std::iterator< std::bidirectional_iterator_tag, value_type > { 276 friend class ScopedMap; 277 typedef typename ScopedMap::MapType::iterator wrapped_iterator; 278 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator; 279 typedef typename ScopedMap::ScopeList scope_list; 280 typedef typename scope_list::size_type size_type; 281 282 /// Checks if this iterator points to a valid item 283 bool is_valid() const { 284 return it != (*scopes)[level].map.end(); 285 } 286 287 /// Increments on invalid 288 const_iterator & next_valid() { 289 if ( ! is_valid() ) { ++(*this); } 290 return *this; 291 } 292 293 /// Decrements on invalid 294 const_iterator & prev_valid() { 295 if ( ! is_valid() ) { --(*this); } 296 return *this; 297 } 298 299 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel) 300 : scopes(&_scopes), it(_it), level(inLevel) {} 301 public: 302 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 303 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 304 const_iterator & operator= (const iterator & that) { 305 scopes = that.scopes; level = that.level; it = that.it; 306 return *this; 307 } 308 const_iterator & operator= (const const_iterator & that) { 309 scopes = that.scopes; level = that.level; it = that.it; 310 return *this; 311 } 312 313 const_reference operator* () { return *it; } 314 const_pointer operator-> () { return it.operator->(); } 315 316 const_iterator & operator++ () { 317 if ( it == (*scopes)[level].map.end() ) { 318 if ( level == 0 ) return *this; 319 --level; 320 it = (*scopes)[level].map.begin(); 321 } else { 322 ++it; 323 } 324 return next_valid(); 325 } 326 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } 327 328 const_iterator & operator-- () { 329 // may fail if this is the begin iterator; allowed by STL spec 330 if ( it == (*scopes)[level].map.begin() ) { 331 ++level; 332 it = (*scopes)[level].map.end(); 333 } 334 --it; 335 return prev_valid(); 336 } 337 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } 338 339 bool operator== (const const_iterator & that) const { 340 return scopes == that.scopes && level == that.level && it == that.it; 341 } 342 bool operator!= (const const_iterator & that) const { return !( *this == that ); } 343 344 size_type get_level() const { return level; } 345 346 const Note & get_note() const { return (*scopes)[level].note; } 347 348 private: 349 scope_list const *scopes; 350 wrapped_const_iterator it; 351 size_type level; 345 352 }; 346 353 -
src/Common/SemanticError.h
r34b4268 r24d6572 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 4 14:08:26 202213 // Update Count : 3 512 // Last Modified On : Sat Feb 25 12:01:31 2023 13 // Update Count : 37 14 14 // 15 15 … … 54 54 55 55 constexpr WarningData WarningFormats[] = { 56 {"self-assign" , Severity::Warn , "self assignment of expression: %s" }, 57 {"reference-conversion" , Severity::Warn , "rvalue to reference conversion of rvalue: %s" }, 58 {"qualifiers-zero_t-one_t", Severity::Warn , "questionable use of type qualifier %s with %s" }, 59 {"aggregate-forward-decl" , Severity::Warn , "forward declaration of nested aggregate: %s" }, 60 {"superfluous-decl" , Severity::Warn , "declaration does not allocate storage: %s" }, 61 {"superfluous-else" , Severity::Warn , "else clause never executed for empty loop conditional" }, 62 {"gcc-attributes" , Severity::Warn , "invalid attribute: %s" }, 63 {"c++-like-copy" , Severity::Warn , "Constructor from reference is not a valid copy constructor" }, 56 {"self-assign" , Severity::Warn , "self assignment of expression: %s" }, 57 {"reference-conversion" , Severity::Warn , "rvalue to reference conversion of rvalue: %s" }, 58 {"qualifiers-zero_t-one_t" , Severity::Warn , "questionable use of type qualifier(s) with %s" }, 59 {"aggregate-forward-decl" , Severity::Warn , "forward declaration of nested aggregate: %s" }, 60 {"superfluous-decl" , Severity::Warn , "declaration does not allocate storage: %s" }, 61 {"superfluous-else" , Severity::Warn , "else clause never executed for empty loop conditional" }, 62 {"gcc-attributes" , Severity::Warn , "invalid attribute: %s" }, 63 {"c++-like-copy" , Severity::Warn , "Constructor from reference is not a valid copy constructor" }, 64 {"depreciated-trait-syntax" , Severity::Warn , "trait type-parameters are now specified using the forall clause" }, 64 65 }; 65 66 … … 73 74 GccAttributes, 74 75 CppCopy, 76 DeprecTraitSyntax, 75 77 NUMBER_OF_WARNINGS, // This MUST be the last warning 76 78 }; -
src/Common/module.mk
r34b4268 r24d6572 20 20 Common/CodeLocationTools.hpp \ 21 21 Common/CodeLocationTools.cpp \ 22 Common/CompilerError.h \23 Common/Debug.h \24 22 Common/DeclStats.hpp \ 25 23 Common/DeclStats.cpp \ 26 24 Common/ErrorObjects.h \ 27 25 Common/Eval.cc \ 26 Common/Eval.h \ 28 27 Common/Examine.cc \ 29 28 Common/Examine.h \ … … 31 30 Common/Indenter.h \ 32 31 Common/Indenter.cc \ 32 Common/Iterate.hpp \ 33 33 Common/PassVisitor.cc \ 34 34 Common/PassVisitor.h \ … … 52 52 Common/Stats/Time.cc \ 53 53 Common/Stats/Time.h \ 54 Common/ UnimplementedError.h\54 Common/ToString.hpp \ 55 55 Common/UniqueName.cc \ 56 56 Common/UniqueName.h \ -
src/Common/utility.h
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h -- 7 // utility.h -- General utilities used across the compiler. 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 25 14:26:00 202213 // Update Count : 5 112 // Last Modified On : Fri Feb 17 15:25:00 2023 13 // Update Count : 53 14 14 // 15 15 … … 19 19 #include <cctype> 20 20 #include <algorithm> 21 #include <functional>22 21 #include <iostream> 23 #include <iterator>24 22 #include <list> 25 23 #include <memory> 26 #include <sstream>27 24 #include <string> 28 25 #include <type_traits> 29 #include <utility>30 26 #include <vector> 31 27 #include <cstring> // memcmp … … 49 45 return 0; 50 46 } // if 51 }52 53 template< typename T, typename U >54 struct maybeBuild_t {55 static T * doit( const U *orig ) {56 if ( orig ) {57 return orig->build();58 } else {59 return 0;60 } // if61 }62 };63 64 template< typename T, typename U >65 static inline T * maybeBuild( const U *orig ) {66 return maybeBuild_t<T,U>::doit(orig);67 }68 69 template< typename T, typename U >70 static inline T * maybeMoveBuild( const U *orig ) {71 T* ret = maybeBuild<T>(orig);72 delete orig;73 return ret;74 47 } 75 48 … … 168 141 splice( src, dst ); 169 142 dst.swap( src ); 170 }171 172 template < typename T >173 void toString_single( std::ostream & os, const T & value ) {174 os << value;175 }176 177 template < typename T, typename... Params >178 void toString_single( std::ostream & os, const T & value, const Params & ... params ) {179 os << value;180 toString_single( os, params ... );181 }182 183 template < typename ... Params >184 std::string toString( const Params & ... params ) {185 std::ostringstream os;186 toString_single( os, params... );187 return os.str();188 }189 190 #define toCString( ... ) toString( __VA_ARGS__ ).c_str()191 192 // replace element of list with all elements of another list193 template< typename T >194 void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {195 typename std::list< T >::iterator next = pos; advance( next, 1 );196 197 //if ( next != org.end() ) {198 org.erase( pos );199 org.splice( next, with );200 //}201 202 return;203 }204 205 // replace range of a list with a single element206 template< typename T >207 void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {208 org.insert( begin, with );209 org.erase( begin, end );210 143 } 211 144 … … 236 169 } 237 170 238 template< typename... Args >239 auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {240 return zipWith(std::forward<Args>(args)..., std::make_pair);241 }242 243 template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >244 void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {245 while ( b1 != e1 && b2 != e2 )246 *out++ = func(*b1++, *b2++);247 }248 249 // it's nice to actually be able to increment iterators by an arbitrary amount250 template< class InputIt, class Distance >251 InputIt operator+( InputIt it, Distance n ) {252 advance(it, n);253 return it;254 }255 256 template< typename T >257 void warn_single( const T & arg ) {258 std::cerr << arg << std::endl;259 }260 261 template< typename T, typename... Params >262 void warn_single(const T & arg, const Params & ... params ) {263 std::cerr << arg;264 warn_single( params... );265 }266 267 template< typename... Params >268 void warn( const Params & ... params ) {269 std::cerr << "Warning: ";270 warn_single( params... );271 }272 273 171 // determines if pref is a prefix of str 274 172 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 275 173 if ( pref.size() > str.size() ) return false; 276 return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() ); 277 // return prefix == full.substr(0, prefix.size()); // for future, requires c++17 278 } 279 280 // ----------------------------------------------------------------------------- 281 // Ref Counted Singleton class 282 // Objects that inherit from this class will have at most one reference to it 283 // but if all references die, the object will be deleted. 284 285 template< typename ThisType > 286 class RefCountSingleton { 287 public: 288 static std::shared_ptr<ThisType> get() { 289 if( global_instance.expired() ) { 290 std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>(); 291 global_instance = new_instance; 292 return std::move(new_instance); 293 } 294 return global_instance.lock(); 295 } 296 private: 297 static std::weak_ptr<ThisType> global_instance; 298 }; 299 300 template< typename ThisType > 301 std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance; 174 return pref == str.substr(start, pref.size()); 175 } 302 176 303 177 // ----------------------------------------------------------------------------- … … 356 230 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 357 231 }; 358 359 // -----------------------------------------------------------------------------360 // Helper struct and function to support361 // for ( val : reverseIterate( container ) ) {}362 // syntax to have a for each that iterates backwards363 364 template< typename T >365 struct reverse_iterate_t {366 T& ref;367 368 reverse_iterate_t( T & ref ) : ref(ref) {}369 370 // this does NOT work on const T!!!371 // typedef typename T::reverse_iterator iterator;372 auto begin() { return ref.rbegin(); }373 auto end() { return ref.rend(); }374 };375 376 template< typename T >377 reverse_iterate_t< T > reverseIterate( T & ref ) {378 return reverse_iterate_t< T >( ref );379 }380 381 template< typename T >382 struct enumerate_t {383 template<typename val_t>384 struct value_t {385 val_t & val;386 size_t idx;387 };388 389 template< typename iter_t, typename val_t >390 struct iterator_t {391 iter_t it;392 size_t idx;393 394 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}395 396 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }397 398 bool operator==(const iterator_t & o) const { return o.it == it; }399 bool operator!=(const iterator_t & o) const { return o.it != it; }400 401 iterator_t & operator++() {402 it++;403 idx++;404 return *this;405 }406 407 using difference_type = typename std::iterator_traits< iter_t >::difference_type;408 using value_type = value_t<val_t>;409 using pointer = value_t<val_t> *;410 using reference = value_t<val_t> &;411 using iterator_category = std::forward_iterator_tag;412 };413 414 T & ref;415 416 using iterator = iterator_t< typename T::iterator, typename T::value_type >;417 using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;418 419 iterator begin() { return iterator( ref.begin(), 0 ); }420 iterator end() { return iterator( ref.end(), ref.size() ); }421 422 const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }423 const_iterator end() const { return const_iterator( ref.cend(), ref.size() ); }424 425 const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }426 const_iterator cend() const { return const_iterator( ref.cend(), ref.size() ); }427 };428 429 template< typename T >430 enumerate_t<T> enumerate( T & ref ) {431 return enumerate_t< T >{ ref };432 }433 434 template< typename T >435 const enumerate_t< const T > enumerate( const T & ref ) {436 return enumerate_t< const T >{ ref };437 }438 439 template< typename OutType, typename Range, typename Functor >440 OutType map_range( const Range& range, Functor&& functor ) {441 OutType out;442 443 std::transform(444 begin( range ),445 end( range ),446 std::back_inserter( out ),447 std::forward< Functor >( functor )448 );449 450 return out;451 }452 453 // -----------------------------------------------------------------------------454 // Helper struct and function to support:455 // for ( auto val : group_iterate( container1, container2, ... ) ) { ... }456 // This iteraters through multiple containers of the same size.457 458 template<typename... Args>459 class group_iterate_t {460 using Iterables = std::tuple<Args...>;461 Iterables iterables;462 463 // Getting the iterator and value types this way preserves const.464 template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());465 template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());466 template<typename> struct base_iterator;467 468 // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`469 // into a pack. These are the indexes into the tuples, so unpacking can470 // go over each element of the tuple.471 // The std::integer_sequence is just used to build that sequence.472 // A library reference will probably explain it better than I can.473 template<std::size_t... Indices>474 struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {475 using value_type = std::tuple< Data<Indices>... >;476 std::tuple<Iter<Indices>...> iterators;477 478 base_iterator( Iter<Indices>... is ) : iterators( is... ) {}479 base_iterator operator++() {480 return base_iterator( ++std::get<Indices>( iterators )... );481 }482 bool operator!=( const base_iterator& other ) const {483 return iterators != other.iterators;484 }485 value_type operator*() const {486 return std::tie( *std::get<Indices>( iterators )... );487 }488 489 static base_iterator make_begin( Iterables & data ) {490 return base_iterator( std::get<Indices>( data ).begin()... );491 }492 static base_iterator make_end( Iterables & data ) {493 return base_iterator( std::get<Indices>( data ).end()... );494 }495 };496 497 public:498 group_iterate_t( const Args &... args ) : iterables( args... ) {}499 500 using iterator = base_iterator<decltype(501 std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;502 503 iterator begin() { return iterator::make_begin( iterables ); }504 iterator end() { return iterator::make_end( iterables ); }505 };506 507 // Helpers for the bounds checks (the non-varatic part of group_iterate):508 static inline void runGroupBoundsCheck(size_t size0, size_t size1) {509 assertf( size0 == size1,510 "group iteration requires containers of the same size: <%zd, %zd>.",511 size0, size1 );512 }513 514 static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {515 assertf( size0 == size1 && size1 == size2,516 "group iteration requires containers of the same size: <%zd, %zd, %zd>.",517 size0, size1, size2 );518 }519 520 /// Performs bounds check to ensure that all arguments are of the same length.521 template< typename... Args >522 group_iterate_t<Args...> group_iterate( Args &&... args ) {523 runGroupBoundsCheck( args.size()... );524 return group_iterate_t<Args...>( std::forward<Args>( args )... );525 }526 527 /// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.528 template< typename... Args >529 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {530 return group_iterate_t<Args...>( std::forward<Args>( args )... );531 }532 533 // -----------------------------------------------------------------------------534 // Helper struct and function to support535 // for ( val : lazy_map( container1, f ) ) {}536 // syntax to have a for each that iterates a container, mapping each element by applying f537 template< typename T, typename Func >538 struct lambda_iterate_t {539 const T & ref;540 std::function<Func> f;541 542 struct iterator {543 typedef decltype(begin(ref)) Iter;544 Iter it;545 std::function<Func> f;546 iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}547 iterator & operator++() {548 ++it; return *this;549 }550 bool operator!=( const iterator &other ) const { return it != other.it; }551 auto operator*() const -> decltype(f(*it)) { return f(*it); }552 };553 554 lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}555 556 auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }557 auto end() const -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }558 };559 560 template< typename... Args >561 lambda_iterate_t<Args...> lazy_map( const Args &... args ) {562 return lambda_iterate_t<Args...>( args...);563 }564 232 565 233 // ----------------------------------------------------------------------------- … … 583 251 } // ilog2 584 252 585 // -----------------------------------------------------------------------------586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated587 std::pair<long long int, bool> eval(const Expression * expr);588 589 namespace ast {590 class Expr;591 }592 593 std::pair<long long int, bool> eval(const ast::Expr * expr);594 595 // -----------------------------------------------------------------------------596 /// Reorders the input range in-place so that the minimal-value elements according to the597 /// comparator are in front;598 /// returns the iterator after the last minimal-value element.599 template<typename Iter, typename Compare>600 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {601 if ( begin == end ) return end;602 603 Iter min_pos = begin;604 for ( Iter i = begin + 1; i != end; ++i ) {605 if ( lt( *i, *min_pos ) ) {606 // new minimum cost; swap into first position607 min_pos = begin;608 std::iter_swap( min_pos, i );609 } else if ( ! lt( *min_pos, *i ) ) {610 // duplicate minimum cost; swap into next minimum position611 ++min_pos;612 std::iter_swap( min_pos, i );613 }614 }615 return ++min_pos;616 }617 618 template<typename Iter, typename Compare>619 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {620 return sort_mins( begin, end, lt );621 }622 623 /// sort_mins defaulted to use std::less624 template<typename Iter>625 inline Iter sort_mins( Iter begin, Iter end ) {626 return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );627 }628 629 253 // Local Variables: // 630 254 // tab-width: 4 // -
src/CompilationState.cc
r34b4268 r24d6572 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:50 2023 13 // Update Count : 6 14 14 // 15 15 … … 27 27 expraltp = false, 28 28 genericsp = false, 29 invariant = false, 29 30 libcfap = false, 30 31 nopreludep = false, … … 33 34 useNewAST = true, 34 35 nomainp = false, 35 parsep = false,36 36 resolvep = false, 37 37 resolvprotop = false, -
src/CompilationState.h
r34b4268 r24d6572 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:53 2023 13 // Update Count : 6 14 14 // 15 15 … … 26 26 expraltp, 27 27 genericsp, 28 invariant, 28 29 libcfap, 29 30 nopreludep, … … 32 33 useNewAST, 33 34 nomainp, 34 parsep,35 35 resolvep, 36 36 resolvprotop, -
src/Concurrency/KeywordsNew.cpp
r34b4268 r24d6572 779 779 780 780 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 781 switch ( stmt-> type) {781 switch ( stmt->kind ) { 782 782 case ast::SuspendStmt::None: 783 783 // Use the context to determain the implicit target. -
src/Concurrency/WaitforNew.cpp
r34b4268 r24d6572 305 305 306 306 const ast::VariableExpr * variableExpr = 307 clause->target _func.as<ast::VariableExpr>();307 clause->target.as<ast::VariableExpr>(); 308 308 ast::Expr * castExpr = new ast::CastExpr( 309 309 location, 310 310 new ast::CastExpr( 311 311 location, 312 clause->target _func,312 clause->target, 313 313 ast::deepCopy( variableExpr->result.get() ), 314 314 ast::GeneratedCast ), … … 325 325 326 326 ResolveContext context{ symtab, transUnit().global }; 327 out->push_back( maybeCond( location, clause-> cond.get(), {327 out->push_back( maybeCond( location, clause->when_cond.get(), { 328 328 makeAccStmt( location, acceptables, index, "is_dtor", 329 detectIsDtor( location, clause->target _func), context ),329 detectIsDtor( location, clause->target ), context ), 330 330 makeAccStmt( location, acceptables, index, "func", 331 331 funcExpr, context ), -
src/Concurrency/module.mk
r34b4268 r24d6572 16 16 17 17 SRC += \ 18 Concurrency/Actors.cpp \ 19 Concurrency/Actors.hpp \ 18 20 Concurrency/KeywordsNew.cpp \ 19 21 Concurrency/Keywords.cc \ … … 21 23 Concurrency/WaitforNew.cpp \ 22 24 Concurrency/Waitfor.cc \ 23 Concurrency/Waitfor.h 25 Concurrency/Waitfor.h \ 26 Concurrency/Waituntil.cpp \ 27 Concurrency/Waituntil.hpp -
src/ControlStruct/ExceptDeclNew.cpp
r34b4268 r24d6572 16 16 #include "ExceptDecl.h" 17 17 18 #include <sstream> 19 20 #include "AST/Copy.hpp" 18 21 #include "AST/Decl.hpp" 19 22 #include "AST/Pass.hpp" -
src/ControlStruct/ExceptTranslateNew.cpp
r34b4268 r24d6572 314 314 nullptr, 315 315 ast::Storage::Classes{}, 316 ast::Linkage::Cforall 316 ast::Linkage::Cforall, 317 {}, 318 { ast::Function::Inline } 317 319 ); 318 320 } -
src/ControlStruct/MLEMutator.cc
r34b4268 r24d6572 25 25 #include <memory> // for allocator_traits<>::value_... 26 26 27 #include "Common/ utility.h" // for toString, operator+27 #include "Common/ToString.hpp" // for toString 28 28 #include "ControlStruct/LabelGenerator.h" // for LabelGenerator 29 29 #include "MLEMutator.h" -
src/GenPoly/Box.cc
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 23:40:34 201913 // Update Count : 34 711 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Dec 19 16:36:00 2022 13 // Update Count : 348 14 14 // 15 16 #include "Box.h" 15 17 16 18 #include <algorithm> // for mismatch … … 24 26 #include <utility> // for pair 25 27 26 #include "Box.h"27 28 28 #include "CodeGen/OperatorTable.h" 29 29 #include "Common/PassVisitor.h" // for PassVisitor … … 31 31 #include "Common/SemanticError.h" // for SemanticError 32 32 #include "Common/UniqueName.h" // for UniqueName 33 #include "Common/ utility.h" // for toString33 #include "Common/ToString.hpp" // for toCString 34 34 #include "FindFunction.h" // for findFunction, findAndReplace... 35 35 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_i... … … 37 37 #include "InitTweak/InitTweak.h" // for getFunctionName, isAssignment 38 38 #include "Lvalue.h" // for generalizedLvalue 39 #include "ResolvExpr/ typeops.h"// for typesCompatible39 #include "ResolvExpr/Unify.h" // for typesCompatible 40 40 #include "ScopedSet.h" // for ScopedSet, ScopedSet<>::iter... 41 41 #include "ScrubTyVars.h" // for ScrubTyVars … … 72 72 }; 73 73 74 /// Updates the call sites of polymorphic functions. 74 75 /// Replaces polymorphic return types with out-parameters, 75 76 /// replaces calls to polymorphic functions with adapter calls, 76 77 /// and adds appropriate type variables to the function call. 77 class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {78 class CallAdapter final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<CallAdapter>, public WithShortCircuiting { 78 79 public: 79 Pass1(); 80 80 CallAdapter(); 81 82 void premutate( Declaration * declaration ); 81 83 void premutate( FunctionDecl * functionDecl ); 82 84 void premutate( TypeDecl * typeDecl ); … … 138 140 }; 139 141 142 /// Updates declarations (and types) that require adapters. 140 143 /// * Moves polymorphic returns in function types to pointer-type parameters 141 144 /// * adds type size and assertion parameters to parameter lists 142 struct Pass2final : public BoxPass, public WithGuards {145 struct DeclAdapter final : public BoxPass, public WithGuards { 143 146 void handleAggDecl(); 144 147 … … 210 213 }; 211 214 215 /// Erases unneeded/unwanted polymorphic information. 212 216 /// Replaces initialization of polymorphic values with alloca, 213 217 /// declaration of dtype/ftype with appropriate void expression, 214 218 /// sizeof expressions of polymorphic types with the proper variable, 215 219 /// and strips fields from generic struct declarations. 216 struct Pass3 final : public BoxPass, public WithGuards { 217 template< typename DeclClass > 218 void handleDecl( DeclClass * decl, Type * type ); 219 220 struct Eraser final { 220 221 void premutate( ObjectDecl * objectDecl ); 221 222 void premutate( FunctionDecl * functionDecl ); … … 223 224 void premutate( StructDecl * structDecl ); 224 225 void premutate( UnionDecl * unionDecl ); 225 void premutate( TypeDecl * typeDecl );226 void premutate( PointerType * pointerType );227 void premutate( FunctionType * funcType );228 226 }; 229 227 } // anonymous namespace … … 231 229 void box( std::list< Declaration *>& translationUnit ) { 232 230 PassVisitor<LayoutFunctionBuilder> layoutBuilder; 233 PassVisitor< Pass1> pass1;234 PassVisitor< Pass2> pass2;231 PassVisitor<CallAdapter> callAdapter; 232 PassVisitor<DeclAdapter> declAdapter; 235 233 PassVisitor<PolyGenericCalculator> polyCalculator; 236 PassVisitor< Pass3> pass3;234 PassVisitor<Eraser> eraser; 237 235 238 236 acceptAll( translationUnit, layoutBuilder ); 239 mutateAll( translationUnit, pass1);240 mutateAll( translationUnit, pass2);237 mutateAll( translationUnit, callAdapter ); 238 mutateAll( translationUnit, declAdapter ); 241 239 mutateAll( translationUnit, polyCalculator ); 242 mutateAll( translationUnit, pass3);240 mutateAll( translationUnit, eraser ); 243 241 } 244 242 245 ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////243 ////////////////////////////////// LayoutFunctionBuilder //////////////////////////////////////// 246 244 247 245 /// Get a list of type declarations that will affect a layout function … … 423 421 } 424 422 425 ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////423 ////////////////////////////////////////////// CallAdapter ////////////////////////////////////// 426 424 427 425 namespace { 428 426 std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) { 429 std::stringstream name;430 431 427 // NOTE: this function previously used isPolyObj, which failed to produce 432 428 // the correct thing in some situations. It's not clear to me why this wasn't working. … … 435 431 // to take those polymorphic types as pointers. Therefore, there can be two different functions 436 432 // with the same mangled name, so we need to further mangle the names. 433 std::stringstream name; 437 434 for ( DeclarationWithType const * const ret : function->returnVals ) { 438 if ( isPolyType( ret->get_type(), tyVars ) ) { 439 name << "P"; 440 } else { 441 name << "M"; 442 } 443 } 444 name << "_"; 435 name << ( isPolyType( ret->get_type(), tyVars ) ? 'P' : 'M' ); 436 } 437 name << '_'; 445 438 for ( DeclarationWithType const * const arg : function->parameters ) { 446 if ( isPolyType( arg->get_type(), tyVars ) ) { 447 name << "P"; 448 } else { 449 name << "M"; 450 } 451 } // for 439 name << ( isPolyType( arg->get_type(), tyVars ) ? 'P' : 'M' ); 440 } 452 441 return name.str(); 453 442 } … … 465 454 Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true ); 466 455 467 Pass1::Pass1() : tempNamer( "_temp" ) {} 468 469 void Pass1::premutate( FunctionDecl *functionDecl ) { 456 CallAdapter::CallAdapter() : tempNamer( "_temp" ) {} 457 458 void CallAdapter::premutate( Declaration * ) { 459 // Prevent type declaration information from leaking out. 460 GuardScope( scopeTyVars ); 461 } 462 463 void CallAdapter::premutate( FunctionDecl *functionDecl ) { 470 464 if ( functionDecl->get_statements() ) { // empty routine body ? 471 465 // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl; … … 500 494 for ( FunctionType const * const funType : functions ) { 501 495 std::string mangleName = mangleAdapterName( funType, scopeTyVars ); 502 if ( adapters.find( mangleName ) == adapters.end() ) {496 if ( !adapters.contains( mangleName ) ) { 503 497 std::string adapterName = makeAdapterName( mangleName ); 504 498 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) ); … … 509 503 } 510 504 511 void Pass1::premutate( TypeDecl *typeDecl ) {505 void CallAdapter::premutate( TypeDecl *typeDecl ) { 512 506 addToTyVarMap( typeDecl, scopeTyVars ); 513 507 } 514 508 515 void Pass1::premutate( CommaExpr *commaExpr ) {509 void CallAdapter::premutate( CommaExpr *commaExpr ) { 516 510 // Attempting to find application expressions that were mutated by the copy constructor passes 517 511 // to use an explicit return variable, so that the variable can be reused as a parameter to the … … 531 525 } 532 526 533 std::list< Expression *>::iterator Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {527 std::list< Expression *>::iterator CallAdapter::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 534 528 Type *polyType = isPolyType( parmType, exprTyVars ); 535 529 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { … … 558 552 } 559 553 560 std::list< Expression *>::iterator Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {554 std::list< Expression *>::iterator CallAdapter::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) { 561 555 assert( env ); 562 556 std::list< Expression *>::iterator arg = appExpr->args.begin(); … … 568 562 // even when converted to strings, sort in the original order. 569 563 // (At least, that is the best explination I have.) 570 for ( std::pair< std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {564 for ( std::pair<const std::string, TypeDecl::Data> const & tyParam : exprTyVars ) { 571 565 if ( !tyParam.second.isComplete ) continue; 572 566 Type *concrete = env->lookup( tyParam.first ); … … 611 605 } 612 606 613 ObjectDecl * Pass1::makeTemporary( Type *type ) {607 ObjectDecl *CallAdapter::makeTemporary( Type *type ) { 614 608 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 ); 615 609 stmtsToAddBefore.push_back( new DeclStmt( newObj ) ); … … 617 611 } 618 612 619 Expression * Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType ) {613 Expression *CallAdapter::addRetParam( ApplicationExpr *appExpr, Type *retType ) { 620 614 // Create temporary to hold return value of polymorphic function and produce that temporary as a result 621 615 // using a comma expression. … … 680 674 } 681 675 682 Expression * Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {676 Expression *CallAdapter::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) { 683 677 Type *concrete = replaceWithConcrete( dynType, env ); 684 678 // add out-parameter for return value … … 686 680 } 687 681 688 Expression * Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {682 Expression *CallAdapter::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) { 689 683 Expression *ret = appExpr; 690 684 if ( isDynRet( function, scopeTyVars ) ) { … … 735 729 } 736 730 737 void Pass1::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {731 void CallAdapter::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) { 738 732 assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() ); 739 733 addCast( arg, param, exprTyVars ); … … 770 764 } 771 765 772 void Pass1::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {766 void CallAdapter::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) { 773 767 for ( DeclarationWithType * param : function->parameters ) { 774 768 assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() ); … … 778 772 } 779 773 780 void Pass1::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {774 void CallAdapter::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) { 781 775 for ( TypeDecl * const tyVar : functionType->forall ) { 782 776 for ( DeclarationWithType * const assert : tyVar->assertions ) { … … 846 840 } 847 841 848 FunctionDecl * Pass1::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {842 FunctionDecl *CallAdapter::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) { 849 843 FunctionType *adapterType = makeAdapterType( adaptee, tyVars ); 850 844 adapterType = ScrubTyVars::scrub( adapterType, tyVars ); … … 906 900 } 907 901 908 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {902 void CallAdapter::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) { 909 903 // collect a list of function types passed as parameters or implicit parameters (assertions) 910 904 std::list<FunctionType const *> functions; … … 923 917 924 918 for ( FunctionType const * const funType : functions ) { 925 FunctionType *originalFunction = funType->clone(); 926 FunctionType *realFunction = funType->clone(); 927 std::string mangleName = SymTab::Mangler::mangle( realFunction ); 919 std::string mangleName = SymTab::Mangler::mangle( funType ); 928 920 929 921 // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this 930 922 // pre-substitution parameter function type. 931 923 // The second part of the insert result is "is the value new". 932 if ( adaptersDone.insert( mangleName ).second ) { 933 934 // apply substitution to type variables to figure out what the adapter's type should look like 935 assert( env ); 936 env->apply( realFunction ); 937 mangleName = SymTab::Mangler::mangle( realFunction ); 938 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars ); 939 940 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter; 941 AdapterIter adapter = adapters.find( mangleName ); 942 if ( adapter == adapters.end() ) { 943 // adapter has not been created yet in the current scope, so define it 944 FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars ); 945 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 946 adapter = answer.first; 947 stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) ); 948 } // if 949 assert( adapter != adapters.end() ); 950 951 // add the appropriate adapter as a parameter 952 appExpr->get_args().push_front( new VariableExpr( adapter->second ) ); 924 if ( !adaptersDone.insert( mangleName ).second ) continue; 925 926 // Apply substitution to type variables to figure out what the adapter's type should look like. 927 assert( env ); 928 FunctionType *realType = funType->clone(); 929 env->apply( realType ); 930 mangleName = SymTab::Mangler::mangle( realType ); 931 mangleName += makePolyMonoSuffix( funType, exprTyVars ); 932 933 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter; 934 AdapterIter adapter = adapters.find( mangleName ); 935 if ( adapter == adapters.end() ) { 936 // Adapter has not been created yet in the current scope, so define it. 937 FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars ); 938 std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter ); 939 adapter = answer.first; 940 stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) ); 953 941 } // if 942 assert( adapter != adapters.end() ); 943 944 // Add the appropriate adapter as a parameter. 945 appExpr->args.push_front( new VariableExpr( adapter->second ) ); 954 946 } // for 955 947 } // passAdapters … … 974 966 } 975 967 976 Expression * Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {968 Expression *CallAdapter::handleIntrinsics( ApplicationExpr *appExpr ) { 977 969 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) { 978 970 if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) { … … 1097 1089 } 1098 1090 1099 Expression * Pass1::postmutate( ApplicationExpr *appExpr ) {1091 Expression *CallAdapter::postmutate( ApplicationExpr *appExpr ) { 1100 1092 // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl; 1101 1093 // for ( auto tyVar : scopeTyVars ) { … … 1169 1161 } 1170 1162 1171 Expression * Pass1::postmutate( UntypedExpr *expr ) {1163 Expression * CallAdapter::postmutate( UntypedExpr *expr ) { 1172 1164 if ( isPolyDeref( expr, scopeTyVars, env ) ) { 1173 1165 Expression *ret = expr->args.front(); … … 1179 1171 } 1180 1172 1181 void Pass1::premutate( AddressExpr * ) { visit_children = false; }1182 1183 Expression * Pass1::postmutate( AddressExpr * addrExpr ) {1173 void CallAdapter::premutate( AddressExpr * ) { visit_children = false; } 1174 1175 Expression * CallAdapter::postmutate( AddressExpr * addrExpr ) { 1184 1176 assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() ); 1185 1177 … … 1212 1204 } 1213 1205 1214 void Pass1::premutate( ReturnStmt *returnStmt ) {1206 void CallAdapter::premutate( ReturnStmt *returnStmt ) { 1215 1207 if ( retval && returnStmt->expr ) { 1216 1208 assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() ); … … 1220 1212 } 1221 1213 1222 void Pass1::premutate( PointerType *pointerType ) {1214 void CallAdapter::premutate( PointerType *pointerType ) { 1223 1215 GuardScope( scopeTyVars ); 1224 1216 makeTyVarMap( pointerType, scopeTyVars ); 1225 1217 } 1226 1218 1227 void Pass1::premutate( FunctionType *functionType ) {1219 void CallAdapter::premutate( FunctionType *functionType ) { 1228 1220 GuardScope( scopeTyVars ); 1229 1221 makeTyVarMap( functionType, scopeTyVars ); 1230 1222 } 1231 1223 1232 void Pass1::beginScope() {1224 void CallAdapter::beginScope() { 1233 1225 adapters.beginScope(); 1234 1226 } 1235 1227 1236 void Pass1::endScope() {1228 void CallAdapter::endScope() { 1237 1229 adapters.endScope(); 1238 1230 } 1239 1231 1240 ////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////1241 1242 void Pass2::addAdapters( FunctionType *functionType ) {1232 ////////////////////////////////////////// DeclAdapter ////////////////////////////////////////// 1233 1234 void DeclAdapter::addAdapters( FunctionType *functionType ) { 1243 1235 std::list< FunctionType const *> functions; 1244 1236 for ( DeclarationWithType * const arg : functionType->parameters ) { … … 1260 1252 } 1261 1253 1262 DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {1254 DeclarationWithType * DeclAdapter::postmutate( FunctionDecl *functionDecl ) { 1263 1255 FunctionType * ftype = functionDecl->type; 1264 1256 if ( ! ftype->returnVals.empty() && functionDecl->statements ) { … … 1285 1277 } 1286 1278 1287 void Pass2::premutate( StructDecl * ) {1279 void DeclAdapter::premutate( StructDecl * ) { 1288 1280 // prevent tyVars from leaking into containing scope 1289 1281 GuardScope( scopeTyVars ); 1290 1282 } 1291 1283 1292 void Pass2::premutate( UnionDecl * ) {1284 void DeclAdapter::premutate( UnionDecl * ) { 1293 1285 // prevent tyVars from leaking into containing scope 1294 1286 GuardScope( scopeTyVars ); 1295 1287 } 1296 1288 1297 void Pass2::premutate( TraitDecl * ) {1289 void DeclAdapter::premutate( TraitDecl * ) { 1298 1290 // prevent tyVars from leaking into containing scope 1299 1291 GuardScope( scopeTyVars ); 1300 1292 } 1301 1293 1302 void Pass2::premutate( TypeDecl *typeDecl ) {1294 void DeclAdapter::premutate( TypeDecl *typeDecl ) { 1303 1295 addToTyVarMap( typeDecl, scopeTyVars ); 1304 1296 } 1305 1297 1306 void Pass2::premutate( PointerType *pointerType ) {1298 void DeclAdapter::premutate( PointerType *pointerType ) { 1307 1299 GuardScope( scopeTyVars ); 1308 1300 makeTyVarMap( pointerType, scopeTyVars ); 1309 1301 } 1310 1302 1311 void Pass2::premutate( FunctionType *funcType ) {1303 void DeclAdapter::premutate( FunctionType *funcType ) { 1312 1304 GuardScope( scopeTyVars ); 1313 1305 makeTyVarMap( funcType, scopeTyVars ); … … 1393 1385 } 1394 1386 1395 ////////////////////////////////////////// PolyGenericCalculator //////////////////////////////// ////////////////////1387 ////////////////////////////////////////// PolyGenericCalculator //////////////////////////////// 1396 1388 1397 1389 PolyGenericCalculator::PolyGenericCalculator() … … 1474 1466 // make sure that any type information passed into the function is accounted for 1475 1467 for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) { 1476 // condition here duplicates that in Pass2::mutate( FunctionType* )1468 // condition here duplicates that in DeclAdapter::mutate( FunctionType* ) 1477 1469 Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars ); 1478 1470 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) { … … 1501 1493 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) { 1502 1494 // do not try to monomorphize generic parameters 1503 if ( scopeTyVars. find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {1495 if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) { 1504 1496 // polymorphic aggregate members should be converted into monomorphic members. 1505 1497 // Using char[size_T] here respects the expected sizing rules of an aggregate type. … … 1710 1702 1711 1703 if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) { 1712 if ( scopeTyVars. find( typeInst->get_name() ) != scopeTyVars.end() ) {1704 if ( scopeTyVars.contains( typeInst->get_name() ) ) { 1713 1705 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set 1714 1706 return true; … … 1718 1710 // check if this type already has a layout generated for it 1719 1711 std::string typeName = mangleType( ty ); 1720 if ( knownLayouts. find( typeName ) != knownLayouts.end() ) return true;1712 if ( knownLayouts.contains( typeName ) ) return true; 1721 1713 1722 1714 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized … … 1755 1747 // check if this type already has a layout generated for it 1756 1748 std::string typeName = mangleType( ty ); 1757 if ( knownLayouts. find( typeName ) != knownLayouts.end() ) return true;1749 if ( knownLayouts.contains( typeName ) ) return true; 1758 1750 1759 1751 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized … … 1846 1838 } else { 1847 1839 std::string offsetName = offsetofName( mangleType( ty ) ); 1848 if ( knownOffsets. find( offsetName ) != knownOffsets.end() ) {1840 if ( knownOffsets.contains( offsetName ) ) { 1849 1841 // use the already-generated offsets for this type 1850 1842 ret = new NameExpr( offsetName ); … … 1884 1876 } 1885 1877 1886 ////////////////////////////////////////// Pass3 //////////////////////////////////////////////////// 1887 1888 template< typename DeclClass > 1889 void Pass3::handleDecl( DeclClass * decl, Type * type ) { 1890 GuardScope( scopeTyVars ); 1891 makeTyVarMap( type, scopeTyVars ); 1892 ScrubTyVars::scrubAll( decl ); 1893 } 1894 1895 void Pass3::premutate( ObjectDecl * objectDecl ) { 1896 handleDecl( objectDecl, objectDecl->type ); 1897 } 1898 1899 void Pass3::premutate( FunctionDecl * functionDecl ) { 1900 handleDecl( functionDecl, functionDecl->type ); 1901 } 1902 1903 void Pass3::premutate( TypedefDecl * typedefDecl ) { 1904 handleDecl( typedefDecl, typedefDecl->base ); 1878 ////////////////////////////////////////// Eraser /////////////////////////////////////////////// 1879 1880 void Eraser::premutate( ObjectDecl * objectDecl ) { 1881 ScrubTyVars::scrubAll( objectDecl ); 1882 } 1883 1884 void Eraser::premutate( FunctionDecl * functionDecl ) { 1885 ScrubTyVars::scrubAll( functionDecl ); 1886 } 1887 1888 void Eraser::premutate( TypedefDecl * typedefDecl ) { 1889 ScrubTyVars::scrubAll( typedefDecl ); 1905 1890 } 1906 1891 1907 1892 /// Strips the members from a generic aggregate 1908 void stripGenericMembers(AggregateDecl * decl) {1893 static void stripGenericMembers( AggregateDecl * decl ) { 1909 1894 if ( ! decl->parameters.empty() ) decl->members.clear(); 1910 1895 } 1911 1896 1912 void Pass3::premutate( StructDecl * structDecl ) {1897 void Eraser::premutate( StructDecl * structDecl ) { 1913 1898 stripGenericMembers( structDecl ); 1914 1899 } 1915 1900 1916 void Pass3::premutate( UnionDecl * unionDecl ) {1901 void Eraser::premutate( UnionDecl * unionDecl ) { 1917 1902 stripGenericMembers( unionDecl ); 1918 }1919 1920 void Pass3::premutate( TypeDecl * typeDecl ) {1921 addToTyVarMap( typeDecl, scopeTyVars );1922 }1923 1924 void Pass3::premutate( PointerType * pointerType ) {1925 GuardScope( scopeTyVars );1926 makeTyVarMap( pointerType, scopeTyVars );1927 }1928 1929 void Pass3::premutate( FunctionType * functionType ) {1930 GuardScope( scopeTyVars );1931 makeTyVarMap( functionType, scopeTyVars );1932 1903 } 1933 1904 } // anonymous namespace … … 1939 1910 // compile-command: "make install" // 1940 1911 // End: // 1941 -
src/GenPoly/ErasableScopedMap.h
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ScopedMap.h --7 // ErasableScopedMap.h -- 8 8 // 9 9 // Author : Aaron B. Moss … … 51 51 typedef typename Scope::const_pointer const_pointer; 52 52 53 // Both iterator types are complete bidirection iterators, definedbelow.53 // Both iterator types are complete bidirectional iterators, see below. 54 54 class iterator; 55 55 class const_iterator; … … 118 118 std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); } 119 119 120 Value& operator[] ( const Key &key ) { 121 iterator slot = find( key ); 122 if ( slot != end() ) return slot->second; 123 return insert( key, Value() ).first->second; 124 } 125 120 126 /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise 121 127 size_type erase( const Key &key ) { … … 130 136 } 131 137 132 Value& operator[] ( const Key &key ) { 133 iterator slot = find( key ); 134 if ( slot != end() ) return slot->second; 135 return insert( key, Value() ).first->second; 138 bool contains( const Key & key ) const { 139 return find( key ) != cend(); 136 140 } 137 141 }; -
src/GenPoly/FindFunction.cc
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri Feb 05 12:22:20 201613 // Update Count : 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 17:05:20 2022 13 // Update Count : 7 14 14 // 15 15 … … 18 18 #include <utility> // for pair 19 19 20 #include "AST/Pass.hpp" // for Pass 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" // for PassVisitor 21 23 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::iterator … … 89 91 handleForall( pointerType->get_forall() ); 90 92 } 93 94 namespace { 95 96 struct FindFunctionCore : 97 public ast::WithGuards, 98 public ast::WithShortCircuiting, 99 public ast::WithVisitorRef<FindFunctionCore> { 100 FindFunctionCore( 101 std::vector<ast::ptr<ast::FunctionType>> & functions, 102 const TypeVarMap & typeVars, FindFunctionPred predicate, 103 bool replaceMode ); 104 105 void previsit( ast::FunctionType const * type ); 106 ast::Type const * postvisit( ast::FunctionType const * type ); 107 void previsit( ast::PointerType const * type ); 108 private: 109 void handleForall( const ast::FunctionType::ForallList & forall ); 110 111 std::vector<ast::ptr<ast::FunctionType>> &functions; 112 TypeVarMap typeVars; 113 FindFunctionPred predicate; 114 bool replaceMode; 115 }; 116 117 FindFunctionCore::FindFunctionCore( 118 std::vector<ast::ptr<ast::FunctionType>> & functions, 119 const TypeVarMap &typeVars, FindFunctionPred predicate, 120 bool replaceMode ) : 121 functions( functions ), typeVars( typeVars ), 122 predicate( predicate ), replaceMode( replaceMode ) {} 123 124 void FindFunctionCore::handleForall( const ast::FunctionType::ForallList & forall ) { 125 for ( const ast::ptr<ast::TypeInstType> & td : forall ) { 126 TypeVarMap::iterator var = typeVars.find( *td ); 127 if ( var != typeVars.end() ) { 128 typeVars.erase( var->first ); 129 } // if 130 } // for 131 } 132 133 void FindFunctionCore::previsit( ast::FunctionType const * type ) { 134 visit_children = false; 135 GuardScope( typeVars ); 136 handleForall( type->forall ); 137 //ast::accept_all( type->returns, *visitor ); 138 // This might have to become ast::mutate_each with return. 139 ast::accept_each( type->returns, *visitor ); 140 } 141 142 ast::Type const * FindFunctionCore::postvisit( ast::FunctionType const * type ) { 143 ast::Type const * ret = type; 144 if ( predicate( type, typeVars ) ) { 145 functions.push_back( type ); 146 if ( replaceMode ) { 147 // replace type parameters in function type with void* 148 ret = scrubTypeVars( ast::deepCopy( type ), typeVars ); 149 } // if 150 } // if 151 return ret; 152 } 153 154 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) { 155 GuardScope( typeVars ); 156 //handleForall( type->forall ); 157 } 158 159 } // namespace 160 161 void findFunction( const ast::Type * type, 162 std::vector<ast::ptr<ast::FunctionType>> & functions, 163 const TypeVarMap & typeVars, FindFunctionPred predicate ) { 164 ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false ); 165 type->accept( pass ); 166 //(void)type; 167 //(void)functions; 168 //(void)typeVars; 169 //(void)predicate; 170 } 171 172 const ast::Type * findAndReplaceFunction( const ast::Type * type, 173 std::vector<ast::ptr<ast::FunctionType>> & functions, 174 const TypeVarMap & typeVars, FindFunctionPred predicate ) { 175 ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true ); 176 return type->accept( pass ); 177 //(void)functions; 178 //(void)typeVars; 179 //(void)predicate; 180 //return type; 181 } 182 91 183 } // namespace GenPoly 92 184 -
src/GenPoly/FindFunction.h
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:23:36 201713 // Update Count : 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 10:30:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 30 30 /// like `findFunction`, but also replaces the function type with void ()(void) 31 31 void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ); 32 33 typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & ); 34 35 /// Recursively walks `type`, placing all functions that match `predicate` 36 /// under `typeVars` into `functions`. 37 void findFunction( const ast::Type * type, 38 std::vector<ast::ptr<ast::FunctionType>> & functions, 39 const TypeVarMap & typeVars, FindFunctionPred predicate ); 40 /// Like findFunction, but also replaces the function type with `void ()(void)`. 41 const ast::Type * findAndReplaceFunction( const ast::Type * type, 42 std::vector<ast::ptr<ast::FunctionType>> & functions, 43 const TypeVarMap & typeVars, FindFunctionPred predicate ); 44 32 45 } // namespace GenPoly 33 46 -
src/GenPoly/GenPoly.cc
r34b4268 r24d6572 24 24 #include <vector> // for vector 25 25 26 #include "AST/Expr.hpp" 26 27 #include "AST/Type.hpp" 28 #include "AST/TypeSubstitution.hpp" 27 29 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_it... 28 30 #include "ResolvExpr/typeops.h" // for flatten … … 170 172 171 173 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { 172 if ( tyVars. find( typeInst->get_name() ) != tyVars.end() ) {174 if ( tyVars.contains( typeInst->get_name() ) ) { 173 175 return type; 174 176 } … … 187 189 188 190 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) { 189 return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;191 if ( tyVars.contains( typeInst->typeString() ) ) return type; 190 192 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { 191 193 return isPolyType( arrayType->base, env ); … … 203 205 204 206 if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) { 205 if ( typeVars. find( *inst ) != typeVars.end() ) return type;207 if ( typeVars.contains( *inst ) ) return type; 206 208 } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) { 207 209 return isPolyType( array->base, subst ); … … 272 274 return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes ); 273 275 } 276 277 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) { 278 if ( func->returns.empty() ) return nullptr; 279 280 TypeVarMap forallTypes = { ast::TypeData() }; 281 makeTypeVarMap( func, forallTypes ); 282 return isDynType( func->returns.front(), forallTypes ); 283 } 274 284 275 285 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) { … … 317 327 return 0; 318 328 } 329 330 const ast::Type * isPolyPtr( 331 const ast::Type * type, const TypeVarMap & typeVars, 332 const ast::TypeSubstitution * typeSubs ) { 333 type = replaceTypeInst( type, typeSubs ); 334 335 if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) { 336 return isPolyType( ptr->base, typeVars, typeSubs ); 337 } 338 return nullptr; 339 } 319 340 320 341 Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) { … … 391 412 392 413 if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) { 393 if ( tyVars. find( typeInstType->get_name() ) != tyVars.end() ) {414 if ( tyVars.contains( typeInstType->get_name() ) ) { 394 415 return true; 395 416 } … … 490 511 } 491 512 513 /// Flattens a list of types. 514 // There is another flattenList in Unify. 492 515 void flattenList( vector<ast::ptr<ast::Type>> const & src, 493 516 vector<ast::ptr<ast::Type>> & out ) { … … 792 815 } 793 816 817 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) { 818 typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) ); 819 } 820 794 821 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) { 795 typeVars.insert( *type, ast::TypeData( type->base ) );822 typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) ); 796 823 } 797 824 … … 818 845 } 819 846 847 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) { 848 for ( auto & typeDecl : decl->type_params ) { 849 addToTypeVarMap( typeDecl, typeVars ); 850 } 851 } 852 820 853 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) { 821 854 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) { -
src/GenPoly/GenPoly.h
r34b4268 r24d6572 111 111 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ); 112 112 void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars ); 113 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ); 113 114 114 115 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 115 116 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ); 116 117 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ); 118 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ); 117 119 118 120 /// Prints type variable map -
src/GenPoly/InstantiateGeneric.cc
r34b4268 r24d6572 28 28 #include "GenPoly.h" // for isPolyType, typesPolyCompatible 29 29 #include "InitTweak/InitTweak.h" 30 #include "ResolvExpr/typeops.h" 30 #include "ResolvExpr/AdjustExprType.hpp" // for adjustExprType 31 #include "ResolvExpr/Unify.h" // for typesCompatible 31 32 #include "ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 32 33 #include "ScrubTyVars.h" // for ScrubTyVars -
src/GenPoly/InstantiateGenericNew.cpp
r34b4268 r24d6572 32 32 #include "GenPoly/GenPoly.h" // for isPolyType, typesPolyCompatible 33 33 #include "GenPoly/ScrubTyVars.h" // for scrubAll 34 #include "ResolvExpr/typeops.h" // for typesCompatible 34 #include "ResolvExpr/AdjustExprType.hpp" // for adjustExprType 35 #include "ResolvExpr/Unify.h" // for typesCompatible 35 36 36 37 namespace GenPoly { … … 361 362 ResolvExpr::typesCompatible( 362 363 memberExpr->result, 363 memberExpr->member->get_type() , ast::SymbolTable()) ) {364 memberExpr->member->get_type() ) ) { 364 365 return memberExpr; 365 366 } -
src/GenPoly/Lvalue.cc
r34b4268 r24d6572 17 17 #include <string> // for string 18 18 19 #include "Common/ToString.hpp" // for toCString 19 20 #include "Common/UniqueName.h" 20 21 #include "Common/PassVisitor.h" -
src/GenPoly/LvalueNew.cpp
r34b4268 r24d6572 25 25 #include "AST/Pass.hpp" 26 26 #include "Common/SemanticError.h" // for SemanticWarning 27 #include "Common/ToString.hpp" // for toCString 27 28 #include "Common/UniqueName.h" // for UniqueName 28 29 #include "GenPoly/GenPoly.h" // for genFunctionType … … 358 359 !ResolvExpr::typesCompatible( 359 360 srcType, 360 strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base, 361 ast::SymbolTable() ) ) { 361 strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) { 362 362 // Must keep cast if cast-to type is different from the actual type. 363 363 return ast::mutate_field( expr, &ast::CastExpr::arg, ret ); … … 376 376 if ( !ResolvExpr::typesCompatibleIgnoreQualifiers( 377 377 dstType->stripReferences(), 378 srcType->stripReferences(), 379 ast::SymbolTable() ) ) { 378 srcType->stripReferences() ) ) { 380 379 return ast::mutate_field( expr, &ast::CastExpr::arg, ret ); 381 380 } … … 392 391 ResolvExpr::typesCompatible( 393 392 expr->result, 394 expr->arg->result , ast::SymbolTable()) ) {393 expr->arg->result ) ) { 395 394 PRINT( 396 395 std::cerr << "types are compatible, removing cast: " << expr << '\n'; … … 589 588 ast::OpenVarSet openVars; 590 589 ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv, 591 needAssertions, haveAssertions, openVars, 592 ast::SymbolTable(), common ); 590 needAssertions, haveAssertions, openVars, common ); 593 591 ret->result = common ? common : ast::deepCopy( ret->arg2->result ); 594 592 return ret; -
src/GenPoly/ScopedSet.h
r34b4268 r24d6572 21 21 22 22 namespace GenPoly { 23 /// A set where the items are placed into nested scopes; 24 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward 25 template<typename Value> 26 class ScopedSet { 27 typedef std::set< Value > Scope; 28 typedef std::vector< Scope > ScopeList; 29 30 ScopeList scopes; ///< scoped list of sets 31 public: 32 typedef typename Scope::key_type key_type; 33 typedef typename Scope::value_type value_type; 34 typedef typename ScopeList::size_type size_type; 35 typedef typename ScopeList::difference_type difference_type; 36 typedef typename Scope::reference reference; 37 typedef typename Scope::const_reference const_reference; 38 typedef typename Scope::pointer pointer; 39 typedef typename Scope::const_pointer const_pointer; 40 41 class iterator : public std::iterator< std::bidirectional_iterator_tag, 42 value_type > { 43 friend class ScopedSet; 44 friend class const_iterator; 45 typedef typename std::set< Value >::iterator wrapped_iterator; 46 typedef typename std::vector< std::set< Value > > scope_list; 47 typedef typename scope_list::size_type size_type; 48 49 /// Checks if this iterator points to a valid item 50 bool is_valid() const { 51 return it != (*scopes)[i].end(); 52 } 53 54 /// Increments on invalid 55 iterator& next_valid() { 56 if ( ! is_valid() ) { ++(*this); } 57 return *this; 58 } 59 60 /// Decrements on invalid 61 iterator& prev_valid() { 62 if ( ! is_valid() ) { --(*this); } 63 return *this; 64 } 65 66 iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i) 67 : scopes(&_scopes), it(_it), i(_i) {} 68 public: 69 iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 70 iterator& operator= (const iterator &that) { 71 scopes = that.scopes; i = that.i; it = that.it; 72 return *this; 73 } 74 75 reference operator* () { return *it; } 76 pointer operator-> () { return it.operator->(); } 77 78 iterator& operator++ () { 79 if ( it == (*scopes)[i].end() ) { 80 if ( i == 0 ) return *this; 81 --i; 82 it = (*scopes)[i].begin(); 83 } else { 84 ++it; 85 } 86 return next_valid(); 87 } 88 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } 89 90 iterator& operator-- () { 91 // may fail if this is the begin iterator; allowed by STL spec 92 if ( it == (*scopes)[i].begin() ) { 93 ++i; 94 it = (*scopes)[i].end(); 95 } 96 --it; 97 return prev_valid(); 98 } 99 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; } 100 101 bool operator== (const iterator &that) { 102 return scopes == that.scopes && i == that.i && it == that.it; 103 } 104 bool operator!= (const iterator &that) { return !( *this == that ); } 105 106 size_type get_level() const { return i; } 107 108 private: 109 scope_list const *scopes; 110 wrapped_iterator it; 111 size_type i; 112 }; 113 114 class const_iterator : public std::iterator< std::bidirectional_iterator_tag, 115 value_type > { 116 friend class ScopedSet; 117 typedef typename std::set< Value >::iterator wrapped_iterator; 118 typedef typename std::set< Value >::const_iterator wrapped_const_iterator; 119 typedef typename std::vector< std::set< Value > > scope_list; 120 typedef typename scope_list::size_type size_type; 121 122 /// Checks if this iterator points to a valid item 123 bool is_valid() const { 124 return it != (*scopes)[i].end(); 125 } 126 127 /// Increments on invalid 128 const_iterator& next_valid() { 129 if ( ! is_valid() ) { ++(*this); } 130 return *this; 131 } 132 133 /// Decrements on invalid 134 const_iterator& prev_valid() { 135 if ( ! is_valid() ) { --(*this); } 136 return *this; 137 } 138 139 const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i) 140 : scopes(&_scopes), it(_it), i(_i) {} 141 public: 142 const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 143 const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 144 const_iterator& operator= (const iterator &that) { 145 scopes = that.scopes; i = that.i; it = that.it; 146 return *this; 147 } 148 const_iterator& operator= (const const_iterator &that) { 149 scopes = that.scopes; i = that.i; it = that.it; 150 return *this; 151 } 152 153 const_reference operator* () { return *it; } 154 const_pointer operator-> () { return it.operator->(); } 155 156 const_iterator& operator++ () { 157 if ( it == (*scopes)[i].end() ) { 158 if ( i == 0 ) return *this; 159 --i; 160 it = (*scopes)[i].begin(); 161 } else { 162 ++it; 163 } 164 return next_valid(); 165 } 166 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } 167 168 const_iterator& operator-- () { 169 // may fail if this is the begin iterator; allowed by STL spec 170 if ( it == (*scopes)[i].begin() ) { 171 ++i; 172 it = (*scopes)[i].end(); 173 } 174 --it; 175 return prev_valid(); 176 } 177 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } 178 179 bool operator== (const const_iterator &that) { 180 return scopes == that.scopes && i == that.i && it == that.it; 181 } 182 bool operator!= (const const_iterator &that) { return !( *this == that ); } 183 184 size_type get_level() const { return i; } 185 186 private: 187 scope_list const *scopes; 188 wrapped_const_iterator it; 189 size_type i; 190 }; 191 192 /// Starts a new scope 193 void beginScope() { 194 Scope scope; 195 scopes.push_back(scope); 196 } 197 198 /// Ends a scope; invalidates any iterators pointing to elements of that scope 199 void endScope() { 200 scopes.pop_back(); 201 } 202 203 /// Default constructor initializes with one scope 204 ScopedSet() { beginScope(); } 205 206 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 207 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 208 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 209 iterator end() { return iterator(scopes, scopes[0].end(), 0); } 210 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); } 211 const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); } 212 213 /// Gets the index of the current scope (counted from 1) 214 size_type currentScope() const { return scopes.size(); } 215 216 /// Finds the given key in the outermost scope it occurs; returns end() for none such 217 iterator find( const Value &key ) { 218 for ( size_type i = scopes.size() - 1; ; --i ) { 219 typename Scope::iterator val = scopes[i].find( key ); 220 if ( val != scopes[i].end() ) return iterator( scopes, val, i ); 221 if ( i == 0 ) break; 222 } 223 return end(); 224 } 225 const_iterator find( const Value &key ) const { 226 return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) ); 227 } 228 229 /// Finds the given key in the outermost scope inside the given scope where it occurs 230 iterator findNext( const_iterator &it, const Value &key ) { 231 if ( it.i == 0 ) return end(); 23 24 /// A set where the items are placed into nested scopes; 25 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward 26 template<typename Value> 27 class ScopedSet { 28 typedef std::set< Value > Scope; 29 typedef std::vector< Scope > ScopeList; 30 31 /// Scoped list of sets. 32 ScopeList scopes; 33 public: 34 typedef typename Scope::key_type key_type; 35 typedef typename Scope::value_type value_type; 36 typedef typename ScopeList::size_type size_type; 37 typedef typename ScopeList::difference_type difference_type; 38 typedef typename Scope::reference reference; 39 typedef typename Scope::const_reference const_reference; 40 typedef typename Scope::pointer pointer; 41 typedef typename Scope::const_pointer const_pointer; 42 43 // Both iterator types are complete bidirectional iterators, see below. 44 class iterator; 45 class const_iterator; 46 47 /// Starts a new scope 48 void beginScope() { 49 Scope scope; 50 scopes.push_back(scope); 51 } 52 53 /// Ends a scope; invalidates any iterators pointing to elements of that scope 54 void endScope() { 55 scopes.pop_back(); 56 } 57 58 /// Default constructor initializes with one scope 59 ScopedSet() { beginScope(); } 60 61 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 62 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 63 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); } 64 iterator end() { return iterator(scopes, scopes[0].end(), 0); } 65 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); } 66 const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); } 67 68 /// Gets the index of the current scope (counted from 1) 69 size_type currentScope() const { return scopes.size(); } 70 71 /// Finds the given key in the outermost scope it occurs; returns end() for none such 72 iterator find( const Value &key ) { 73 for ( size_type i = scopes.size() - 1; ; --i ) { 74 typename Scope::iterator val = scopes[i].find( key ); 75 if ( val != scopes[i].end() ) return iterator( scopes, val, i ); 76 if ( i == 0 ) break; 77 } 78 return end(); 79 } 80 const_iterator find( const Value &key ) const { 81 return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) ); 82 } 83 84 /// Finds the given key in the outermost scope inside the given scope where it occurs 85 iterator findNext( const_iterator &it, const Value &key ) { 86 if ( it.i == 0 ) return end(); 232 87 for ( size_type i = it.i - 1; ; --i ) { 233 typename Scope::iterator val = scopes[i].find( key ); 234 if ( val != scopes[i].end() ) return iterator( scopes, val, i ); 235 if ( i == 0 ) break; 236 } 237 return end(); 238 } 239 const_iterator findNext( const_iterator &it, const Value &key ) const { 240 return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) ); 241 } 242 243 /// Inserts the given value into the outermost scope 244 std::pair< iterator, bool > insert( const value_type &value ) { 245 std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value ); 246 return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second ); 247 } 248 249 }; 88 typename Scope::iterator val = scopes[i].find( key ); 89 if ( val != scopes[i].end() ) return iterator( scopes, val, i ); 90 if ( i == 0 ) break; 91 } 92 return end(); 93 } 94 const_iterator findNext( const_iterator &it, const Value &key ) const { 95 return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) ); 96 } 97 98 /// Inserts the given value into the outermost scope 99 std::pair< iterator, bool > insert( const value_type &value ) { 100 std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value ); 101 return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second ); 102 } 103 104 bool contains( const Value & key ) const { 105 return find( key ) != cend(); 106 } 107 }; 108 109 template<typename Value> 110 class ScopedSet<Value>::iterator : 111 public std::iterator< std::bidirectional_iterator_tag, value_type > { 112 friend class ScopedSet; 113 friend class const_iterator; 114 typedef typename std::set< Value >::iterator wrapped_iterator; 115 typedef typename std::vector< std::set< Value > > scope_list; 116 typedef typename scope_list::size_type size_type; 117 118 /// Checks if this iterator points to a valid item 119 bool is_valid() const { 120 return it != (*scopes)[i].end(); 121 } 122 123 /// Increments on invalid 124 iterator& next_valid() { 125 if ( ! is_valid() ) { ++(*this); } 126 return *this; 127 } 128 129 /// Decrements on invalid 130 iterator& prev_valid() { 131 if ( ! is_valid() ) { --(*this); } 132 return *this; 133 } 134 135 iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i) 136 : scopes(&_scopes), it(_it), i(_i) {} 137 public: 138 iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 139 iterator& operator= (const iterator &that) { 140 scopes = that.scopes; i = that.i; it = that.it; 141 return *this; 142 } 143 144 reference operator* () { return *it; } 145 pointer operator-> () { return it.operator->(); } 146 147 iterator& operator++ () { 148 if ( it == (*scopes)[i].end() ) { 149 if ( i == 0 ) return *this; 150 --i; 151 it = (*scopes)[i].begin(); 152 } else { 153 ++it; 154 } 155 return next_valid(); 156 } 157 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } 158 159 iterator& operator-- () { 160 // may fail if this is the begin iterator; allowed by STL spec 161 if ( it == (*scopes)[i].begin() ) { 162 ++i; 163 it = (*scopes)[i].end(); 164 } 165 --it; 166 return prev_valid(); 167 } 168 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; } 169 170 bool operator== (const iterator &that) { 171 return scopes == that.scopes && i == that.i && it == that.it; 172 } 173 bool operator!= (const iterator &that) { return !( *this == that ); } 174 175 size_type get_level() const { return i; } 176 177 private: 178 scope_list const *scopes; 179 wrapped_iterator it; 180 size_type i; 181 }; 182 183 template<typename Value> 184 class ScopedSet<Value>::const_iterator : 185 public std::iterator< std::bidirectional_iterator_tag, value_type > { 186 friend class ScopedSet; 187 typedef typename std::set< Value >::iterator wrapped_iterator; 188 typedef typename std::set< Value >::const_iterator wrapped_const_iterator; 189 typedef typename std::vector< std::set< Value > > scope_list; 190 typedef typename scope_list::size_type size_type; 191 192 /// Checks if this iterator points to a valid item 193 bool is_valid() const { 194 return it != (*scopes)[i].end(); 195 } 196 197 /// Increments on invalid 198 const_iterator& next_valid() { 199 if ( ! is_valid() ) { ++(*this); } 200 return *this; 201 } 202 203 /// Decrements on invalid 204 const_iterator& prev_valid() { 205 if ( ! is_valid() ) { --(*this); } 206 return *this; 207 } 208 209 const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i) 210 : scopes(&_scopes), it(_it), i(_i) {} 211 public: 212 const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 213 const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {} 214 const_iterator& operator= (const iterator &that) { 215 scopes = that.scopes; i = that.i; it = that.it; 216 return *this; 217 } 218 const_iterator& operator= (const const_iterator &that) { 219 scopes = that.scopes; i = that.i; it = that.it; 220 return *this; 221 } 222 223 const_reference operator* () { return *it; } 224 const_pointer operator-> () { return it.operator->(); } 225 226 const_iterator& operator++ () { 227 if ( it == (*scopes)[i].end() ) { 228 if ( i == 0 ) return *this; 229 --i; 230 it = (*scopes)[i].begin(); 231 } else { 232 ++it; 233 } 234 return next_valid(); 235 } 236 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } 237 238 const_iterator& operator-- () { 239 // may fail if this is the begin iterator; allowed by STL spec 240 if ( it == (*scopes)[i].begin() ) { 241 ++i; 242 it = (*scopes)[i].end(); 243 } 244 --it; 245 return prev_valid(); 246 } 247 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } 248 249 bool operator== (const const_iterator &that) { 250 return scopes == that.scopes && i == that.i && it == that.it; 251 } 252 bool operator!= (const const_iterator &that) { return !( *this == that ); } 253 254 size_type get_level() const { return i; } 255 256 private: 257 scope_list const *scopes; 258 wrapped_const_iterator it; 259 size_type i; 260 }; 261 250 262 } // namespace GenPoly 251 263 -
src/GenPoly/ScrubTyVars.cc
r34b4268 r24d6572 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 15:42:00 202213 // Update Count : 512 // Last Modified On : Wed Dec 7 17:01:00 2022 13 // Update Count : 6 14 14 // 15 15 … … 117 117 namespace { 118 118 119 enum class ScrubMode {120 FromMap,121 DynamicFromMap,122 All,123 };124 125 119 struct ScrubTypeVars : 126 120 public ast::WithGuards, … … 184 178 185 179 ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) { 180 ast::TypeDecl::Kind kind; 186 181 // This implies that mode == ScrubMode::All. 187 182 if ( !typeVars ) { 188 if ( ast::TypeDecl::Ftype == type->kind ) { 189 return new ast::PointerType( 190 new ast::FunctionType( ast::FixedArgs ) ); 191 } else { 192 return new ast::PointerType( 193 new ast::VoidType( type->qualifiers ) ); 194 } 195 } 196 197 auto typeVar = typeVars->find( *type ); 198 if ( typeVar == typeVars->end() ) { 199 return type; 200 } 201 202 switch ( typeVar->second.kind ) { 203 case ::TypeDecl::Dtype: 204 case ::TypeDecl::Ttype: 183 kind = type->kind; 184 } else { 185 // Otherwise, only scrub the type var if it is in map. 186 auto typeVar = typeVars->find( *type ); 187 if ( typeVar == typeVars->end() ) { 188 return type; 189 } 190 kind = typeVar->second.kind; 191 } 192 193 switch ( kind ) { 194 case ast::TypeDecl::Dtype: 195 case ast::TypeDecl::Ttype: 205 196 return new ast::PointerType( 206 197 new ast::VoidType( type->qualifiers ) ); 207 case ::TypeDecl::Ftype:198 case ast::TypeDecl::Ftype: 208 199 return new ast::PointerType( 209 200 new ast::FunctionType( ast::VariableArgs ) ); 210 201 default: 211 assertf( false, 212 "Unhandled type variable kind: %d", typeVar->second.kind ); 202 assertf( false, "Unhandled type variable kind: %d", kind ); 213 203 throw; // Just in case the assert is removed, stop here. 214 204 } … … 253 243 } 254 244 245 } // namespace 246 255 247 const ast::Node * scrubTypeVarsBase( 256 const ast::Node * target, 257 ScrubMode mode, const TypeVarMap * typeVars ) { 248 const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) { 258 249 if ( ScrubMode::All == mode ) { 259 250 assert( nullptr == typeVars ); … … 262 253 } 263 254 ast::Pass<ScrubTypeVars> visitor( mode, typeVars ); 264 return target->accept( visitor ); 265 } 266 267 } // namespace 268 269 template<> 270 ast::Node const * scrubTypeVars<ast::Node>( 271 const ast::Node * target, const TypeVarMap & typeVars ) { 272 return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars ); 273 } 274 275 template<> 276 ast::Node const * scrubTypeVarsDynamic<ast::Node>( 277 ast::Node const * target, const TypeVarMap & typeVars ) { 278 return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars ); 279 } 280 281 template<> 282 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) { 283 return scrubTypeVarsBase( target, ScrubMode::All, nullptr ); 255 return node->accept( visitor ); 284 256 } 285 257 -
src/GenPoly/ScrubTyVars.h
r34b4268 r24d6572 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 15:51:00 202213 // Update Count : 412 // Last Modified On : Wed Dec 7 16:57:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 109 109 } 110 110 111 // ScrubMode and scrubTypeVarsBase are internal. 112 enum class ScrubMode { FromMap, DynamicFromMap, All }; 113 114 const ast::Node * scrubTypeVarsBase( 115 const ast::Node * target, const TypeVarMap * typeVars, ScrubMode mode ); 116 117 111 118 /// For all polymorphic types with type variables in `typeVars`, 112 119 /// replaces generic types, dtypes, and ftypes with the appropriate void type, … … 116 123 node_t const * target, const TypeVarMap & typeVars ) { 117 124 return strict_dynamic_cast<node_t const *>( 118 scrubTypeVars <ast::Node>( target, typeVars) );125 scrubTypeVarsBase( target, &typeVars, ScrubMode::FromMap ) ); 119 126 } 120 127 … … 123 130 /// and sizeof/alignof expressions with the proper variable. 124 131 template<typename node_t> 125 ast::Nodeconst * scrubTypeVarsDynamic(132 node_t const * scrubTypeVarsDynamic( 126 133 node_t const * target, const TypeVarMap & typeVars ) { 127 134 return strict_dynamic_cast<node_t const *>( 128 scrubTypeVars Dynamic<ast::Node>( target, typeVars) );135 scrubTypeVarsBase( target, &typeVars, ScrubMode::DynamicFromMap ) ); 129 136 } 130 137 … … 134 141 node_t const * scrubAllTypeVars( node_t const * target ) { 135 142 return strict_dynamic_cast<node_t const *>( 136 scrub AllTypeVars<ast::Node>( target) );143 scrubTypeVarsBase( target, nullptr, ScrubMode::All ) ); 137 144 } 138 139 // We specialize for Node as a base case.140 template<>141 ast::Node const * scrubTypeVars<ast::Node>(142 const ast::Node * target, const TypeVarMap & typeVars );143 144 template<>145 ast::Node const * scrubTypeVarsDynamic<ast::Node>(146 ast::Node const * target, const TypeVarMap & typeVars );147 148 template<>149 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );150 145 151 146 } // namespace GenPoly -
src/GenPoly/SpecializeNew.cpp
r34b4268 r24d6572 16 16 #include "Specialize.h" 17 17 18 #include "AST/Copy.hpp" // for deepCopy 18 19 #include "AST/Inspect.hpp" // for isIntrinsicCallExpr 19 20 #include "AST/Pass.hpp" // for Pass -
src/InitTweak/FixInit.cc
r34b4268 r24d6572 32 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 33 33 #include "Common/SemanticError.h" // for SemanticError 34 #include "Common/ToString.hpp" // for toCString 34 35 #include "Common/UniqueName.h" // for UniqueName 35 #include "Common/utility.h" // for CodeLocation, ValueGuard, toSt...36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor … … 39 39 #include "InitTweak.h" // for getFunctionName, getCallArg 40 40 #include "ResolvExpr/Resolver.h" // for findVoidExpression 41 #include "ResolvExpr/ typeops.h"// for typesCompatible41 #include "ResolvExpr/Unify.h" // for typesCompatible 42 42 #include "SymTab/Autogen.h" // for genImplicitCall 43 43 #include "SymTab/Indexer.h" // for Indexer … … 1233 1233 } 1234 1234 1235 template< typename Visitor, typename... Params >1236 void error( Visitor & v, CodeLocation loc, const Params &... params ) {1237 SemanticErrorException err( loc, toString( params... ) );1238 v.errors.append( err );1239 }1240 1241 1235 template< typename... Params > 1242 1236 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1243 // toggle warnings vs. errors here. 1244 // warn( params... ); 1245 error( *this, loc, params... ); 1237 SemanticErrorException err( loc, toString( params... ) ); 1238 errors.append( err ); 1246 1239 } 1247 1240 -
src/InitTweak/FixInitNew.cpp
r34b4268 r24d6572 14 14 #include <utility> // for pair 15 15 16 #include "AST/DeclReplacer.hpp" 17 #include "AST/Expr.hpp" 16 18 #include "AST/Inspect.hpp" // for getFunction, getPointerBase, g... 19 #include "AST/Node.hpp" 20 #include "AST/Pass.hpp" 21 #include "AST/Print.hpp" 22 #include "AST/SymbolTable.hpp" 23 #include "AST/Type.hpp" 17 24 #include "CodeGen/GenType.h" // for genPrettyType 18 25 #include "CodeGen/OperatorTable.h" 19 #include "Common/CodeLocationTools.hpp"20 26 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 21 27 #include "Common/SemanticError.h" // for SemanticError 28 #include "Common/ToString.hpp" // for toCString 22 29 #include "Common/UniqueName.h" // for UniqueName 23 #include "Common/utility.h" // for CodeLocation, ValueGuard, toSt...24 30 #include "FixGlobalInit.h" // for fixGlobalInit 25 31 #include "GenInit.h" // for genCtorDtor 26 32 #include "GenPoly/GenPoly.h" // for getFunctionType 27 33 #include "ResolvExpr/Resolver.h" // for findVoidExpression 28 #include "ResolvExpr/ typeops.h"// for typesCompatible34 #include "ResolvExpr/Unify.h" // for typesCompatible 29 35 #include "SymTab/Autogen.h" // for genImplicitCall 36 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 30 37 #include "SymTab/Indexer.h" // for Indexer 31 38 #include "SymTab/Mangler.h" // for Mangler … … 45 52 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy 46 53 47 #include "AST/Expr.hpp"48 #include "AST/Node.hpp"49 #include "AST/Pass.hpp"50 #include "AST/Print.hpp"51 #include "AST/SymbolTable.hpp"52 #include "AST/Type.hpp"53 #include "AST/DeclReplacer.hpp"54 55 54 extern bool ctordtorp; // print all debug 56 55 extern bool ctorp; // print ctor debug … … 63 62 namespace InitTweak { 64 63 namespace { 64 65 // Shallow copy the pointer list for return. 66 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams( const ast::Type * t ) { 67 if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) { 68 return inst->base->params; 69 } 70 if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) { 71 return inst->base->params; 72 } 73 return {}; 74 } 75 76 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &). 77 ast::FunctionDecl * genDefaultFunc( 78 const CodeLocation loc, 79 const std::string fname, 80 const ast::Type * paramType, 81 bool maybePolymorphic = true) { 82 std::vector<ast::ptr<ast::TypeDecl>> typeParams; 83 if ( maybePolymorphic ) typeParams = getGenericParams( paramType ); 84 auto dstParam = new ast::ObjectDecl( loc, 85 "_dst", 86 new ast::ReferenceType( paramType ), 87 nullptr, 88 {}, 89 ast::Linkage::Cforall 90 ); 91 return new ast::FunctionDecl( loc, 92 fname, 93 std::move(typeParams), 94 {dstParam}, 95 {}, 96 new ast::CompoundStmt(loc), 97 {}, 98 ast::Linkage::Cforall 99 ); 100 } 101 65 102 struct SelfAssignChecker { 66 103 void previsit( const ast::ApplicationExpr * appExpr ); … … 107 144 private: 108 145 /// hack to implement WithTypeSubstitution while conforming to mutation safety. 109 ast::TypeSubstitution * env ;110 bool envModified ;146 ast::TypeSubstitution * env = nullptr; 147 bool envModified = false; 111 148 }; 112 149 … … 121 158 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 122 159 123 protected:160 protected: 124 161 ObjectSet curVars; 125 162 }; … … 202 239 203 240 SemanticErrorException errors; 204 private:241 private: 205 242 template< typename... Params > 206 243 void emit( CodeLocation, const Params &... params ); … … 288 325 static UniqueName dtorNamer( "__cleanup_dtor" ); 289 326 std::string name = dtorNamer.newName(); 290 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );327 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false ); 291 328 stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) ); 292 329 … … 522 559 { 523 560 static UniqueName tempNamer("_tmp_cp"); 524 assert( env );525 561 const CodeLocation loc = impCpCtorExpr->location; 526 562 // CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; ) … … 534 570 535 571 // xxx - this originally mutates arg->result in place. is it correct? 572 assert( env ); 536 573 result = env->applyFree( result.get() ).node; 537 574 auto mutResult = result.get_and_mutate(); … … 1080 1117 void InsertDtors::previsit( const ast::BranchStmt * stmt ) { 1081 1118 switch( stmt->kind ) { 1082 case ast::BranchStmt::Continue:1083 case ast::BranchStmt::Break:1119 case ast::BranchStmt::Continue: 1120 case ast::BranchStmt::Break: 1084 1121 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 1085 1122 // always be empty), but it serves as a small sanity check. 1086 case ast::BranchStmt::Goto:1123 case ast::BranchStmt::Goto: 1087 1124 handleGoto( stmt ); 1088 1125 break; 1089 default:1126 default: 1090 1127 assert( false ); 1091 1128 } // switch … … 1303 1340 } 1304 1341 1305 template< typename Visitor, typename... Params >1306 void error( Visitor & v, CodeLocation loc, const Params &... params ) {1307 SemanticErrorException err( loc, toString( params... ) );1308 v.errors.append( err );1309 }1310 1311 1342 template< typename... Params > 1312 1343 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1313 // toggle warnings vs. errors here. 1314 // warn( params... ); 1315 error( *this, loc, params... ); 1344 SemanticErrorException err( loc, toString( params... ) ); 1345 errors.append( err ); 1316 1346 } 1317 1347 … … 1319 1349 // xxx - functions returning ast::ptr seems wrong... 1320 1350 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1321 // Fix CodeLocation (at least until resolver is fixed). 1322 auto fix = localFillCodeLocations( untypedExpr->location, res.release() ); 1323 return strict_dynamic_cast<const ast::Expr *>( fix ); 1351 return res.release(); 1324 1352 } 1325 1353 -
src/InitTweak/GenInit.cc
r34b4268 r24d6572 31 31 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 32 32 #include "Common/SemanticError.h" // for SemanticError 33 #include "Common/ToString.hpp" // for toCString 33 34 #include "Common/UniqueName.h" // for UniqueName 34 35 #include "Common/utility.h" // for ValueGuard, maybeClone … … 38 39 #include "ResolvExpr/Resolver.h" 39 40 #include "SymTab/Autogen.h" // for genImplicitCall 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 40 42 #include "SymTab/Mangler.h" // for Mangler 41 43 #include "SynTree/LinkageSpec.h" // for isOverridable, C -
src/InitTweak/InitTweak.cc
r34b4268 r24d6572 35 35 #include "GenPoly/GenPoly.h" // for getFunctionType 36 36 #include "InitTweak.h" 37 #include "ResolvExpr/ typeops.h"// for typesCompatibleIgnoreQualifiers37 #include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers 38 38 #include "SymTab/Autogen.h" 39 39 #include "SymTab/Indexer.h" // for Indexer … … 1066 1066 const ast::Type * t2 = ftype->params.back(); 1067 1067 1068 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 , ast::SymbolTable());1068 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 ); 1069 1069 } 1070 1070 -
src/MakeLibCfaNew.cpp
r34b4268 r24d6572 16 16 #include "MakeLibCfa.h" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Fwd.hpp" 19 20 #include "AST/Pass.hpp" -
src/Parser/DeclarationNode.cc
r34b4268 r24d6572 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 12:34:05 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Aug 8 17:07:00 202213 // Update Count : 1 18511 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Apr 20 11:46:00 2023 13 // Update Count : 1393 14 14 // 15 16 #include "DeclarationNode.h" 15 17 16 18 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 21 23 #include <string> // for string, operator+, allocator, char... 22 24 25 #include "AST/Attribute.hpp" // for Attribute 26 #include "AST/Copy.hpp" // for shallowCopy 27 #include "AST/Decl.hpp" // for Decl 28 #include "AST/Expr.hpp" // for Expr 29 #include "AST/Print.hpp" // for print 30 #include "AST/Stmt.hpp" // for AsmStmt, DirectiveStmt 31 #include "AST/StorageClasses.hpp" // for Storage::Class 32 #include "AST/Type.hpp" // for Type 33 #include "Common/CodeLocation.h" // for CodeLocation 34 #include "Common/Iterate.hpp" // for reverseIterate 23 35 #include "Common/SemanticError.h" // for SemanticError 24 36 #include "Common/UniqueName.h" // for UniqueName 25 #include "Common/utility.h" // for maybeClone, maybeBuild, CodeLocation 26 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 27 #include "SynTree/LinkageSpec.h" // for Spec, linkageName, Cforall 28 #include "SynTree/Attribute.h" // for Attribute 29 #include "SynTree/Declaration.h" // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration 30 #include "SynTree/Expression.h" // for Expression, ConstantExpr 31 #include "SynTree/Statement.h" // for AsmStmt 32 #include "SynTree/Type.h" // for Type, Type::StorageClasses, Type::... 37 #include "Common/utility.h" // for maybeClone 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 #include "Parser/InitializerNode.h"// for InitializerNode 40 #include "Parser/StatementNode.h" // for StatementNode 33 41 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 34 42 #include "TypedefTable.h" // for TypedefTable … … 41 49 42 50 // These must harmonize with the corresponding DeclarationNode enumerations. 43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128", 44 "float", "double", "long double", "float80", "float128", 45 "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" }; 46 const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message 47 const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" }; 48 const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" }; 49 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" }; 51 const char * DeclarationNode::basicTypeNames[] = { 52 "void", "_Bool", "char", "int", "int128", 53 "float", "double", "long double", "float80", "float128", 54 "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" 55 }; 56 const char * DeclarationNode::complexTypeNames[] = { 57 "_Complex", "NoComplexTypeNames", "_Imaginary" 58 }; // Imaginary unsupported => parse, but make invisible and print error message 59 const char * DeclarationNode::signednessNames[] = { 60 "signed", "unsigned", "NoSignednessNames" 61 }; 62 const char * DeclarationNode::lengthNames[] = { 63 "short", "long", "long long", "NoLengthNames" 64 }; 65 const char * DeclarationNode::builtinTypeNames[] = { 66 "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" 67 }; 50 68 51 69 UniqueName DeclarationNode::anonymous( "__anonymous" ); 52 70 53 extern LinkageSpec::Spec linkage; // defined in parser.yy71 extern ast::Linkage::Spec linkage; // defined in parser.yy 54 72 55 73 DeclarationNode::DeclarationNode() : … … 57 75 58 76 // variable.name = nullptr; 59 variable.tyClass = TypeDecl::NUMBER_OF_KINDS;77 variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS; 60 78 variable.assertions = nullptr; 61 79 variable.initializer = nullptr; 62 80 63 // attr.name = nullptr;64 attr.expr = nullptr;65 attr.type = nullptr;66 67 81 assert.condition = nullptr; 68 82 assert.message = nullptr; … … 70 84 71 85 DeclarationNode::~DeclarationNode() { 72 // delete attr.name;73 delete attr.expr;74 delete attr.type;75 76 86 // delete variable.name; 77 87 delete variable.assertions; 78 88 delete variable.initializer; 79 89 80 // delete type;90 // delete type; 81 91 delete bitfieldWidth; 82 92 … … 103 113 newnode->hasEllipsis = hasEllipsis; 104 114 newnode->linkage = linkage; 105 newnode->asmName = maybeC lone( asmName );106 cloneAll( attributes, newnode->attributes );115 newnode->asmName = maybeCopy( asmName ); 116 newnode->attributes = attributes; 107 117 newnode->initializer = maybeClone( initializer ); 108 118 newnode->extension = extension; … … 115 125 newnode->variable.initializer = maybeClone( variable.initializer ); 116 126 117 // newnode->attr.name = attr.name ? new string( *attr.name ) : nullptr;118 newnode->attr.expr = maybeClone( attr.expr );119 newnode->attr.type = maybeClone( attr.type );120 121 127 newnode->assert.condition = maybeClone( assert.condition ); 122 newnode->assert.message = maybeC lone( assert.message );128 newnode->assert.message = maybeCopy( assert.message ); 123 129 return newnode; 124 130 } // DeclarationNode::clone … … 130 136 } // if 131 137 132 if ( linkage != LinkageSpec::Cforall ) {133 os << LinkageSpec::name( linkage ) << " ";134 } // if 135 136 storageClasses.print( os );137 funcSpecs.print( os );138 if ( linkage != ast::Linkage::Cforall ) { 139 os << ast::Linkage::name( linkage ) << " "; 140 } // if 141 142 ast::print( os, storageClasses ); 143 ast::print( os, funcSpecs ); 138 144 139 145 if ( type ) { … … 154 160 } // if 155 161 156 for ( Attribute * attr: reverseIterate( attributes ) ) { 157 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str(); 158 } // for 162 if ( ! attributes.empty() ) { 163 os << string( indent + 2, ' ' ) << "with attributes " << endl; 164 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) { 165 os << string( indent + 4, ' ' ) << attr->name.c_str() << endl; 166 } // for 167 } // if 159 168 160 169 os << endl; … … 168 177 } 169 178 170 DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) {179 DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) { 171 180 DeclarationNode * newnode = new DeclarationNode; 172 181 newnode->storageClasses = sc; … … 174 183 } // DeclarationNode::newStorageClass 175 184 176 DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) {185 DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) { 177 186 DeclarationNode * newnode = new DeclarationNode; 178 187 newnode->funcSpecs = fs; … … 180 189 } // DeclarationNode::newFuncSpecifier 181 190 182 DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) {191 DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) { 183 192 DeclarationNode * newnode = new DeclarationNode; 184 193 newnode->type = new TypeData(); … … 240 249 } 241 250 242 DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {251 DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) { 243 252 DeclarationNode * newnode = new DeclarationNode; 244 253 newnode->type = new TypeData( TypeData::Aggregate ); 245 254 newnode->type->aggregate.kind = kind; 246 newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 255 newnode->type->aggregate.anon = name == nullptr; 256 newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 247 257 newnode->type->aggregate.actuals = actuals; 248 258 newnode->type->aggregate.fields = fields; … … 250 260 newnode->type->aggregate.tagged = false; 251 261 newnode->type->aggregate.parent = nullptr; 252 newnode->type->aggregate.anon = name == nullptr;253 262 return newnode; 254 263 } // DeclarationNode::newAggregate … … 257 266 DeclarationNode * newnode = new DeclarationNode; 258 267 newnode->type = new TypeData( TypeData::Enum ); 259 newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 268 newnode->type->enumeration.anon = name == nullptr; 269 newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 260 270 newnode->type->enumeration.constants = constants; 261 271 newnode->type->enumeration.body = body; 262 newnode->type->enumeration.anon = name == nullptr;263 272 newnode->type->enumeration.typed = typed; 264 273 newnode->type->enumeration.hiding = hiding; 265 if ( base && base->type ) {274 if ( base && base->type ) { 266 275 newnode->type->base = base->type; 267 276 } // if … … 269 278 return newnode; 270 279 } // DeclarationNode::newEnum 271 272 273 280 274 281 DeclarationNode * DeclarationNode::newName( const string * name ) { … … 323 330 } // DeclarationNode::newFromTypeGen 324 331 325 DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) {332 DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) { 326 333 DeclarationNode * newnode = newName( name ); 327 334 newnode->type = nullptr; … … 335 342 newnode->type = new TypeData( TypeData::Aggregate ); 336 343 newnode->type->aggregate.name = name; 337 newnode->type->aggregate.kind = AggregateDecl::Trait;344 newnode->type->aggregate.kind = ast::AggregateDecl::Trait; 338 345 newnode->type->aggregate.params = params; 339 346 newnode->type->aggregate.fields = asserts; … … 345 352 newnode->type = new TypeData( TypeData::AggregateInst ); 346 353 newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate ); 347 newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait;354 newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait; 348 355 newnode->type->aggInst.aggregate->aggregate.name = name; 349 356 newnode->type->aggInst.params = params; … … 380 387 newnode->type->array.dimension = size; 381 388 newnode->type->array.isStatic = isStatic; 382 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType< ConstantExpr *>() ) {389 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ast::ConstantExpr *>() ) { 383 390 newnode->type->array.isVarLen = false; 384 391 } else { … … 450 457 DeclarationNode * newnode = new DeclarationNode; 451 458 newnode->type = nullptr; 452 std:: list< Expression *> exprs;459 std::vector<ast::ptr<ast::Expr>> exprs; 453 460 buildList( expr, exprs ); 454 newnode->attributes.push_back( new Attribute( *name, exprs ) ); 461 newnode->attributes.push_back( 462 new ast::Attribute( *name, std::move( exprs ) ) ); 455 463 delete name; 456 464 return newnode; … … 469 477 } 470 478 471 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression* message ) {479 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) { 472 480 DeclarationNode * newnode = new DeclarationNode; 473 481 newnode->assert.condition = condition; … … 476 484 } 477 485 478 479 void appendError( string & dst, const string & src ) { 486 static void appendError( string & dst, const string & src ) { 480 487 if ( src.empty() ) return; 481 488 if ( dst.empty() ) { dst = src; return; } … … 484 491 485 492 void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) { 486 const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization 487 488 if ( (qsrc & qdst).any() ) { // duplicates ? 489 for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates 490 if ( qsrc[i] && qdst[i] ) { 491 appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] ); 492 } // if 493 } // for 493 const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization 494 const ast::CV::Qualifiers duplicates = qsrc & qdst; 495 496 if ( duplicates.any() ) { 497 std::stringstream str; 498 str << "duplicate "; 499 ast::print( str, duplicates ); 500 str << "qualifier(s)"; 501 appendError( error, str.str() ); 494 502 } // for 495 503 } // DeclarationNode::checkQualifiers 496 504 497 505 void DeclarationNode::checkSpecifiers( DeclarationNode * src ) { 498 if ( (funcSpecs & src->funcSpecs).any() ) { // duplicates ? 499 for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates 500 if ( funcSpecs[i] && src->funcSpecs[i] ) { 501 appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] ); 502 } // if 503 } // for 504 } // if 505 506 if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ? 507 if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ? 508 for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates 509 if ( storageClasses[i] && src->storageClasses[i] ) { 510 appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] ); 511 } // if 512 } // for 513 // src is the new item being added and has a single bit 514 } else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ? 515 appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] + 516 " & " + Type::StorageClassesNames[src->storageClasses.ffs()] ); 517 src->storageClasses.reset(); // FIX to preserve invariant of one basic storage specifier 518 } // if 506 ast::Function::Specs fsDups = funcSpecs & src->funcSpecs; 507 if ( fsDups.any() ) { 508 std::stringstream str; 509 str << "duplicate "; 510 ast::print( str, fsDups ); 511 str << "function specifier(s)"; 512 appendError( error, str.str() ); 513 } // if 514 515 // Skip if everything is unset. 516 if ( storageClasses.any() && src->storageClasses.any() ) { 517 ast::Storage::Classes dups = storageClasses & src->storageClasses; 518 // Check for duplicates. 519 if ( dups.any() ) { 520 std::stringstream str; 521 str << "duplicate "; 522 ast::print( str, dups ); 523 str << "storage class(es)"; 524 appendError( error, str.str() ); 525 // Check for conflicts. 526 } else if ( !src->storageClasses.is_threadlocal_any() ) { 527 std::stringstream str; 528 str << "conflicting "; 529 ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) ); 530 str << "& "; 531 ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) ); 532 str << "storage classes"; 533 appendError( error, str.str() ); 534 // FIX to preserve invariant of one basic storage specifier 535 src->storageClasses.reset(); 536 } 519 537 } // if 520 538 … … 526 544 storageClasses |= q->storageClasses; 527 545 528 for ( Attribute * attr: reverseIterate( q->attributes ) ) { 529 attributes.push_front( attr->clone() ); 530 } // for 546 std::vector<ast::ptr<ast::Attribute>> tmp; 547 tmp.reserve( q->attributes.size() ); 548 for ( auto const & attr : q->attributes ) { 549 tmp.emplace_back( ast::shallowCopy( attr.get() ) ); 550 } 551 spliceBegin( attributes, tmp ); 552 531 553 return this; 532 554 } // DeclarationNode::copySpecifiers … … 576 598 577 599 checkQualifiers( type, q->type ); 578 if ( (builtin == Zero || builtin == One) && q->type->qualifiers. val != 0&& error.length() == 0 ) {579 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, Type::QualifiersNames[ilog2( q->type->qualifiers.val )],builtinTypeNames[builtin] );600 if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) { 601 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] ); 580 602 } // if 581 603 addQualifiersToType( q->type, type ); … … 598 620 } else { 599 621 switch ( dst->kind ) { 600 case TypeData::Unknown:622 case TypeData::Unknown: 601 623 src->qualifiers |= dst->qualifiers; 602 624 dst = src; 603 625 src = nullptr; 604 626 break; 605 case TypeData::Basic:627 case TypeData::Basic: 606 628 dst->qualifiers |= src->qualifiers; 607 629 if ( src->kind != TypeData::Unknown ) { … … 631 653 } // if 632 654 break; 633 default:655 default: 634 656 switch ( src->kind ) { 635 case TypeData::Aggregate:636 case TypeData::Enum:657 case TypeData::Aggregate: 658 case TypeData::Enum: 637 659 dst->base = new TypeData( TypeData::AggregateInst ); 638 660 dst->base->aggInst.aggregate = src; … … 643 665 src = nullptr; 644 666 break; 645 default:667 default: 646 668 if ( dst->forall ) { 647 669 dst->forall->appendList( src->forall ); … … 714 736 715 737 DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) { 716 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {717 if ( variable.assertions ) {718 variable.assertions->appendList( assertions );719 } else {720 variable.assertions = assertions;721 } // if722 return this;738 if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) { 739 if ( variable.assertions ) { 740 variable.assertions->appendList( assertions ); 741 } else { 742 variable.assertions = assertions; 743 } // if 744 return this; 723 745 } // if 724 746 725 747 assert( type ); 726 748 switch ( type->kind ) { 727 case TypeData::Symbolic:749 case TypeData::Symbolic: 728 750 if ( type->symbolic.assertions ) { 729 751 type->symbolic.assertions->appendList( assertions ); … … 732 754 } // if 733 755 break; 734 default:756 default: 735 757 assert( false ); 736 758 } // switch … … 796 818 DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) { 797 819 if ( a ) { 798 for ( Attribute *attr: reverseIterate( a->attributes ) ) { 799 attributes.push_front( attr ); 800 } // for 820 spliceBegin( attributes, a->attributes ); 801 821 a->attributes.clear(); 802 822 } // if … … 831 851 if ( type ) { 832 852 switch ( type->kind ) { 833 case TypeData::Aggregate:834 case TypeData::Enum:853 case TypeData::Aggregate: 854 case TypeData::Enum: 835 855 p->type->base = new TypeData( TypeData::AggregateInst ); 836 856 p->type->base->aggInst.aggregate = type; … … 841 861 break; 842 862 843 default:863 default: 844 864 p->type->base = type; 845 865 } // switch … … 863 883 864 884 DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) { 865 if ( ! a ) return this;885 if ( ! a ) return this; 866 886 assert( a->type->kind == TypeData::Array ); 867 887 TypeData * lastArray = findLast( a->type ); 868 888 if ( type ) { 869 889 switch ( type->kind ) { 870 case TypeData::Aggregate:871 case TypeData::Enum:890 case TypeData::Aggregate: 891 case TypeData::Enum: 872 892 lastArray->base = new TypeData( TypeData::AggregateInst ); 873 893 lastArray->base->aggInst.aggregate = type; … … 877 897 lastArray->base->qualifiers |= type->qualifiers; 878 898 break; 879 default:899 default: 880 900 lastArray->base = type; 881 901 } // switch … … 919 939 920 940 DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) { 921 assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );941 assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." ); 922 942 variable.initializer = init; 923 943 return this; … … 983 1003 } 984 1004 985 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) { 1005 // If a typedef wraps an anonymous declaration, name the inner declaration 1006 // so it has a consistent name across translation units. 1007 static void nameTypedefedDecl( 1008 DeclarationNode * innerDecl, 1009 const DeclarationNode * outerDecl ) { 1010 TypeData * outer = outerDecl->type; 1011 assert( outer ); 1012 // First make sure this is a typedef: 1013 if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) { 1014 return; 1015 } 1016 TypeData * inner = innerDecl->type; 1017 assert( inner ); 1018 // Always clear any CVs associated with the aggregate: 1019 inner->qualifiers.reset(); 1020 // Handle anonymous aggregates: typedef struct { int i; } foo 1021 if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) { 1022 delete inner->aggregate.name; 1023 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1024 inner->aggregate.anon = false; 1025 assert( outer->base ); 1026 delete outer->base->aggInst.aggregate->aggregate.name; 1027 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1028 outer->base->aggInst.aggregate->aggregate.anon = false; 1029 outer->base->aggInst.aggregate->qualifiers.reset(); 1030 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1031 } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) { 1032 delete inner->enumeration.name; 1033 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1034 inner->enumeration.anon = false; 1035 assert( outer->base ); 1036 delete outer->base->aggInst.aggregate->enumeration.name; 1037 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1038 outer->base->aggInst.aggregate->enumeration.anon = false; 1039 // No qualifiers.reset() here. 1040 } 1041 } 1042 1043 // This code handles a special issue with the attribute transparent_union. 1044 // 1045 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1046 // 1047 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1048 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1049 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1050 // alias. 1051 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) { 1052 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1053 // Is the typedef alias a union aggregate? 1054 if ( nullptr == unionDecl ) return; 1055 1056 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1057 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1058 auto instType = ast::mutate( unionInstType ); 1059 // Remove all transparent_union attributes from typedef and move to alias union. 1060 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { 1061 assert( *attr ); 1062 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1063 unionDecl->attributes.emplace_back( attr->release() ); 1064 attr = instType->attributes.erase( attr ); 1065 } else { 1066 attr++; 1067 } 1068 } 1069 typedefDecl->base = instType; 1070 } 1071 } 1072 } 1073 1074 // Get the non-anonymous name of the instance type of the declaration, 1075 // if one exists. 1076 static const std::string * getInstTypeOfName( ast::Decl * decl ) { 1077 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1078 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1079 if ( aggr->name.find("anonymous") == std::string::npos ) { 1080 return &aggr->name; 1081 } 1082 } 1083 } 1084 return nullptr; 1085 } 1086 1087 void buildList( DeclarationNode * firstNode, 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { 986 1089 SemanticErrorException errors; 987 std::back_insert_iterator< std::list< Declaration * >> out( outputList );988 989 for ( const DeclarationNode * cur = firstNode ; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1090 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1091 1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 990 1093 try { 991 bool extracted = false; 992 bool anon = false; 1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1096 993 1097 if ( DeclarationNode * extr = cur->extractAggregate() ) { 994 // handle the case where a structure declaration is contained within an object or type declaration 995 Declaration * decl = extr->build(); 996 if ( decl ) { 997 // hoist the structure declaration 998 decl->location = cur->location; 999 * out++ = decl; 1098 assert( cur->type ); 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 1102 // Remember the declaration if it is a union aggregate ? 1103 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 1104 1105 *out++ = decl; 1000 1106 1001 1107 // need to remember the cases where a declaration contains an anonymous aggregate definition 1002 extracted = true;1003 1108 assert( extr->type ); 1004 1109 if ( extr->type->kind == TypeData::Aggregate ) { 1005 anon = extr->type->aggregate.anon; 1110 // typedef struct { int A } B is the only case? 1111 extracted_named = !extr->type->aggregate.anon; 1006 1112 } else if ( extr->type->kind == TypeData::Enum ) { 1007 // xxx - is it useful to have an implicit anonymous enum member? 1008 anon = extr->type->enumeration.anon; 1113 // typedef enum { A } B is the only case? 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1009 1117 } 1010 1118 } // if … … 1012 1120 } // if 1013 1121 1014 Declaration * decl = cur->build(); 1015 if ( decl ) { 1016 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1017 // struct S { 1018 // struct T { int x; }; // no anonymous member 1019 // struct { int y; }; // anonymous member 1020 // struct T; // anonymous member 1021 // }; 1022 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) { 1023 if ( decl->name == "" ) { 1024 if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) { 1025 if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) { 1026 if ( aggr->name.find("anonymous") == std::string::npos ) { 1027 if ( ! cur->get_inLine() ) { 1028 // temporary: warn about anonymous member declarations of named types, since 1029 // this conflicts with the syntax for the forward declaration of an anonymous type 1030 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() ); 1031 } // if 1032 } // if 1033 } // if 1034 } // if 1035 } // if 1036 decl->location = cur->location; 1037 *out++ = decl; 1122 if ( ast::Decl * decl = cur->build() ) { 1123 moveUnionAttribute( decl, unionDecl ); 1124 1125 if ( "" == decl->name && !cur->get_inLine() ) { 1126 // Don't include anonymous declaration for named aggregates, 1127 // but do include them for anonymous aggregates, e.g.: 1128 // struct S { 1129 // struct T { int x; }; // no anonymous member 1130 // struct { int y; }; // anonymous member 1131 // struct T; // anonymous member 1132 // }; 1133 if ( extracted_named ) { 1134 continue; 1135 } 1136 1137 if ( auto name = getInstTypeOfName( decl ) ) { 1138 // Temporary: warn about anonymous member declarations of named types, since 1139 // this conflicts with the syntax for the forward declaration of an anonymous type. 1140 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() ); 1141 } 1038 1142 } // if 1143 *out++ = decl; 1039 1144 } // if 1040 } catch ( SemanticErrorException & e ) {1145 } catch ( SemanticErrorException & e ) { 1041 1146 errors.append( e ); 1042 1147 } // try … … 1049 1154 1050 1155 // currently only builds assertions, function parameters, and return values 1051 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType *> & outputList ) {1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) { 1052 1157 SemanticErrorException errors; 1053 std::back_insert_iterator< std::list< DeclarationWithType * >> out( outputList );1054 1055 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1158 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1159 1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) { 1056 1161 try { 1057 Declaration* decl = cur->build();1058 assert ( decl);1059 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType *>( decl ) ) {1162 ast::Decl * decl = cur->build(); 1163 assertf( decl, "buildList: build for ast::DeclWithType." ); 1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1060 1165 dwt->location = cur->location; 1061 1166 *out++ = dwt; 1062 } else if ( StructDecl * agg = dynamic_cast< StructDecl *>( decl ) ) {1167 } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) { 1063 1168 // e.g., int foo(struct S) {} 1064 StructInstType * inst = new StructInstType( Type::Qualifiers(),agg->name );1065 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr);1066 obj->l ocation = cur->location;1169 auto inst = new ast::StructInstType( agg->name ); 1170 auto obj = new ast::ObjectDecl( cur->location, "", inst ); 1171 obj->linkage = linkage; 1067 1172 *out++ = obj; 1068 1173 delete agg; 1069 } else if ( UnionDecl * agg = dynamic_cast< UnionDecl *>( decl ) ) {1174 } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) { 1070 1175 // e.g., int foo(union U) {} 1071 UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name ); 1072 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr ); 1073 obj->location = cur->location; 1176 auto inst = new ast::UnionInstType( agg->name ); 1177 auto obj = new ast::ObjectDecl( cur->location, 1178 "", inst, nullptr, ast::Storage::Classes(), 1179 linkage ); 1074 1180 *out++ = obj; 1075 } else if ( EnumDecl * agg = dynamic_cast< EnumDecl *>( decl ) ) {1181 } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) { 1076 1182 // e.g., int foo(enum E) {} 1077 EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name ); 1078 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr ); 1079 obj->location = cur->location; 1183 auto inst = new ast::EnumInstType( agg->name ); 1184 auto obj = new ast::ObjectDecl( cur->location, 1185 "", 1186 inst, 1187 nullptr, 1188 ast::Storage::Classes(), 1189 linkage 1190 ); 1080 1191 *out++ = obj; 1192 } else { 1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." ); 1081 1194 } // if 1082 } catch ( SemanticErrorException & e ) {1195 } catch ( SemanticErrorException & e ) { 1083 1196 errors.append( e ); 1084 1197 } // try … … 1090 1203 } // buildList 1091 1204 1092 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) { 1205 void buildTypeList( const DeclarationNode * firstNode, 1206 std::vector<ast::ptr<ast::Type>> & outputList ) { 1093 1207 SemanticErrorException errors; 1094 std::back_insert_iterator< std::list< Type * > > out( outputList ); 1095 const DeclarationNode * cur = firstNode; 1096 1097 while ( cur ) { 1208 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1098 1211 try { 1099 1212 * out++ = cur->buildType(); 1100 } catch ( SemanticErrorException & e ) {1213 } catch ( SemanticErrorException & e ) { 1101 1214 errors.append( e ); 1102 1215 } // try 1103 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1104 } // while 1216 } // for 1105 1217 1106 1218 if ( ! errors.isEmpty() ) { … … 1109 1221 } // buildTypeList 1110 1222 1111 Declaration* DeclarationNode::build() const {1223 ast::Decl * DeclarationNode::build() const { 1112 1224 if ( ! error.empty() ) SemanticError( this, error + " in declaration of " ); 1113 1225 1114 1226 if ( asmStmt ) { 1115 return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) ); 1227 auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() ); 1228 return new ast::AsmDecl( stmt->location, stmt ); 1116 1229 } // if 1117 1230 if ( directiveStmt ) { 1118 return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) ); 1119 } // if 1120 1121 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) { 1231 auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() ); 1232 return new ast::DirectiveDecl( stmt->location, stmt ); 1233 } // if 1234 1235 if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) { 1122 1236 // otype is internally converted to dtype + otype parameters 1123 static const TypeDecl::Kind kindMap[] = { TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype,TypeDecl::Dimension };1124 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );1237 static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension }; 1238 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." ); 1125 1239 assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." ); 1126 TypeDecl * ret = new TypeDecl( *name, Type::StorageClasses(), nullptr, kindMap[ variable.tyClass ], variable.tyClass == TypeDecl::Otype || variable.tyClass == TypeDecl::DStype, variable.initializer ? variable.initializer->buildType() : nullptr ); 1127 buildList( variable.assertions, ret->get_assertions() ); 1240 ast::TypeDecl * ret = new ast::TypeDecl( location, 1241 *name, 1242 ast::Storage::Classes(), 1243 (ast::Type *)nullptr, 1244 kindMap[ variable.tyClass ], 1245 variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype, 1246 variable.initializer ? variable.initializer->buildType() : nullptr 1247 ); 1248 buildList( variable.assertions, ret->assertions ); 1128 1249 return ret; 1129 1250 } // if … … 1147 1268 } // if 1148 1269 bool isDelete = initializer && initializer->get_isDelete(); 1149 Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension ); 1270 ast::Decl * decl = buildDecl( 1271 type, 1272 name ? *name : string( "" ), 1273 storageClasses, 1274 maybeBuild( bitfieldWidth ), 1275 funcSpecs, 1276 linkage, 1277 asmName, 1278 isDelete ? nullptr : maybeBuild( initializer ), 1279 copy( attributes ) 1280 )->set_extension( extension ); 1150 1281 if ( isDelete ) { 1151 DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );1282 auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl ); 1152 1283 dwt->isDeleted = true; 1153 1284 } … … 1156 1287 1157 1288 if ( assert.condition ) { 1158 return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) ); 1289 auto cond = maybeBuild( assert.condition ); 1290 auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) ); 1291 return new ast::StaticAssertDecl( location, cond, msg ); 1159 1292 } 1160 1293 … … 1167 1300 } // if 1168 1301 if ( enumInLine ) { 1169 return new InlineMemberDecl( *name, storageClasses, linkage, nullptr ); 1302 return new ast::InlineMemberDecl( location, 1303 *name, (ast::Type*)nullptr, storageClasses, linkage ); 1170 1304 } // if 1171 1305 assertf( name, "ObjectDecl must a have name\n" ); 1172 return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension ); 1173 } 1174 1175 Type * DeclarationNode::buildType() const { 1306 auto ret = new ast::ObjectDecl( location, 1307 *name, 1308 (ast::Type*)nullptr, 1309 maybeBuild( initializer ), 1310 storageClasses, 1311 linkage, 1312 maybeBuild( bitfieldWidth ) 1313 ); 1314 ret->asmName = asmName; 1315 ret->extension = extension; 1316 return ret; 1317 } 1318 1319 ast::Type * DeclarationNode::buildType() const { 1176 1320 assert( type ); 1177 1321 1178 if ( attr.expr ) {1179 return new AttrType( buildQualifiers( type ), *name, attr.expr->build(), attributes );1180 } else if ( attr.type ) {1181 return new AttrType( buildQualifiers( type ), *name, attr.type->buildType(), attributes );1182 } // if1183 1184 1322 switch ( type->kind ) { 1185 case TypeData::Enum: 1186 case TypeData::Aggregate: { 1187 ReferenceToType * ret = buildComAggInst( type, attributes, linkage ); 1188 buildList( type->aggregate.actuals, ret->get_parameters() ); 1189 return ret; 1190 } 1191 case TypeData::Symbolic: { 1192 TypeInstType * ret = new TypeInstType( buildQualifiers( type ), *type->symbolic.name, false, attributes ); 1193 buildList( type->symbolic.actuals, ret->get_parameters() ); 1194 return ret; 1195 } 1196 default: 1197 Type * simpletypes = typebuild( type ); 1198 simpletypes->get_attributes() = attributes; // copy because member is const 1323 case TypeData::Enum: 1324 case TypeData::Aggregate: { 1325 ast::BaseInstType * ret = 1326 buildComAggInst( type, copy( attributes ), linkage ); 1327 buildList( type->aggregate.actuals, ret->params ); 1328 return ret; 1329 } 1330 case TypeData::Symbolic: { 1331 ast::TypeInstType * ret = new ast::TypeInstType( 1332 *type->symbolic.name, 1333 // This is just a default, the true value is not known yet. 1334 ast::TypeDecl::Dtype, 1335 buildQualifiers( type ), 1336 copy( attributes ) ); 1337 buildList( type->symbolic.actuals, ret->params ); 1338 return ret; 1339 } 1340 default: 1341 ast::Type * simpletypes = typebuild( type ); 1342 // copy because member is const 1343 simpletypes->attributes = attributes; 1199 1344 return simpletypes; 1200 1345 } // switch -
src/Parser/ExpressionNode.cc
r34b4268 r24d6572 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 13:17:07 2015 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 7 09:18:56 2021 13 // Update Count : 1077 14 // 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 11:07:00 2023 13 // Update Count : 1083 14 // 15 16 #include "ExpressionNode.h" 15 17 16 18 #include <cassert> // for assert … … 21 23 #include <string> // for string, operator+, operator== 22 24 25 #include "AST/Expr.hpp" // for NameExpr 26 #include "AST/Type.hpp" // for BaseType, SueInstType 23 27 #include "Common/SemanticError.h" // for SemanticError 24 28 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 25 #include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType 26 #include "SynTree/Constant.h" // for Constant 27 #include "SynTree/Declaration.h" // for EnumDecl, StructDecl, UnionDecl 28 #include "SynTree/Expression.h" // for Expression, ConstantExpr, NameExpr 29 #include "SynTree/Statement.h" // for CompoundStmt, Statement 30 #include "SynTree/Type.h" // for BasicType, Type, Type::Qualifiers 29 #include "DeclarationNode.h" // for DeclarationNode 30 #include "InitializerNode.h" // for InitializerNode 31 31 #include "parserutility.h" // for notZeroExpr 32 33 class Initializer;34 32 35 33 using namespace std; … … 48 46 // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their 49 47 // type. 50 51 extern const Type::Qualifiers noQualifiers; // no qualifiers on constants52 48 53 49 // static inline bool checkH( char c ) { return c == 'h' || c == 'H'; } … … 71 67 size_t end = str.length() - 1; 72 68 if ( posn == end ) { type = 3; return; } // no length after 'l' => long 73 69 74 70 string::size_type next = posn + 1; // advance to length 75 71 if ( str[next] == '3' ) { // 32 … … 122 118 if ( str[i] == '1' ) v |= 1; 123 119 i += 1; 124 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;120 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break; 125 121 v <<= 1; 126 122 } // for 127 123 } // scanbin 128 124 129 Expression * build_constantInteger( string & str ) { 130 static const BasicType::Kind kind[2][6] = { 125 ast::Expr * build_constantInteger( 126 const CodeLocation & location, string & str ) { 127 static const ast::BasicType::Kind kind[2][6] = { 131 128 // short (h) must be before char (hh) because shorter type has the longer suffix 132 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */BasicType::LongLongSignedInt, },133 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */BasicType::LongLongUnsignedInt, },129 { ast::BasicType::ShortSignedInt, ast::BasicType::SignedChar, ast::BasicType::SignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ ast::BasicType::LongLongSignedInt, }, 130 { ast::BasicType::ShortUnsignedInt, ast::BasicType::UnsignedChar, ast::BasicType::UnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ ast::BasicType::LongLongUnsignedInt, }, 134 131 }; 135 132 … … 141 138 string str2( "0x0" ); 142 139 unsigned long long int v, v2 = 0; // converted integral value 143 Expression* ret, * ret2;140 ast::Expr * ret, * ret2; 144 141 145 142 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128 … … 149 146 // special constants 150 147 if ( str == "0" ) { 151 ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ));148 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 ); 152 149 goto CLEANUP; 153 150 } // if 154 151 if ( str == "1" ) { 155 ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ));152 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 ); 156 153 goto CLEANUP; 157 154 } // if 158 159 string::size_type posn;160 155 161 156 // 'u' can appear before or after length suffix … … 166 161 } else { 167 162 // At least one digit in integer constant, so safe to backup while looking for suffix. 168 169 posn = str.find_last_of( "pP" ); // pointer value 170 if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; } 171 172 posn = str.find_last_of( "zZ" ); // size_t 173 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; } 174 175 posn = str.rfind( "hh" ); // char 176 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 177 178 posn = str.rfind( "HH" ); // char 179 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 180 181 posn = str.find_last_of( "hH" ); // short 182 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; } 183 184 posn = str.find_last_of( "nN" ); // int (natural number) 185 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; } 186 187 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; } 188 189 lnthSuffix( str, type, ltype ); // must be after check for "ll" 190 FINI: ; 163 // This declaration and the comma expressions in the conditions mimic 164 // the declare and check pattern allowed in later compiler versions. 165 // (Only some early compilers/C++ standards do not support it.) 166 string::size_type posn; 167 // pointer value 168 if ( posn = str.find_last_of( "pP" ), posn != string::npos ) { 169 ltype = 5; str.erase( posn, 1 ); 170 // size_t 171 } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) { 172 Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); 173 // signed char 174 } else if ( posn = str.rfind( "hh" ), posn != string::npos ) { 175 type = 1; str.erase( posn, 2 ); 176 // signed char 177 } else if ( posn = str.rfind( "HH" ), posn != string::npos ) { 178 type = 1; str.erase( posn, 2 ); 179 // short 180 } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) { 181 type = 0; str.erase( posn, 1 ); 182 // int (natural number) 183 } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) { 184 type = 2; str.erase( posn, 1 ); 185 } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { 186 type = 4; 187 } else { 188 lnthSuffix( str, type, ltype ); 189 } // if 191 190 } // if 192 191 … … 196 195 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str ); 197 196 #endif // ! __SIZEOF_INT128__ 198 197 199 198 if ( str[0] == '0' ) { // radix character ? 200 199 dec = false; … … 206 205 unsigned int len = str.length(); 207 206 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str ); 208 if ( len <= (2 + 16) ) goto FHEX1; // hex digits < 2^64 209 str2 = "0x" + str.substr( len - 16 ); 210 sscanf( (char *)str2.c_str(), "%llx", &v2 ); 211 str = str.substr( 0, len - 16 ); 212 FHEX1: ; 207 // hex digits < 2^64 208 if ( len > (2 + 16) ) { 209 str2 = "0x" + str.substr( len - 16 ); 210 sscanf( (char *)str2.c_str(), "%llx", &v2 ); 211 str = str.substr( 0, len - 16 ); 212 } // if 213 213 sscanf( (char *)str.c_str(), "%llx", &v ); 214 214 #endif // __SIZEOF_INT128__ … … 301 301 302 302 // Constant type is correct for overload resolving. 303 ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) ); 303 ret = new ast::ConstantExpr( location, 304 new ast::BasicType( kind[Unsigned][type] ), str, v ); 304 305 if ( Unsigned && type < 2 ) { // hh or h, less than int ? 305 306 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values. 306 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 307 ret = new ast::CastExpr( location, 308 ret, 309 new ast::BasicType( kind[Unsigned][type] ), 310 ast::ExplicitCast ); 307 311 } else if ( ltype != -1 ) { // explicit length ? 308 312 if ( ltype == 6 ) { // int128, (int128)constant 309 // ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 310 ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) ); 311 ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ), 312 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) ); 313 ret2 = new ast::ConstantExpr( location, 314 new ast::BasicType( ast::BasicType::LongLongSignedInt ), 315 str2, 316 v2 ); 317 ret = build_compoundLiteral( location, 318 DeclarationNode::newBasicType( 319 DeclarationNode::Int128 320 )->addType( 321 DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ), 322 new InitializerNode( 323 (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) 324 ); 313 325 } else { // explicit length, (length_type)constant 314 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false ); 326 ret = new ast::CastExpr( location, 327 ret, 328 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ), 329 ast::ExplicitCast ); 315 330 if ( ltype == 5 ) { // pointer, intptr( (uintptr_t)constant ) 316 ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) ); 331 ret = build_func( location, 332 new ExpressionNode( 333 build_varref( location, new string( "intptr" ) ) ), 334 new ExpressionNode( ret ) ); 317 335 } // if 318 336 } // if … … 358 376 359 377 360 Expression * build_constantFloat( string & str ) { 361 static const BasicType::Kind kind[2][12] = { 362 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x }, 363 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex }, 378 ast::Expr * build_constantFloat( 379 const CodeLocation & location, string & str ) { 380 static const ast::BasicType::Kind kind[2][12] = { 381 { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x }, 382 { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex }, 364 383 }; 365 384 … … 398 417 399 418 assert( 0 <= type && type < 12 ); 400 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) ); 401 if ( explnth ) { // explicit length ? 402 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false ); 419 ast::Expr * ret = new ast::ConstantExpr( location, 420 new ast::BasicType( kind[complx][type] ), 421 str, 422 v ); 423 // explicit length ? 424 if ( explnth ) { 425 ret = new ast::CastExpr( location, 426 ret, 427 new ast::BasicType( kind[complx][type] ), 428 ast::ExplicitCast ); 403 429 } // if 404 430 … … 415 441 } // sepString 416 442 417 Expression * build_constantChar(string & str ) {443 ast::Expr * build_constantChar( const CodeLocation & location, string & str ) { 418 444 string units; // units 419 445 sepString( str, units, '\'' ); // separate constant from units 420 446 421 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) ); 447 ast::Expr * ret = new ast::ConstantExpr( location, 448 new ast::BasicType( ast::BasicType::Char ), 449 str, 450 (unsigned long long int)(unsigned char)str[1] ); 422 451 if ( units.length() != 0 ) { 423 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 452 ret = new ast::UntypedExpr( location, 453 new ast::NameExpr( location, units ), 454 { ret } ); 424 455 } // if 425 456 … … 428 459 } // build_constantChar 429 460 430 Expression * build_constantStr( string & str ) { 461 ast::Expr * build_constantStr( 462 const CodeLocation & location, 463 string & str ) { 431 464 assert( str.length() > 0 ); 432 465 string units; // units 433 466 sepString( str, units, '"' ); // separate constant from units 434 467 435 Type * strtype;468 ast::Type * strtype; 436 469 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1 437 case 'u':470 case 'u': 438 471 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char 439 472 // lookup type of associated typedef 440 strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );473 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype ); 441 474 break; 442 case 'U':443 strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );475 case 'U': 476 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype ); 444 477 break; 445 case 'L':446 strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );478 case 'L': 479 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype ); 447 480 break; 448 Default: // char default string type449 default:450 strtype = new BasicType( Type::Qualifiers( ),BasicType::Char );481 Default: // char default string type 482 default: 483 strtype = new ast::BasicType( ast::BasicType::Char ); 451 484 } // switch 452 ArrayType * at = new ArrayType( noQualifiers, strtype, 453 new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"' 454 false, false ); 455 Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) ); 485 ast::ArrayType * at = new ast::ArrayType( 486 strtype, 487 // Length is adjusted: +1 for '\0' and -2 for '"' 488 ast::ConstantExpr::from_ulong( location, str.size() + 1 - 2 ), 489 ast::FixedLen, 490 ast::DynamicDim ); 491 ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt ); 456 492 if ( units.length() != 0 ) { 457 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 493 ret = new ast::UntypedExpr( location, 494 new ast::NameExpr( location, units ), 495 { ret } ); 458 496 } // if 459 497 … … 462 500 } // build_constantStr 463 501 464 Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) { 502 ast::Expr * build_field_name_FLOATING_FRACTIONconstant( 503 const CodeLocation & location, const string & str ) { 465 504 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str ); 466 Expression * ret = build_constantInteger( *new string( str.substr(1) ) ); 505 ast::Expr * ret = build_constantInteger( location, 506 *new string( str.substr(1) ) ); 467 507 delete &str; 468 508 return ret; 469 509 } // build_field_name_FLOATING_FRACTIONconstant 470 510 471 Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) { 511 ast::Expr * build_field_name_FLOATING_DECIMALconstant( 512 const CodeLocation & location, const string & str ) { 472 513 if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str ); 473 Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) ); 514 ast::Expr * ret = build_constantInteger( 515 location, *new string( str.substr( 0, str.size()-1 ) ) ); 474 516 delete &str; 475 517 return ret; 476 518 } // build_field_name_FLOATING_DECIMALconstant 477 519 478 Expression * build_field_name_FLOATINGconstant( const string & str ) { 520 ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location, 521 const string & str ) { 479 522 // str is of the form A.B -> separate at the . and return member expression 480 523 int a, b; … … 482 525 stringstream ss( str ); 483 526 ss >> a >> dot >> b; 484 UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) ); 527 auto ret = new ast::UntypedMemberExpr( location, 528 ast::ConstantExpr::from_int( location, b ), 529 ast::ConstantExpr::from_int( location, a ) 530 ); 485 531 delete &str; 486 532 return ret; 487 533 } // build_field_name_FLOATINGconstant 488 534 489 Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) { 490 if ( fracts ) { 491 if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) { 492 memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) ); 493 return memberExpr; 494 } else { 495 return new UntypedMemberExpr( fracts, fieldName ); 496 } // if 497 } // if 498 return fieldName; 535 ast::Expr * make_field_name_fraction_constants( const CodeLocation & location, 536 ast::Expr * fieldName, 537 ast::Expr * fracts ) { 538 if ( nullptr == fracts ) { 539 return fieldName; 540 } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) { 541 memberExpr->member = make_field_name_fraction_constants( location, 542 fieldName, 543 ast::mutate( memberExpr->aggregate.get() ) ); 544 return memberExpr; 545 } else { 546 return new ast::UntypedMemberExpr( location, fracts, fieldName ); 547 } // if 499 548 } // make_field_name_fraction_constants 500 549 501 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) { 502 return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) ); 550 ast::Expr * build_field_name_fraction_constants( const CodeLocation & location, 551 ast::Expr * fieldName, 552 ExpressionNode * fracts ) { 553 return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) ); 503 554 } // build_field_name_fraction_constants 504 555 505 NameExpr * build_varref( const string * name ) { 506 NameExpr * expr = new NameExpr( *name ); 556 ast::NameExpr * build_varref( const CodeLocation & location, 557 const string * name ) { 558 ast::NameExpr * expr = new ast::NameExpr( location, *name ); 507 559 delete name; 508 560 return expr; 509 561 } // build_varref 510 562 511 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) { 512 Declaration * newDecl = maybeBuild< Declaration >(decl_node); 513 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { 514 const Type * t = newDeclWithType->get_type(); 515 if ( t ) { 516 if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) { 517 newDecl= new EnumDecl( typeInst->name ); 563 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location, 564 const DeclarationNode * decl_node, 565 const ast::NameExpr * name ) { 566 ast::Decl * newDecl = maybeBuild( decl_node ); 567 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) { 568 if ( const ast::Type * t = newDeclWithType->get_type() ) { 569 if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) { 570 newDecl = new ast::EnumDecl( location, typeInst->name ); 518 571 } 519 572 } 520 573 } 521 return new QualifiedNameExpr(newDecl, name->name );574 return new ast::QualifiedNameExpr( location, newDecl, name->name ); 522 575 } 523 576 524 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) { 525 EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node ); 526 return new QualifiedNameExpr( newDecl, name->name ); 577 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location, 578 const ast::EnumDecl * decl, 579 const ast::NameExpr * name ) { 580 return new ast::QualifiedNameExpr( location, decl, name->name ); 527 581 } 528 582 529 DimensionExpr * build_dimensionref( const string * name ) { 530 DimensionExpr * expr = new DimensionExpr( *name ); 583 ast::DimensionExpr * build_dimensionref( const CodeLocation & location, 584 const string * name ) { 585 ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name ); 531 586 delete name; 532 587 return expr; … … 544 599 }; // OperName 545 600 546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind ) { 547 Type * targetType = maybeMoveBuildType( decl_node ); 548 if ( dynamic_cast< VoidType * >( targetType ) ) { 601 ast::Expr * build_cast( const CodeLocation & location, 602 DeclarationNode * decl_node, 603 ExpressionNode * expr_node, 604 ast::CastExpr::CastKind kind ) { 605 ast::Type * targetType = maybeMoveBuildType( decl_node ); 606 if ( dynamic_cast<ast::VoidType *>( targetType ) ) { 549 607 delete targetType; 550 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false, kind ); 608 return new ast::CastExpr( location, 609 maybeMoveBuild( expr_node ), 610 ast::ExplicitCast, kind ); 551 611 } else { 552 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false, kind ); 612 return new ast::CastExpr( location, 613 maybeMoveBuild( expr_node ), 614 targetType, 615 ast::ExplicitCast, kind ); 553 616 } // if 554 617 } // build_cast 555 618 556 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) { 557 return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target ); 619 ast::Expr * build_keyword_cast( const CodeLocation & location, 620 ast::AggregateDecl::Aggregate target, 621 ExpressionNode * expr_node ) { 622 return new ast::KeywordCastExpr( location, 623 maybeMoveBuild( expr_node ), 624 target 625 ); 558 626 } 559 627 560 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { 561 return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) ); 628 ast::Expr * build_virtual_cast( const CodeLocation & location, 629 DeclarationNode * decl_node, 630 ExpressionNode * expr_node ) { 631 return new ast::VirtualCastExpr( location, 632 maybeMoveBuild( expr_node ), 633 maybeMoveBuildType( decl_node ) 634 ); 562 635 } // build_virtual_cast 563 636 564 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) { 565 return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) ); 637 ast::Expr * build_fieldSel( const CodeLocation & location, 638 ExpressionNode * expr_node, 639 ast::Expr * member ) { 640 return new ast::UntypedMemberExpr( location, 641 member, 642 maybeMoveBuild( expr_node ) 643 ); 566 644 } // build_fieldSel 567 645 568 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) { 569 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 646 ast::Expr * build_pfieldSel( const CodeLocation & location, 647 ExpressionNode * expr_node, 648 ast::Expr * member ) { 649 auto deref = new ast::UntypedExpr( location, 650 new ast::NameExpr( location, "*?" ) 651 ); 570 652 deref->location = expr_node->location; 571 deref-> get_args().push_back( maybeMoveBuild< Expression >(expr_node) );572 UntypedMemberExpr * ret = new UntypedMemberExpr(member, deref );653 deref->args.push_back( maybeMoveBuild( expr_node ) ); 654 auto ret = new ast::UntypedMemberExpr( location, member, deref ); 573 655 return ret; 574 656 } // build_pfieldSel 575 657 576 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) { 577 Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() ); 658 ast::Expr * build_offsetOf( const CodeLocation & location, 659 DeclarationNode * decl_node, 660 ast::NameExpr * member ) { 661 ast::Expr * ret = new ast::UntypedOffsetofExpr( location, 662 maybeMoveBuildType( decl_node ), 663 member->name 664 ); 665 ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt ); 578 666 delete member; 579 667 return ret; 580 668 } // build_offsetOf 581 669 582 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) { 583 return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind ); 670 ast::Expr * build_and_or( const CodeLocation & location, 671 ExpressionNode * expr_node1, 672 ExpressionNode * expr_node2, 673 ast::LogicalFlag flag ) { 674 return new ast::LogicalExpr( location, 675 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 676 notZeroExpr( maybeMoveBuild( expr_node2 ) ), 677 flag 678 ); 584 679 } // build_and_or 585 680 586 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) { 587 list< Expression * > args; 588 args.push_back( maybeMoveBuild< Expression >(expr_node) ); 589 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 681 ast::Expr * build_unary_val( const CodeLocation & location, 682 OperKinds op, 683 ExpressionNode * expr_node ) { 684 std::vector<ast::ptr<ast::Expr>> args; 685 args.push_back( maybeMoveBuild( expr_node ) ); 686 return new ast::UntypedExpr( location, 687 new ast::NameExpr( location, OperName[ (int)op ] ), 688 std::move( args ) 689 ); 590 690 } // build_unary_val 591 691 592 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { 593 list< Expression * > args;594 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.595 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );596 } // build_unary_ptr 597 598 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 599 list< Expression * > args;600 args.push_back( maybeMoveBuild< Expression >(expr_node1) );601 args.push_back( maybeMoveBuild< Expression >(expr_node2) );602 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args);692 ast::Expr * build_binary_val( const CodeLocation & location, 693 OperKinds op, 694 ExpressionNode * expr_node1, 695 ExpressionNode * expr_node2 ) { 696 std::vector<ast::ptr<ast::Expr>> args; 697 args.push_back( maybeMoveBuild( expr_node1 ) ); 698 args.push_back( maybeMoveBuild( expr_node2 ) ); 699 return new ast::UntypedExpr( location, 700 new ast::NameExpr( location, OperName[ (int)op ] ), 701 std::move( args ) 702 ); 603 703 } // build_binary_val 604 704 605 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 606 list< Expression * > args;607 args.push_back( maybeMoveBuild< Expression >(expr_node1) );608 args.push_back( maybeMoveBuild< Expression >(expr_node2) );609 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );610 } // build_binary_ptr 611 612 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) { 613 return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3));705 ast::Expr * build_cond( const CodeLocation & location, 706 ExpressionNode * expr_node1, 707 ExpressionNode * expr_node2, 708 ExpressionNode * expr_node3 ) { 709 return new ast::ConditionalExpr( location, 710 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 711 maybeMoveBuild( expr_node2 ), 712 maybeMoveBuild( expr_node3 ) 713 ); 614 714 } // build_cond 615 715 616 Expression * build_tuple( ExpressionNode * expr_node ) { 617 list< Expression * > exprs; 716 ast::Expr * build_tuple( const CodeLocation & location, 717 ExpressionNode * expr_node ) { 718 std::vector<ast::ptr<ast::Expr>> exprs; 618 719 buildMoveList( expr_node, exprs ); 619 return new UntypedTupleExpr( exprs );;720 return new ast::UntypedTupleExpr( location, std::move( exprs ) ); 620 721 } // build_tuple 621 722 622 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) { 623 list< Expression * > args; 723 ast::Expr * build_func( const CodeLocation & location, 724 ExpressionNode * function, 725 ExpressionNode * expr_node ) { 726 std::vector<ast::ptr<ast::Expr>> args; 624 727 buildMoveList( expr_node, args ); 625 return new UntypedExpr( maybeMoveBuild< Expression >(function), args ); 728 return new ast::UntypedExpr( location, 729 maybeMoveBuild( function ), 730 std::move( args ) 731 ); 626 732 } // build_func 627 733 628 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) { 629 Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type 630 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type 631 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) ); 734 ast::Expr * build_compoundLiteral( const CodeLocation & location, 735 DeclarationNode * decl_node, 736 InitializerNode * kids ) { 737 // compound literal type 738 ast::Decl * newDecl = maybeBuild( decl_node ); 739 // non-sue compound-literal type 740 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) { 741 return new ast::CompoundLiteralExpr( location, 742 newDeclWithType->get_type(), 743 maybeMoveBuild( kids ) ); 632 744 // these types do not have associated type information 633 } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { 634 if ( newDeclStructDecl->has_body() ) { 635 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) ); 745 } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) { 746 if ( newDeclStructDecl->body ) { 747 return new ast::CompoundLiteralExpr( location, 748 new ast::StructInstType( newDeclStructDecl ), 749 maybeMoveBuild( kids ) ); 636 750 } else { 637 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 638 } // if 639 } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { 640 if ( newDeclUnionDecl->has_body() ) { 641 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) ); 751 return new ast::CompoundLiteralExpr( location, 752 new ast::StructInstType( newDeclStructDecl->name ), 753 maybeMoveBuild( kids ) ); 754 } // if 755 } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl ) ) { 756 if ( newDeclUnionDecl->body ) { 757 return new ast::CompoundLiteralExpr( location, 758 new ast::UnionInstType( newDeclUnionDecl ), 759 maybeMoveBuild( kids ) ); 642 760 } else { 643 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 644 } // if 645 } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { 646 if ( newDeclEnumDecl->has_body() ) { 647 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) ); 761 return new ast::CompoundLiteralExpr( location, 762 new ast::UnionInstType( newDeclUnionDecl->name ), 763 maybeMoveBuild( kids ) ); 764 } // if 765 } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl ) ) { 766 if ( newDeclEnumDecl->body ) { 767 return new ast::CompoundLiteralExpr( location, 768 new ast::EnumInstType( newDeclEnumDecl ), 769 maybeMoveBuild( kids ) ); 648 770 } else { 649 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 771 return new ast::CompoundLiteralExpr( location, 772 new ast::EnumInstType( newDeclEnumDecl->name ), 773 maybeMoveBuild( kids ) ); 650 774 } // if 651 775 } else { … … 656 780 // Local Variables: // 657 781 // tab-width: 4 // 658 // mode: c++ //659 // compile-command: "make install" //660 782 // End: // -
src/Parser/InitializerNode.cc
r34b4268 r24d6572 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:20:24 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 28 23:27:20 201713 // Update Count : 2 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 11:18:00 2023 13 // Update Count : 27 14 14 // 15 16 #include "InitializerNode.h" 15 17 16 18 #include <iostream> // for operator<<, ostream, basic_ostream … … 18 20 #include <string> // for operator<<, string 19 21 22 #include "AST/Expr.hpp" // for Expr 23 #include "AST/Init.hpp" // for Designator, Init, ListInit, Sing... 24 #include "Common/SemanticError.h" // for SemanticError 25 #include "Common/utility.h" // for maybeBuild 26 #include "ExpressionNode.h" // for ExpressionNode 27 #include "DeclarationNode.h" // for buildList 28 20 29 using namespace std; 21 30 22 #include "Common/SemanticError.h" // for SemanticError 23 #include "Common/utility.h" // for maybeBuild 24 #include "ParseNode.h" // for InitializerNode, ExpressionNode 25 #include "SynTree/Expression.h" // for Expression 26 #include "SynTree/Initializer.h" // for Initializer, ListInit, SingleInit 31 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) { 32 return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct; 33 } 27 34 28 35 InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des ) … … 33 40 if ( kids ) 34 41 set_last( nullptr ); 35 } // InitializerNode::InitializerNode 42 } // InitializerNode::InitializerNode 36 43 37 44 InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des ) … … 85 92 } // InitializerNode::printOneLine 86 93 87 Initializer* InitializerNode::build() const {94 ast::Init * InitializerNode::build() const { 88 95 assertf( ! isDelete, "Should not build delete stmt InitializerNode" ); 89 96 if ( aggregate ) { 90 97 // steal designators from children 91 std:: list< Designation *> designlist;98 std::vector<ast::ptr<ast::Designation>> designlist; 92 99 InitializerNode * child = next_init(); 93 for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) { 94 std::list< Expression * > desList; 95 buildList< Expression, ExpressionNode >( child->designator, desList ); 96 designlist.push_back( new Designation( desList ) ); 100 for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) { 101 std::deque<ast::ptr<ast::Expr>> desList; 102 buildList( child->designator, desList ); 103 designlist.push_back( 104 new ast::Designation( location, std::move( desList ) ) ); 97 105 } // for 98 std::list< Initializer * > initlist; 99 buildList< Initializer, InitializerNode >( next_init(), initlist ); 100 return new ListInit( initlist, designlist, maybeConstructed ); 101 } else { 102 if ( get_expression() ) { 103 assertf( get_expression()->expr, "The expression of initializer must have value" ); 104 return new SingleInit( maybeBuild< Expression >( get_expression() ), maybeConstructed ); 105 } // if 106 std::vector<ast::ptr<ast::Init>> initlist; 107 buildList( next_init(), initlist ); 108 return new ast::ListInit( location, 109 std::move( initlist ), 110 std::move( designlist ), 111 toConstructFlag( maybeConstructed ) 112 ); 113 } else if ( get_expression() ) { 114 assertf( get_expression()->expr, "The expression of initializer must have value" ); 115 return new ast::SingleInit( location, 116 maybeBuild( get_expression() ), 117 toConstructFlag( maybeConstructed ) 118 ); 106 119 } // if 107 120 return nullptr; -
src/Parser/ParseNode.h
r34b4268 r24d6572 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:28:16 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Nov 2 21:27:07 202213 // Update Count : 9 3911 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 3 17:55:00 2023 13 // Update Count : 942 14 14 // 15 15 … … 24 24 #include <string> // for string 25 25 26 #include "AST/Expr.hpp" // for Expr, NameExpr LogicalFlag 27 #include "AST/Fwd.hpp" // for ptr, Decl, DeclWithType, 28 #include "AST/Stmt.hpp" // for Stmt 26 29 #include "Common/CodeLocation.h" // for CodeLocation 27 30 #include "Common/SemanticError.h" // for SemanticError 28 31 #include "Common/UniqueName.h" // for UniqueName 29 #include "Common/utility.h" // for maybeClone, maybeBuild 30 #include "SynTree/LinkageSpec.h" // for Spec 31 #include "SynTree/Declaration.h" // for Aggregate 32 #include "SynTree/Expression.h" // for Expression, ConstantExpr (ptr only) 33 #include "SynTree/Label.h" // for Label 34 #include "SynTree/Statement.h" // for Statement, BranchStmt, BranchStmt:... 35 #include "SynTree/Type.h" // for Type, Type::FuncSpecifiers, Type::... 32 #include "Common/utility.h" // for maybeClone 33 #include "Parser/parserutility.h" // for maybeBuild, maybeCopy 36 34 37 35 class Attribute; … … 40 38 class DeclarationWithType; 41 39 class Initializer; 40 class InitializerNode; 42 41 class ExpressionNode; 43 42 struct StatementNode; … … 82 81 }; // ParseNode 83 82 84 //##############################################################################85 86 class InitializerNode : public ParseNode {87 public:88 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );89 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );90 InitializerNode( bool isDelete );91 ~InitializerNode();92 virtual InitializerNode * clone() const { assert( false ); return nullptr; }93 94 ExpressionNode * get_expression() const { return expr; }95 96 InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; }97 ExpressionNode * get_designators() const { return designator; }98 99 InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }100 bool get_maybeConstructed() const { return maybeConstructed; }101 102 bool get_isDelete() const { return isDelete; }103 104 InitializerNode * next_init() const { return kids; }105 106 void print( std::ostream & os, int indent = 0 ) const;107 void printOneLine( std::ostream & ) const;108 109 virtual Initializer * build() const;110 private:111 ExpressionNode * expr;112 bool aggregate;113 ExpressionNode * designator; // may be list114 InitializerNode * kids;115 bool maybeConstructed;116 bool isDelete;117 }; // InitializerNode118 119 //##############################################################################120 121 class ExpressionNode final : public ParseNode {122 public:123 ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {}124 virtual ~ExpressionNode() {}125 virtual ExpressionNode * clone() const override { return expr ? static_cast<ExpressionNode*>((new ExpressionNode( expr->clone() ))->set_next( maybeClone( get_next() ) )) : nullptr; }126 127 bool get_extension() const { return extension; }128 ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }129 130 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {131 os << expr.get();132 }133 void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}134 135 template<typename T>136 bool isExpressionType() const { return nullptr != dynamic_cast<T>(expr.get()); }137 138 Expression * build() const { return const_cast<ExpressionNode *>(this)->expr.release(); }139 140 std::unique_ptr<Expression> expr; // public because of lifetime implications141 private:142 bool extension = false;143 }; // ExpressionNode144 145 template< typename T >146 struct maybeBuild_t< Expression, T > {147 static inline Expression * doit( const T * orig ) {148 if ( orig ) {149 Expression * p = orig->build();150 p->set_extension( orig->get_extension() );151 p->location = orig->location;152 return p;153 } else {154 return nullptr;155 } // if156 }157 };158 159 83 // Must harmonize with OperName. 160 84 enum class OperKinds { … … 172 96 173 97 struct LabelNode { 174 std:: list< Label> labels;98 std::vector<ast::Label> labels; 175 99 }; 176 100 177 Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string178 Expression * build_constantFloat( std::string & str );179 Expression * build_constantChar( std::string & str );180 Expression * build_constantStr( std::string & str );181 Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );182 Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );183 Expression * build_field_name_FLOATINGconstant( const std::string & str );184 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );185 186 NameExpr * build_varref( const std::string * name );187 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );188 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );189 DimensionExpr * build_dimensionref( const std::string * name );190 191 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind = CastExpr::Default );192 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node );193 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );194 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );195 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );196 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member );197 Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 );198 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind );199 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node );200 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node );201 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );202 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );203 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );204 Expression * build_tuple( ExpressionNode * expr_node = nullptr );205 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node );206 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids );207 208 //##############################################################################209 210 struct TypeData;211 212 struct DeclarationNode : public ParseNode {213 // These enumerations must harmonize with their names in DeclarationNode.cc.214 enum BasicType { Void, Bool, Char, Int, Int128,215 Float, Double, LongDouble, uuFloat80, uuFloat128,216 uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x, NoBasicType };217 static const char * basicTypeNames[];218 enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message219 static const char * complexTypeNames[];220 enum Signedness { Signed, Unsigned, NoSignedness };221 static const char * signednessNames[];222 enum Length { Short, Long, LongLong, NoLength };223 static const char * lengthNames[];224 enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };225 static const char * builtinTypeNames[];226 227 static DeclarationNode * newStorageClass( Type::StorageClasses );228 static DeclarationNode * newFuncSpecifier( Type::FuncSpecifiers );229 static DeclarationNode * newTypeQualifier( Type::Qualifiers );230 static DeclarationNode * newBasicType( BasicType );231 static DeclarationNode * newComplexType( ComplexType );232 static DeclarationNode * newSignedNess( Signedness );233 static DeclarationNode * newLength( Length );234 static DeclarationNode * newBuiltinType( BuiltinType );235 static DeclarationNode * newForall( DeclarationNode * );236 static DeclarationNode * newFromTypedef( const std::string * );237 static DeclarationNode * newFromGlobalScope();238 static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );239 static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );240 static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );241 static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );242 static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );243 static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );244 static DeclarationNode * newEnumInLine( const std::string name );245 static DeclarationNode * newName( const std::string * );246 static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );247 static DeclarationNode * newTypeParam( TypeDecl::Kind, const std::string * );248 static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );249 static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );250 static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );251 static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );252 static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );253 static DeclarationNode * newVarArray( DeclarationNode * qualifiers );254 static DeclarationNode * newBitfield( ExpressionNode * size );255 static DeclarationNode * newTuple( DeclarationNode * members );256 static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );257 static DeclarationNode * newVtableType( DeclarationNode * expr );258 static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes259 static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement260 static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement261 static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );262 263 DeclarationNode();264 ~DeclarationNode();265 DeclarationNode * clone() const override;266 267 DeclarationNode * addQualifiers( DeclarationNode * );268 void checkQualifiers( const TypeData *, const TypeData * );269 void checkSpecifiers( DeclarationNode * );270 DeclarationNode * copySpecifiers( DeclarationNode * );271 DeclarationNode * addType( DeclarationNode * );272 DeclarationNode * addTypedef();273 DeclarationNode * addEnumBase( DeclarationNode * );274 DeclarationNode * addAssertions( DeclarationNode * );275 DeclarationNode * addName( std::string * );276 DeclarationNode * addAsmName( DeclarationNode * );277 DeclarationNode * addBitfield( ExpressionNode * size );278 DeclarationNode * addVarArgs();279 DeclarationNode * addFunctionBody( StatementNode * body, ExpressionNode * with = nullptr );280 DeclarationNode * addOldDeclList( DeclarationNode * list );281 DeclarationNode * setBase( TypeData * newType );282 DeclarationNode * copyAttribute( DeclarationNode * attr );283 DeclarationNode * addPointer( DeclarationNode * qualifiers );284 DeclarationNode * addArray( DeclarationNode * array );285 DeclarationNode * addNewPointer( DeclarationNode * pointer );286 DeclarationNode * addNewArray( DeclarationNode * array );287 DeclarationNode * addParamList( DeclarationNode * list );288 DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions289 DeclarationNode * addInitializer( InitializerNode * init );290 DeclarationNode * addTypeInitializer( DeclarationNode * init );291 292 DeclarationNode * cloneType( std::string * newName );293 DeclarationNode * cloneBaseType( DeclarationNode * newdecl );294 295 DeclarationNode * appendList( DeclarationNode * node ) {296 return (DeclarationNode *)set_last( node );297 }298 299 virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;300 virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;301 302 Declaration * build() const;303 Type * buildType() const;304 305 LinkageSpec::Spec get_linkage() const { return linkage; }306 DeclarationNode * extractAggregate() const;307 bool has_enumeratorValue() const { return (bool)enumeratorValue; }308 ExpressionNode * consume_enumeratorValue() const { return const_cast<DeclarationNode *>(this)->enumeratorValue.release(); }309 310 bool get_extension() const { return extension; }311 DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }312 313 bool get_inLine() const { return inLine; }314 DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }315 316 DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }317 318 struct Variable_t {319 // const std::string * name;320 TypeDecl::Kind tyClass;321 DeclarationNode * assertions;322 DeclarationNode * initializer;323 };324 Variable_t variable;325 326 struct Attr_t {327 // const std::string * name;328 ExpressionNode * expr;329 DeclarationNode * type;330 };331 Attr_t attr;332 333 struct StaticAssert_t {334 ExpressionNode * condition;335 Expression * message;336 };337 StaticAssert_t assert;338 339 BuiltinType builtin = NoBuiltinType;340 341 TypeData * type = nullptr;342 343 bool inLine = false;344 bool enumInLine = false;345 Type::FuncSpecifiers funcSpecs;346 Type::StorageClasses storageClasses;347 348 ExpressionNode * bitfieldWidth = nullptr;349 std::unique_ptr<ExpressionNode> enumeratorValue;350 bool hasEllipsis = false;351 LinkageSpec::Spec linkage;352 Expression * asmName = nullptr;353 std::list< Attribute * > attributes;354 InitializerNode * initializer = nullptr;355 bool extension = false;356 std::string error;357 StatementNode * asmStmt = nullptr;358 StatementNode * directiveStmt = nullptr;359 360 static UniqueName anonymous;361 }; // DeclarationNode362 363 Type * buildType( TypeData * type );364 365 static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) {366 Type * ret = orig ? orig->buildType() : nullptr;367 delete orig;368 return ret;369 }370 371 //##############################################################################372 373 struct StatementNode final : public ParseNode {374 StatementNode() { stmt = nullptr; }375 StatementNode( Statement * stmt ) : stmt( stmt ) {}376 StatementNode( DeclarationNode * decl );377 virtual ~StatementNode() {}378 379 virtual StatementNode * clone() const final { assert( false ); return nullptr; }380 Statement * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }381 382 virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) {383 stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} );384 delete attr;385 delete name;386 return this;387 }388 389 virtual StatementNode * append_last_case( StatementNode * );390 391 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {392 os << stmt.get() << std::endl;393 }394 395 std::unique_ptr<Statement> stmt;396 }; // StatementNode397 398 Statement * build_expr( ExpressionNode * ctl );399 400 struct CondCtl {401 CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :402 init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}403 404 StatementNode * init;405 ExpressionNode * condition;406 };407 408 struct ForCtrl {409 ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :410 init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}411 ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :412 init( new StatementNode( decl ) ), condition( condition ), change( change ) {}413 414 StatementNode * init;415 ExpressionNode * condition;416 ExpressionNode * change;417 };418 419 Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );420 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );421 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );422 Statement * build_case( ExpressionNode * ctl );423 Statement * build_default();424 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );425 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );426 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );427 Statement * build_branch( BranchStmt::Type kind );428 Statement * build_branch( std::string * identifier, BranchStmt::Type kind );429 Statement * build_computedgoto( ExpressionNode * ctl );430 Statement * build_return( ExpressionNode * ctl );431 Statement * build_throw( ExpressionNode * ctl );432 Statement * build_resume( ExpressionNode * ctl );433 Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );434 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );435 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );436 Statement * build_finally( StatementNode * stmt );437 Statement * build_compound( StatementNode * first );438 StatementNode * maybe_build_compound( StatementNode * first );439 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );440 Statement * build_directive( std::string * directive );441 SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);442 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );443 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );444 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );445 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );446 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );447 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );448 449 //##############################################################################450 451 template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >452 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {453 SemanticErrorException errors;454 std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );455 const NodeType * cur = firstNode;456 457 while ( cur ) {458 try {459 SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) );460 if ( result ) {461 result->location = cur->location;462 * out++ = result;463 } else {464 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );465 } // if466 } catch( SemanticErrorException & e ) {467 errors.append( e );468 } // try469 const ParseNode * temp = (cur->get_next());470 cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr471 if ( ! cur && temp ) { // non-homogeneous nodes ?472 SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );473 } // if474 } // while475 if ( ! errors.isEmpty() ) {476 throw errors;477 } // if478 }479 480 // in DeclarationNode.cc481 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );482 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );483 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );484 485 template< typename SynTreeType, typename NodeType >486 void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {487 buildList( firstNode, outputList );488 delete firstNode;489 }490 491 // in ParseNode.cc492 101 std::ostream & operator<<( std::ostream & out, const ParseNode * node ); 493 102 -
src/Parser/ParserTypes.h
r34b4268 r24d6572 4 4 // The contents of this file are covered under the licence agreement in the 5 5 // file "LICENCE" distributed with Cforall. 6 // 7 // parser.hh -- 8 // 6 // 7 // parser.hh -- 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 22 08:58:10 2001 -
src/Parser/StatementNode.cc
r34b4268 r24d6572 10 10 // Author : Rodolfo G. Esteves 11 11 // Created On : Sat May 16 14:59:41 2015 12 // Last Modified By : Peter A. Buhr13 // Last Modified On : Wed Feb 2 20:29:30 202214 // Update Count : 42 512 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 11 10:16:00 2023 14 // Update Count : 428 15 15 // 16 16 17 #include "StatementNode.h" 18 17 19 #include <cassert> // for assert, strict_dynamic_cast, assertf 18 #include <list> // for list19 20 #include <memory> // for unique_ptr 20 21 #include <string> // for string 21 22 23 #include "AST/Label.hpp" // for Label 24 #include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla... 22 25 #include "Common/SemanticError.h" // for SemanticError 23 26 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 24 #include "ParseNode.h" // for StatementNode, ExpressionNode, bui... 25 #include "SynTree/Expression.h" // for Expression, ConstantExpr 26 #include "SynTree/Label.h" // for Label, noLabels 27 #include "SynTree/Declaration.h" 28 #include "SynTree/Statement.h" // for Statement, BranchStmt, CaseStmt 27 #include "DeclarationNode.h" // for DeclarationNode 28 #include "ExpressionNode.h" // for ExpressionNode 29 29 #include "parserutility.h" // for notZeroExpr 30 30 … … 33 33 using namespace std; 34 34 35 // Some helpers for cases that really want a single node but check for lists. 36 static const ast::Stmt * buildMoveSingle( StatementNode * node ) { 37 std::vector<ast::ptr<ast::Stmt>> list; 38 buildMoveList( node, list ); 39 assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" ); 40 return list.front().release(); 41 } 42 43 static const ast::Stmt * buildMoveOptional( StatementNode * node ) { 44 std::vector<ast::ptr<ast::Stmt>> list; 45 buildMoveList( node, list ); 46 assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" ); 47 return list.empty() ? nullptr : list.front().release(); 48 } 35 49 36 50 StatementNode::StatementNode( DeclarationNode * decl ) { … … 38 52 DeclarationNode * agg = decl->extractAggregate(); 39 53 if ( agg ) { 40 StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) ); 54 StatementNode * nextStmt = new StatementNode( 55 new ast::DeclStmt( decl->location, maybeBuild( decl ) ) ); 41 56 set_next( nextStmt ); 42 57 if ( decl->get_next() ) { … … 51 66 agg = decl; 52 67 } // if 53 stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) ); 68 // Local copy to avoid accessing the pointer after it is moved from. 69 CodeLocation declLocation = agg->location; 70 stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) ); 54 71 } // StatementNode::StatementNode 55 72 56 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 57 StatementNode * prev = this; 73 StatementNode * StatementNode::add_label( 74 const CodeLocation & location, 75 const std::string * name, 76 DeclarationNode * attr ) { 77 stmt->labels.emplace_back( location, 78 *name, 79 attr ? std::move( attr->attributes ) 80 : std::vector<ast::ptr<ast::Attribute>>{} ); 81 delete attr; 82 delete name; 83 return this; 84 } 85 86 ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) { 87 ClauseNode * prev = this; 58 88 // find end of list and maintain previous pointer 59 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {60 StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);61 assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );89 for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) { 90 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr); 91 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) ); 62 92 prev = curr; 63 93 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev); 64 95 // convert from StatementNode list to Statement list 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 66 list< Statement * > stmts; 96 std::vector<ast::ptr<ast::Stmt>> stmts; 67 97 buildMoveList( stmt, stmts ); 68 98 // splice any new Statements to end of current Statements 69 CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get()); 70 caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); 99 auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() ); 100 for ( auto const & newStmt : stmts ) { 101 caseStmt->stmts.emplace_back( newStmt ); 102 } 103 stmts.clear(); 71 104 return this; 72 } // StatementNode::append_last_case 73 74 Statement * build_expr( ExpressionNode * ctl ) { 75 Expression * e = maybeMoveBuild< Expression >( ctl ); 76 77 if ( e ) return new ExprStmt( e ); 78 else return new NullStmt(); 105 } // ClauseNode::append_last_case 106 107 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) { 108 if ( ast::Expr * e = maybeMoveBuild( ctl ) ) { 109 return new ast::ExprStmt( location, e ); 110 } else { 111 return new ast::NullStmt( location ); 112 } 79 113 } // build_expr 80 114 81 Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) { 82 if ( ctl->init != 0 ) { 83 buildMoveList( ctl->init, init ); 115 static ast::Expr * build_if_control( CondCtl * ctl, 116 std::vector<ast::ptr<ast::Stmt>> & inits ) { 117 assert( inits.empty() ); 118 if ( nullptr != ctl->init ) { 119 buildMoveList( ctl->init, inits ); 84 120 } // if 85 121 86 Expression* cond = nullptr;122 ast::Expr * cond = nullptr; 87 123 if ( ctl->condition ) { 88 124 // compare the provided condition against 0 89 cond = notZeroExpr( maybeMoveBuild < Expression >(ctl->condition) );125 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) ); 90 126 } else { 91 for ( Statement * stmt : init) {127 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 92 128 // build the && of all of the declared variables compared against 0 93 DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt);94 DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl);95 Expression * nze = notZeroExpr( new VariableExpr(dwt ) );96 cond = cond ? new LogicalExpr( cond, nze, true) : nze;129 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 130 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 131 ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) ); 132 cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze; 97 133 } 98 134 } … … 101 137 } // build_if_control 102 138 103 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) { 104 list< Statement * > astinit; // maybe empty 105 Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 106 107 Statement * astthen, * astelse = nullptr; 108 list< Statement * > aststmt; 109 buildMoveList< Statement, StatementNode >( then, aststmt ); 110 assert( aststmt.size() == 1 ); 111 astthen = aststmt.front(); 112 113 if ( else_ ) { 114 list< Statement * > aststmt; 115 buildMoveList< Statement, StatementNode >( else_, aststmt ); 116 assert( aststmt.size() == 1 ); 117 astelse = aststmt.front(); 118 } // if 119 120 return new IfStmt( astcond, astthen, astelse, astinit ); 139 ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) { 140 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 141 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 142 143 ast::Stmt const * astthen = buildMoveSingle( then ); 144 ast::Stmt const * astelse = buildMoveOptional( else_ ); 145 146 return new ast::IfStmt( location, astcond, astthen, astelse, 147 std::move( astinit ) 148 ); 121 149 } // build_if 122 150 123 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) { 124 list< Statement * > aststmt; 125 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 126 if ( ! isSwitch ) { // choose statement 127 for ( Statement * stmt : aststmt ) { 128 CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt ); 129 if ( ! caseStmt->stmts.empty() ) { // code after "case" => end of case list 130 CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() ); 131 block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) ); 151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) { 152 std::vector<ast::ptr<ast::CaseClause>> aststmt; 153 buildMoveList( stmt, aststmt ); 154 // If it is not a switch it is a choose statement. 155 if ( ! isSwitch ) { 156 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) { 157 // Code after "case" is the end of case list. 158 if ( !stmt->stmts.empty() ) { 159 auto mutStmt = ast::mutate( stmt.get() ); 160 // I believe the stmts are actually always one block. 161 auto stmts = mutStmt->stmts.front().get_and_mutate(); 162 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts ); 163 block->kids.push_back( new ast::BranchStmt( block->location, 164 ast::BranchStmt::Break, 165 ast::Label( block->location ) ) ); 166 stmt = mutStmt; 132 167 } // if 133 168 } // for 134 169 } // if 135 170 // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements 136 return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt ); 171 return new ast::SwitchStmt( location, 172 maybeMoveBuild( ctl ), std::move( aststmt ) ); 137 173 } // build_switch 138 174 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) { 176 // stmt starts empty and then added to 177 auto expr = maybeMoveBuild( ctl ); 178 return new ast::CaseClause( location, expr, {} ); 141 179 } // build_case 142 180 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 181 ast::CaseClause * build_default( const CodeLocation & location ) { 182 // stmt starts empty and then added to 183 return new ast::CaseClause( location, nullptr, {} ); 145 184 } // build_default 146 185 147 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) { 148 list< Statement * > astinit; // maybe empty 149 Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 150 151 list< Statement * > aststmt; // loop body, compound created if empty 152 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 153 assert( aststmt.size() == 1 ); 154 155 list< Statement * > astelse; // else clause, maybe empty 156 buildMoveList< Statement, StatementNode >( else_, astelse ); 157 158 return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false ); 186 ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) { 187 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 188 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 189 190 return new ast::WhileDoStmt( location, 191 astcond, 192 buildMoveSingle( stmt ), 193 buildMoveOptional( else_ ), 194 std::move( astinit ), 195 ast::While 196 ); 159 197 } // build_while 160 198 161 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 162 list< Statement * > aststmt; // loop body, compound created if empty 163 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 164 assert( aststmt.size() == 1 ); // compound created if empty 165 166 list< Statement * > astelse; // else clause, maybe empty 167 buildMoveList< Statement, StatementNode >( else_, astelse ); 168 199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 169 200 // do-while cannot have declarations in the contitional, so init is always empty 170 return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true ); 201 return new ast::WhileDoStmt( location, 202 notZeroExpr( maybeMoveBuild( ctl ) ), 203 buildMoveSingle( stmt ), 204 buildMoveOptional( else_ ), 205 {}, 206 ast::DoWhile 207 ); 171 208 } // build_do_while 172 209 173 Statement * build_for(ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {174 list< Statement *> astinit; // maybe empty210 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) { 211 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 175 212 buildMoveList( forctl->init, astinit ); 176 213 177 Expression* astcond = nullptr; // maybe empty178 astcond = notZeroExpr( maybeMoveBuild < Expression >(forctl->condition) );179 180 Expression* astincr = nullptr; // maybe empty181 astincr = maybeMoveBuild < Expression >(forctl->change);214 ast::Expr * astcond = nullptr; // maybe empty 215 astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) ); 216 217 ast::Expr * astincr = nullptr; // maybe empty 218 astincr = maybeMoveBuild( forctl->change ); 182 219 delete forctl; 183 220 184 list< Statement * > aststmt; // loop body, compound created if empty 185 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 186 assert( aststmt.size() == 1 ); 187 188 list< Statement * > astelse; // else clause, maybe empty 189 buildMoveList< Statement, StatementNode >( else_, astelse ); 190 191 return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() ); 221 return new ast::ForStmt( location, 222 std::move( astinit ), 223 astcond, 224 astincr, 225 buildMoveSingle( stmt ), 226 buildMoveOptional( else_ ) 227 ); 192 228 } // build_for 193 229 194 Statement * build_branch( BranchStmt::Type kind ) { 195 Statement * ret = new BranchStmt( "", kind ); 196 return ret; 230 ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) { 231 return new ast::BranchStmt( location, 232 kind, 233 ast::Label( location ) 234 ); 197 235 } // build_branch 198 236 199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) { 200 Statement * ret = new BranchStmt( * identifier, kind ); 237 ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) { 238 ast::Stmt * ret = new ast::BranchStmt( location, 239 kind, 240 ast::Label( location, *identifier ) 241 ); 201 242 delete identifier; // allocated by lexer 202 243 return ret; 203 244 } // build_branch 204 245 205 Statement * build_computedgoto( ExpressionNode * ctl ) { 206 return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 246 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) { 247 ast::Expr * expr = maybeMoveBuild( ctl ); 248 return new ast::BranchStmt( expr->location, expr ); 207 249 } // build_computedgoto 208 250 209 Statement * build_return(ExpressionNode * ctl ) {210 list< Expression *> exps;251 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) { 252 std::vector<ast::ptr<ast::Expr>> exps; 211 253 buildMoveList( ctl, exps ); 212 return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr ); 254 return new ast::ReturnStmt( location, 255 exps.size() > 0 ? exps.back().release() : nullptr 256 ); 213 257 } // build_return 214 258 215 Statement * build_throw( ExpressionNode * ctl ) { 216 list< Expression * > exps; 259 static ast::Stmt * build_throw_stmt( 260 const CodeLocation & location, 261 ExpressionNode * ctl, 262 ast::ExceptionKind kind ) { 263 std::vector<ast::ptr<ast::Expr>> exps; 217 264 buildMoveList( ctl, exps ); 218 265 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 219 return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr ); 266 return new ast::ThrowStmt( location, 267 kind, 268 !exps.empty() ? exps.back().release() : nullptr, 269 (ast::Expr *)nullptr 270 ); 271 } 272 273 ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) { 274 return build_throw_stmt( loc, ctl, ast::Terminate ); 220 275 } // build_throw 221 276 222 Statement * build_resume( ExpressionNode * ctl ) { 223 list< Expression * > exps; 224 buildMoveList( ctl, exps ); 225 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 226 return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr ); 277 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) { 278 return build_throw_stmt( loc, ctl, ast::Resume ); 227 279 } // build_resume 228 280 229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {281 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) { 230 282 (void)ctl; 231 283 (void)target; … … 233 285 } // build_resume_at 234 286 235 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) { 236 list< CatchStmt * > aststmt; 237 buildMoveList< CatchStmt, StatementNode >( catch_, aststmt ); 238 CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_)); 239 FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) ); 240 return new TryStmt( tryBlock, aststmt, finallyBlock ); 287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) { 288 std::vector<ast::ptr<ast::CatchClause>> aststmt; 289 buildMoveList( catch_, aststmt ); 290 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) ); 291 ast::FinallyClause * finallyBlock = nullptr; 292 if ( finally_ ) { 293 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() ); 294 } 295 return new ast::TryStmt( location, 296 tryBlock, 297 std::move( aststmt ), 298 finallyBlock 299 ); 241 300 } // build_try 242 301 243 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) { 244 list< Statement * > aststmt; 245 buildMoveList< Statement, StatementNode >( body, aststmt ); 246 assert( aststmt.size() == 1 ); 247 return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() ); 302 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) { 303 return new ast::CatchClause( location, 304 kind, 305 maybeMoveBuild( decl ), 306 maybeMoveBuild( cond ), 307 buildMoveSingle( body ) 308 ); 248 309 } // build_catch 249 310 250 Statement * build_finally( StatementNode * stmt ) { 251 list< Statement * > aststmt; 252 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 253 assert( aststmt.size() == 1 ); 254 return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) ); 311 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) { 312 return new ast::FinallyClause( location, 313 strict_dynamic_cast<const ast::CompoundStmt *>( 314 buildMoveSingle( stmt ) 315 ) 316 ); 255 317 } // build_finally 256 318 257 SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) { 258 auto node = new SuspendStmt(); 259 260 node->type = type; 261 262 list< Statement * > stmts; 263 buildMoveList< Statement, StatementNode >( then, stmts ); 264 if(!stmts.empty()) { 265 assert( stmts.size() == 1 ); 266 node->then = dynamic_cast< CompoundStmt * >( stmts.front() ); 267 } 268 269 return node; 270 } 271 272 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) { 273 auto node = new WaitForStmt(); 274 275 WaitForStmt::Target target; 276 target.function = maybeBuild<Expression>( targetExpr ); 319 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) { 320 return new ast::SuspendStmt( location, 321 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>( 322 buildMoveOptional( then ) 323 ), 324 kind 325 ); 326 } // build_suspend 327 328 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) { 329 auto clause = new ast::WaitForClause( location ); 330 clause->target = maybeBuild( targetExpr ); 331 clause->stmt = maybeMoveBuild( stmt ); 332 clause->when_cond = notZeroExpr( maybeMoveBuild( when ) ); 277 333 278 334 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 279 335 targetExpr->set_next( nullptr ); 280 buildMoveList < Expression >( next, target.arguments );336 buildMoveList( next, clause->target_args ); 281 337 282 338 delete targetExpr; 283 339 284 node->clauses.push_back( WaitForStmt::Clause{ 285 target, 286 maybeMoveBuild<Statement >( stmt ), 287 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 288 }); 289 290 return node; 340 existing->clauses.insert( existing->clauses.begin(), clause ); 341 342 return existing; 291 343 } // build_waitfor 292 344 293 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) { 294 WaitForStmt::Target target; 295 target.function = maybeBuild<Expression>( targetExpr ); 296 297 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 298 targetExpr->set_next( nullptr ); 299 buildMoveList< Expression >( next, target.arguments ); 300 301 delete targetExpr; 302 303 node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{ 304 std::move( target ), 305 maybeMoveBuild<Statement >( stmt ), 306 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 307 }); 308 309 return node; 310 } // build_waitfor 311 312 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) { 313 auto node = new WaitForStmt(); 314 315 if( timeout ) { 316 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 317 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 318 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 319 } else { 320 node->orelse.statement = maybeMoveBuild<Statement >( stmt ); 321 node->orelse.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 322 } // if 323 324 return node; 345 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) { 346 existing->else_stmt = maybeMoveBuild( stmt ); 347 existing->else_cond = notZeroExpr( maybeMoveBuild( when ) ); 348 349 (void)location; 350 return existing; 351 } // build_waitfor_else 352 353 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) { 354 existing->timeout_time = maybeMoveBuild( timeout ); 355 existing->timeout_stmt = maybeMoveBuild( stmt ); 356 existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) ); 357 358 (void)location; 359 return existing; 325 360 } // build_waitfor_timeout 326 361 327 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_, ExpressionNode * else_when ) { 328 auto node = new WaitForStmt(); 329 330 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 331 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 332 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 333 334 node->orelse.statement = maybeMoveBuild<Statement >( else_ ); 335 node->orelse.condition = notZeroExpr( maybeMoveBuild<Expression>( else_when ) ); 336 337 return node; 338 } // build_waitfor_timeout 339 340 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) { 341 list< Expression * > e; 362 ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) { 363 ast::WhenClause * clause = new ast::WhenClause( loc ); 364 clause->when_cond = notZeroExpr( maybeMoveBuild( when ) ); 365 clause->stmt = maybeMoveBuild( stmt ); 366 clause->target = maybeMoveBuild( targetExpr ); 367 return new ast::WaitUntilStmt::ClauseNode( clause ); 368 } 369 ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) { 370 ast::WhenClause * clause = new ast::WhenClause( loc ); 371 clause->when_cond = notZeroExpr( maybeMoveBuild( when ) ); 372 clause->stmt = maybeMoveBuild( stmt ); 373 return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause ); 374 } 375 ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) { 376 ast::WhenClause * clause = new ast::WhenClause( loc ); 377 clause->when_cond = notZeroExpr( maybeMoveBuild( when ) ); 378 clause->stmt = maybeMoveBuild( stmt ); 379 clause->target = maybeMoveBuild( timeout ); 380 return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause ); 381 } 382 383 ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) { 384 ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc ); 385 retStmt->predicateTree = root; 386 387 // iterative tree traversal 388 std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal 389 ast::WaitUntilStmt::ClauseNode * currNode = nullptr; 390 ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr; 391 ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout 392 nodeStack.push_back(root); 393 394 do { 395 currNode = nodeStack.back(); 396 nodeStack.pop_back(); // remove node since it will be processed 397 398 switch (currNode->op) { 399 case ast::WaitUntilStmt::ClauseNode::LEAF: 400 retStmt->clauses.push_back(currNode->leaf); 401 break; 402 case ast::WaitUntilStmt::ClauseNode::ELSE: 403 retStmt->else_stmt = currNode->leaf->stmt 404 ? ast::deepCopy( currNode->leaf->stmt ) 405 : nullptr; 406 407 retStmt->else_cond = currNode->leaf->when_cond 408 ? ast::deepCopy( currNode->leaf->when_cond ) 409 : nullptr; 410 411 delete currNode->leaf; 412 break; 413 case ast::WaitUntilStmt::ClauseNode::TIMEOUT: 414 retStmt->timeout_time = currNode->leaf->target 415 ? ast::deepCopy( currNode->leaf->target ) 416 : nullptr; 417 retStmt->timeout_stmt = currNode->leaf->stmt 418 ? ast::deepCopy( currNode->leaf->stmt ) 419 : nullptr; 420 retStmt->timeout_cond = currNode->leaf->when_cond 421 ? ast::deepCopy( currNode->leaf->when_cond ) 422 : nullptr; 423 424 delete currNode->leaf; 425 break; 426 default: 427 nodeStack.push_back( currNode->right ); // process right after left 428 nodeStack.push_back( currNode->left ); 429 430 // Cut else/timeout out of the tree 431 if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) { 432 if ( lastInternalNode ) 433 lastInternalNode->right = currNode->left; 434 else // if not set then root is LEFT_OR 435 retStmt->predicateTree = currNode->left; 436 437 currNode->left = nullptr; 438 cleanup = currNode; 439 } 440 441 lastInternalNode = currNode; 442 break; 443 } 444 } while ( !nodeStack.empty() ); 445 446 if ( cleanup ) delete cleanup; 447 448 return retStmt; 449 } 450 451 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 452 std::vector<ast::ptr<ast::Expr>> e; 342 453 buildMoveList( exprs, e ); 343 Statement * s = maybeMoveBuild<Statement>( stmt );344 return new DeclStmt( new WithStmt( e, s ) );454 ast::Stmt * s = maybeMoveBuild( stmt ); 455 return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) ); 345 456 } // build_with 346 457 347 Statement * build_compound(StatementNode * first ) {348 CompoundStmt * cs = new CompoundStmt();349 buildMoveList( first, cs-> get_kids());458 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) { 459 auto cs = new ast::CompoundStmt( location ); 460 buildMoveList( first, cs->kids ); 350 461 return cs; 351 462 } // build_compound … … 355 466 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a 356 467 // conical form for code generation. 357 StatementNode * maybe_build_compound( StatementNode * first ) {468 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) { 358 469 // Optimization: if the control-structure statement is a compound statement, do not wrap it. 359 470 // e.g., if (...) {...} do not wrap the existing compound statement. 360 if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 361 CompoundStmt * cs = new CompoundStmt(); 362 buildMoveList( first, cs->get_kids() ); 363 return new StatementNode( cs ); 471 if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 472 return new StatementNode( build_compound( location, first ) ); 364 473 } // if 365 474 return first; … … 367 476 368 477 // Question 369 Statement * build_asm( bool voltile, Expression* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {370 list< Expression *> out, in;371 list< ConstantExpr *> clob;478 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 479 std::vector<ast::ptr<ast::Expr>> out, in; 480 std::vector<ast::ptr<ast::ConstantExpr>> clob; 372 481 373 482 buildMoveList( output, out ); 374 483 buildMoveList( input, in ); 375 484 buildMoveList( clobber, clob ); 376 return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels ); 485 return new ast::AsmStmt( location, 486 is_volatile, 487 maybeMoveBuild( instruction ), 488 std::move( out ), 489 std::move( in ), 490 std::move( clob ), 491 gotolabels ? gotolabels->labels : std::vector<ast::Label>() 492 ); 377 493 } // build_asm 378 494 379 Statement * build_directive( string * directive ) { 380 return new DirectiveStmt( *directive ); 495 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) { 496 auto stmt = new ast::DirectiveStmt( location, *directive ); 497 delete directive; 498 return stmt; 381 499 } // build_directive 382 500 383 Statement * build_mutex(ExpressionNode * exprs, StatementNode * stmt ) {384 list< Expression *> expList;501 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 502 std::vector<ast::ptr<ast::Expr>> expList; 385 503 buildMoveList( exprs, expList ); 386 Statement * body = maybeMoveBuild<Statement>( stmt );387 return new MutexStmt( body, expList);504 ast::Stmt * body = maybeMoveBuild( stmt ); 505 return new ast::MutexStmt( location, body, std::move( expList ) ); 388 506 } // build_mutex 389 507 -
src/Parser/TypeData.cc
r34b4268 r24d6572 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:12:51 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 10 22:36:52 202213 // Update Count : 6 7711 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 13:39:00 2023 13 // Update Count : 680 14 14 // 15 16 #include "TypeData.h" 15 17 16 18 #include <cassert> // for assert 17 19 #include <ostream> // for operator<<, ostream, basic_ostream 18 20 21 #include "AST/Decl.hpp" // for AggregateDecl, ObjectDecl, TypeDe... 22 #include "AST/Init.hpp" // for SingleInit, ListInit 23 #include "AST/Print.hpp" // for print 19 24 #include "Common/SemanticError.h" // for SemanticError 20 #include "Common/utility.h" // for maybeClone, maybeBuild, maybeMoveB... 21 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 22 #include "SynTree/Declaration.h" // for TypeDecl, ObjectDecl, FunctionDecl 23 #include "SynTree/Expression.h" // for Expression, ConstantExpr (ptr only) 24 #include "SynTree/Initializer.h" // for SingleInit, Initializer (ptr only) 25 #include "SynTree/Statement.h" // for CompoundStmt, Statement 26 #include "SynTree/Type.h" // for BasicType, Type, Type::ForallList 27 #include "TypeData.h" 25 #include "Common/utility.h" // for splice, spliceBegin 26 #include "Parser/ExpressionNode.h" // for ExpressionNode 27 #include "Parser/StatementNode.h" // for StatementNode 28 28 29 29 class Attribute; … … 33 33 TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ { 34 34 switch ( kind ) { 35 case Unknown: 36 case Pointer: 37 case Reference: 38 case EnumConstant: 39 case GlobalScope: 40 // nothing else to initialize 41 break; 42 case Basic: 43 // basic = new Basic_t; 44 break; 45 case Array: 46 // array = new Array_t; 35 case Unknown: 36 case Pointer: 37 case Reference: 38 case EnumConstant: 39 case GlobalScope: 40 case Basic: 41 // No unique data to initialize. 42 break; 43 case Array: 47 44 array.dimension = nullptr; 48 45 array.isVarLen = false; 49 46 array.isStatic = false; 50 47 break; 51 case Function: 52 // function = new Function_t; 48 case Function: 53 49 function.params = nullptr; 54 50 function.idList = nullptr; … … 57 53 function.withExprs = nullptr; 58 54 break; 59 // Enum is an Aggregate, so both structures are initialized together. 60 case Enum: 61 // enumeration = new Enumeration_t; 55 case Enum: 62 56 enumeration.name = nullptr; 63 57 enumeration.constants = nullptr; … … 65 59 enumeration.anon = false; 66 60 break; 67 case Aggregate: 68 // aggregate = new Aggregate_t; 69 aggregate.kind = AggregateDecl::NoAggregate; 61 case Aggregate: 62 aggregate.kind = ast::AggregateDecl::NoAggregate; 70 63 aggregate.name = nullptr; 71 64 aggregate.params = nullptr; … … 77 70 aggregate.anon = false; 78 71 break; 79 case AggregateInst: 80 // aggInst = new AggInst_t; 72 case AggregateInst: 81 73 aggInst.aggregate = nullptr; 82 74 aggInst.params = nullptr; 83 75 aggInst.hoistType = false; 84 76 break; 85 case Symbolic: 86 case SymbolicInst: 87 // symbolic = new Symbolic_t; 77 case Symbolic: 78 case SymbolicInst: 88 79 symbolic.name = nullptr; 89 80 symbolic.params = nullptr; … … 91 82 symbolic.assertions = nullptr; 92 83 break; 93 case Tuple: 94 // tuple = new Tuple_t; 84 case Tuple: 95 85 tuple = nullptr; 96 86 break; 97 case Typeof: 98 case Basetypeof: 99 // typeexpr = new Typeof_t; 87 case Typeof: 88 case Basetypeof: 100 89 typeexpr = nullptr; 101 90 break; 102 case Vtable:103 break;104 case Builtin:105 // builtin = new Builtin_t;106 case Qualified:91 case Vtable: 92 case Builtin: 93 // No unique data to initialize. 94 break; 95 case Qualified: 107 96 qualified.parent = nullptr; 108 97 qualified.child = nullptr; … … 117 106 118 107 switch ( kind ) { 119 case Unknown: 120 case Pointer: 121 case Reference: 122 case EnumConstant: 123 case GlobalScope: 124 // nothing to destroy 125 break; 126 case Basic: 127 // delete basic; 128 break; 129 case Array: 108 case Unknown: 109 case Pointer: 110 case Reference: 111 case EnumConstant: 112 case GlobalScope: 113 case Basic: 114 // No unique data to deconstruct. 115 break; 116 case Array: 130 117 delete array.dimension; 131 // delete array; 132 break; 133 case Function: 118 break; 119 case Function: 134 120 delete function.params; 135 121 delete function.idList; … … 137 123 delete function.body; 138 124 delete function.withExprs; 139 // delete function; 140 break; 141 case Aggregate: 125 break; 126 case Aggregate: 142 127 delete aggregate.name; 143 128 delete aggregate.params; 144 129 delete aggregate.actuals; 145 130 delete aggregate.fields; 146 // delete aggregate; 147 break; 148 case AggregateInst: 131 break; 132 case AggregateInst: 149 133 delete aggInst.aggregate; 150 134 delete aggInst.params; 151 // delete aggInst; 152 break; 153 case Enum: 135 break; 136 case Enum: 154 137 delete enumeration.name; 155 138 delete enumeration.constants; 156 // delete enumeration; 157 break; 158 case Symbolic: 159 case SymbolicInst: 139 break; 140 case Symbolic: 141 case SymbolicInst: 160 142 delete symbolic.name; 161 143 delete symbolic.params; 162 144 delete symbolic.actuals; 163 145 delete symbolic.assertions; 164 // delete symbolic; 165 break; 166 case Tuple: 167 // delete tuple->members; 146 break; 147 case Tuple: 168 148 delete tuple; 169 149 break; 170 case Typeof: 171 case Basetypeof: 172 // delete typeexpr->expr; 150 case Typeof: 151 case Basetypeof: 173 152 delete typeexpr; 174 153 break; 175 case Vtable: 176 break; 177 case Builtin: 178 // delete builtin; 179 break; 180 case Qualified: 154 case Vtable: 155 case Builtin: 156 // No unique data to deconstruct. 157 break; 158 case Qualified: 181 159 delete qualified.parent; 182 160 delete qualified.child; 161 break; 183 162 } // switch 184 163 } // TypeData::~TypeData … … 192 171 193 172 switch ( kind ) { 194 case Unknown:195 case EnumConstant:196 case Pointer:197 case Reference:198 case GlobalScope:173 case Unknown: 174 case EnumConstant: 175 case Pointer: 176 case Reference: 177 case GlobalScope: 199 178 // nothing else to copy 200 179 break; 201 case Basic:180 case Basic: 202 181 newtype->basictype = basictype; 203 182 newtype->complextype = complextype; … … 205 184 newtype->length = length; 206 185 break; 207 case Array:186 case Array: 208 187 newtype->array.dimension = maybeClone( array.dimension ); 209 188 newtype->array.isVarLen = array.isVarLen; 210 189 newtype->array.isStatic = array.isStatic; 211 190 break; 212 case Function:191 case Function: 213 192 newtype->function.params = maybeClone( function.params ); 214 193 newtype->function.idList = maybeClone( function.idList ); … … 217 196 newtype->function.withExprs = maybeClone( function.withExprs ); 218 197 break; 219 case Aggregate:198 case Aggregate: 220 199 newtype->aggregate.kind = aggregate.kind; 221 200 newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr; … … 228 207 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr; 229 208 break; 230 case AggregateInst:209 case AggregateInst: 231 210 newtype->aggInst.aggregate = maybeClone( aggInst.aggregate ); 232 211 newtype->aggInst.params = maybeClone( aggInst.params ); 233 212 newtype->aggInst.hoistType = aggInst.hoistType; 234 213 break; 235 case Enum:214 case Enum: 236 215 newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr; 237 216 newtype->enumeration.constants = maybeClone( enumeration.constants ); … … 239 218 newtype->enumeration.anon = enumeration.anon; 240 219 break; 241 case Symbolic:242 case SymbolicInst:220 case Symbolic: 221 case SymbolicInst: 243 222 newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr; 244 223 newtype->symbolic.params = maybeClone( symbolic.params ); … … 247 226 newtype->symbolic.isTypedef = symbolic.isTypedef; 248 227 break; 249 case Tuple:228 case Tuple: 250 229 newtype->tuple = maybeClone( tuple ); 251 230 break; 252 case Typeof:253 case Basetypeof:231 case Typeof: 232 case Basetypeof: 254 233 newtype->typeexpr = maybeClone( typeexpr ); 255 234 break; 256 case Vtable:257 break; 258 case Builtin:235 case Vtable: 236 break; 237 case Builtin: 259 238 assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One ); 260 239 newtype->builtintype = builtintype; 261 240 break; 262 case Qualified:241 case Qualified: 263 242 newtype->qualified.parent = maybeClone( qualified.parent ); 264 243 newtype->qualified.child = maybeClone( qualified.child ); … … 270 249 271 250 void TypeData::print( ostream &os, int indent ) const { 272 for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) { 273 if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' '; 274 } // for 251 ast::print( os, qualifiers ); 275 252 276 253 if ( forall ) { … … 280 257 281 258 switch ( kind ) { 282 case Basic:259 case Basic: 283 260 if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " "; 284 261 if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " "; … … 286 263 if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " "; 287 264 break; 288 case Pointer:265 case Pointer: 289 266 os << "pointer "; 290 267 if ( base ) { … … 293 270 } // if 294 271 break; 295 case Reference:272 case Reference: 296 273 os << "reference "; 297 274 if ( base ) { … … 300 277 } // if 301 278 break; 302 case Array:279 case Array: 303 280 if ( array.isStatic ) { 304 281 os << "static "; … … 316 293 } // if 317 294 break; 318 case Function:295 case Function: 319 296 os << "function" << endl; 320 297 if ( function.params ) { … … 344 321 } // if 345 322 break; 346 case Aggregate:347 os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;323 case Aggregate: 324 os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl; 348 325 if ( aggregate.params ) { 349 326 os << string( indent + 2, ' ' ) << "with type parameters" << endl; … … 362 339 } // if 363 340 break; 364 case AggregateInst:341 case AggregateInst: 365 342 if ( aggInst.aggregate ) { 366 343 os << "instance of " ; … … 374 351 } // if 375 352 break; 376 case Enum:377 os << "enumeration " ;353 case Enum: 354 os << "enumeration " << *enumeration.name << endl;; 378 355 if ( enumeration.constants ) { 379 356 os << "with constants" << endl; … … 388 365 } // if 389 366 break; 390 case EnumConstant:367 case EnumConstant: 391 368 os << "enumeration constant "; 392 369 break; 393 case Symbolic:370 case Symbolic: 394 371 if ( symbolic.isTypedef ) { 395 372 os << "typedef definition "; … … 411 388 } // if 412 389 break; 413 case SymbolicInst:390 case SymbolicInst: 414 391 os << *symbolic.name; 415 392 if ( symbolic.actuals ) { … … 419 396 } // if 420 397 break; 421 case Tuple:398 case Tuple: 422 399 os << "tuple "; 423 400 if ( tuple ) { … … 426 403 } // if 427 404 break; 428 case Basetypeof:405 case Basetypeof: 429 406 os << "base-"; 430 407 #if defined(__GNUC__) && __GNUC__ >= 7 … … 432 409 #endif 433 410 // FALL THROUGH 434 case Typeof:411 case Typeof: 435 412 os << "type-of expression "; 436 413 if ( typeexpr ) { … … 438 415 } // if 439 416 break; 440 case Vtable:417 case Vtable: 441 418 os << "vtable"; 442 419 break; 443 case Builtin:420 case Builtin: 444 421 os << DeclarationNode::builtinTypeNames[builtintype]; 445 422 break; 446 case GlobalScope:447 break; 448 case Qualified:423 case GlobalScope: 424 break; 425 case Qualified: 449 426 qualified.parent->print( os ); 450 427 os << "."; 451 428 qualified.child->print( os ); 452 429 break; 453 case Unknown:430 case Unknown: 454 431 os << "entity of unknown type "; 455 432 break; 456 default:433 default: 457 434 os << "internal error: TypeData::print " << kind << endl; 458 435 assert( false ); … … 462 439 const std::string * TypeData::leafName() const { 463 440 switch ( kind ) { 464 case Unknown:465 case Pointer:466 case Reference:467 case EnumConstant:468 case GlobalScope:469 case Array:470 case Basic:471 case Function:472 case AggregateInst:473 case Tuple:474 case Typeof:475 case Basetypeof:476 case Builtin:477 case Vtable:441 case Unknown: 442 case Pointer: 443 case Reference: 444 case EnumConstant: 445 case GlobalScope: 446 case Array: 447 case Basic: 448 case Function: 449 case AggregateInst: 450 case Tuple: 451 case Typeof: 452 case Basetypeof: 453 case Builtin: 454 case Vtable: 478 455 assertf(false, "Tried to get leaf name from kind without a name: %d", kind); 479 456 break; 480 case Aggregate:457 case Aggregate: 481 458 return aggregate.name; 482 case Enum:459 case Enum: 483 460 return enumeration.name; 484 case Symbolic:485 case SymbolicInst:461 case Symbolic: 462 case SymbolicInst: 486 463 return symbolic.name; 487 case Qualified:464 case Qualified: 488 465 return qualified.child->leafName(); 489 466 } // switch … … 492 469 493 470 494 template< typename ForallList > 495 void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) { 496 buildList( firstNode, outputList ); 471 void buildForall( 472 const DeclarationNode * firstNode, 473 std::vector<ast::ptr<ast::TypeInstType>> &outputList ) { 474 { 475 std::vector<ast::ptr<ast::Type>> tmpList; 476 buildTypeList( firstNode, tmpList ); 477 for ( auto tmp : tmpList ) { 478 outputList.emplace_back( 479 strict_dynamic_cast<const ast::TypeInstType *>( 480 tmp.release() ) ); 481 } 482 } 497 483 auto n = firstNode; 498 for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i, n = (DeclarationNode*)n->get_next() ) { 499 TypeDecl * td = static_cast<TypeDecl *>(*i); 500 if ( n->variable.tyClass == TypeDecl::Otype ) { 501 // add assertion parameters to `type' tyvars in reverse order 502 // add dtor: void ^?{}(T *) 503 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false ); 504 dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 505 td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) ); 506 507 // add copy ctor: void ?{}(T *, T) 508 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false ); 509 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 510 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 511 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) ); 512 513 // add default ctor: void ?{}(T *) 514 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false ); 515 ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 516 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) ); 517 518 // add assignment operator: T * ?=?(T *, T) 519 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false ); 520 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 521 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 522 assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 523 td->get_assertions().push_front( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, assignType, nullptr ) ); 524 } // if 484 for ( auto i = outputList.begin() ; 485 i != outputList.end() ; 486 ++i, n = (DeclarationNode*)n->get_next() ) { 487 // Only the object type class adds additional assertions. 488 if ( n->variable.tyClass != ast::TypeDecl::Otype ) { 489 continue; 490 } 491 492 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>(); 493 std::vector<ast::ptr<ast::DeclWithType>> newAssertions; 494 auto mutTypeDecl = ast::mutate( td ); 495 const CodeLocation & location = mutTypeDecl->location; 496 *i = mutTypeDecl; 497 498 // add assertion parameters to `type' tyvars in reverse order 499 // add assignment operator: T * ?=?(T *, T) 500 newAssertions.push_back( new ast::FunctionDecl( 501 location, 502 "?=?", 503 {}, // forall 504 {}, // assertions 505 { 506 new ast::ObjectDecl( 507 location, 508 "", 509 new ast::ReferenceType( i->get() ), 510 (ast::Init *)nullptr, 511 ast::Storage::Classes(), 512 ast::Linkage::Cforall, 513 (ast::Expr *)nullptr 514 ), 515 new ast::ObjectDecl( 516 location, 517 "", 518 i->get(), 519 (ast::Init *)nullptr, 520 ast::Storage::Classes(), 521 ast::Linkage::Cforall, 522 (ast::Expr *)nullptr 523 ), 524 }, // params 525 { 526 new ast::ObjectDecl( 527 location, 528 "", 529 i->get(), 530 (ast::Init *)nullptr, 531 ast::Storage::Classes(), 532 ast::Linkage::Cforall, 533 (ast::Expr *)nullptr 534 ), 535 }, // returns 536 (ast::CompoundStmt *)nullptr, 537 ast::Storage::Classes(), 538 ast::Linkage::Cforall 539 ) ); 540 541 // add default ctor: void ?{}(T *) 542 newAssertions.push_back( new ast::FunctionDecl( 543 location, 544 "?{}", 545 {}, // forall 546 {}, // assertions 547 { 548 new ast::ObjectDecl( 549 location, 550 "", 551 new ast::ReferenceType( i->get() ), 552 (ast::Init *)nullptr, 553 ast::Storage::Classes(), 554 ast::Linkage::Cforall, 555 (ast::Expr *)nullptr 556 ), 557 }, // params 558 {}, // returns 559 (ast::CompoundStmt *)nullptr, 560 ast::Storage::Classes(), 561 ast::Linkage::Cforall 562 ) ); 563 564 // add copy ctor: void ?{}(T *, T) 565 newAssertions.push_back( new ast::FunctionDecl( 566 location, 567 "?{}", 568 {}, // forall 569 {}, // assertions 570 { 571 new ast::ObjectDecl( 572 location, 573 "", 574 new ast::ReferenceType( i->get() ), 575 (ast::Init *)nullptr, 576 ast::Storage::Classes(), 577 ast::Linkage::Cforall, 578 (ast::Expr *)nullptr 579 ), 580 new ast::ObjectDecl( 581 location, 582 "", 583 i->get(), 584 (ast::Init *)nullptr, 585 ast::Storage::Classes(), 586 ast::Linkage::Cforall, 587 (ast::Expr *)nullptr 588 ), 589 }, // params 590 {}, // returns 591 (ast::CompoundStmt *)nullptr, 592 ast::Storage::Classes(), 593 ast::Linkage::Cforall 594 ) ); 595 596 // add dtor: void ^?{}(T *) 597 newAssertions.push_back( new ast::FunctionDecl( 598 location, 599 "^?{}", 600 {}, // forall 601 {}, // assertions 602 { 603 new ast::ObjectDecl( 604 location, 605 "", 606 new ast::ReferenceType( i->get() ), 607 (ast::Init *)nullptr, 608 ast::Storage::Classes(), 609 ast::Linkage::Cforall, 610 (ast::Expr *)nullptr 611 ), 612 }, // params 613 {}, // returns 614 (ast::CompoundStmt *)nullptr, 615 ast::Storage::Classes(), 616 ast::Linkage::Cforall 617 ) ); 618 619 spliceBegin( mutTypeDecl->assertions, newAssertions ); 620 } // for 621 } 622 623 624 void buildForall( 625 const DeclarationNode * firstNode, 626 std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) { 627 buildList( firstNode, outputForall ); 628 auto n = firstNode; 629 for ( auto i = outputForall.begin() ; 630 i != outputForall.end() ; 631 ++i, n = (DeclarationNode*)n->get_next() ) { 632 // Only the object type class adds additional assertions. 633 if ( n->variable.tyClass != ast::TypeDecl::Otype ) { 634 continue; 635 } 636 637 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>(); 638 std::vector<ast::ptr<ast::DeclWithType>> newAssertions; 639 auto mutTypeDecl = ast::mutate( td ); 640 const CodeLocation & location = mutTypeDecl->location; 641 *i = mutTypeDecl; 642 643 // add assertion parameters to `type' tyvars in reverse order 644 // add assignment operator: T * ?=?(T *, T) 645 newAssertions.push_back( new ast::FunctionDecl( 646 location, 647 "?=?", 648 {}, // forall 649 {}, // assertions 650 { 651 new ast::ObjectDecl( 652 location, 653 "", 654 new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ), 655 (ast::Init *)nullptr, 656 ast::Storage::Classes(), 657 ast::Linkage::Cforall, 658 (ast::Expr *)nullptr 659 ), 660 new ast::ObjectDecl( 661 location, 662 "", 663 new ast::TypeInstType( td->name, *i ), 664 (ast::Init *)nullptr, 665 ast::Storage::Classes(), 666 ast::Linkage::Cforall, 667 (ast::Expr *)nullptr 668 ), 669 }, // params 670 { 671 new ast::ObjectDecl( 672 location, 673 "", 674 new ast::TypeInstType( td->name, *i ), 675 (ast::Init *)nullptr, 676 ast::Storage::Classes(), 677 ast::Linkage::Cforall, 678 (ast::Expr *)nullptr 679 ), 680 }, // returns 681 (ast::CompoundStmt *)nullptr, 682 ast::Storage::Classes(), 683 ast::Linkage::Cforall 684 ) ); 685 686 // add default ctor: void ?{}(T *) 687 newAssertions.push_back( new ast::FunctionDecl( 688 location, 689 "?{}", 690 {}, // forall 691 {}, // assertions 692 { 693 new ast::ObjectDecl( 694 location, 695 "", 696 new ast::ReferenceType( 697 new ast::TypeInstType( td->name, i->get() ) ), 698 (ast::Init *)nullptr, 699 ast::Storage::Classes(), 700 ast::Linkage::Cforall, 701 (ast::Expr *)nullptr 702 ), 703 }, // params 704 {}, // returns 705 (ast::CompoundStmt *)nullptr, 706 ast::Storage::Classes(), 707 ast::Linkage::Cforall 708 ) ); 709 710 // add copy ctor: void ?{}(T *, T) 711 newAssertions.push_back( new ast::FunctionDecl( 712 location, 713 "?{}", 714 {}, // forall 715 {}, // assertions 716 { 717 new ast::ObjectDecl( 718 location, 719 "", 720 new ast::ReferenceType( 721 new ast::TypeInstType( td->name, *i ) ), 722 (ast::Init *)nullptr, 723 ast::Storage::Classes(), 724 ast::Linkage::Cforall, 725 (ast::Expr *)nullptr 726 ), 727 new ast::ObjectDecl( 728 location, 729 "", 730 new ast::TypeInstType( td->name, *i ), 731 (ast::Init *)nullptr, 732 ast::Storage::Classes(), 733 ast::Linkage::Cforall, 734 (ast::Expr *)nullptr 735 ), 736 }, // params 737 {}, // returns 738 (ast::CompoundStmt *)nullptr, 739 ast::Storage::Classes(), 740 ast::Linkage::Cforall 741 ) ); 742 743 // add dtor: void ^?{}(T *) 744 newAssertions.push_back( new ast::FunctionDecl( 745 location, 746 "^?{}", 747 {}, // forall 748 {}, // assertions 749 { 750 new ast::ObjectDecl( 751 location, 752 "", 753 new ast::ReferenceType( 754 new ast::TypeInstType( i->get() ) 755 ), 756 (ast::Init *)nullptr, 757 ast::Storage::Classes(), 758 ast::Linkage::Cforall, 759 (ast::Expr *)nullptr 760 ), 761 }, // params 762 {}, // returns 763 (ast::CompoundStmt *)nullptr, 764 ast::Storage::Classes(), 765 ast::Linkage::Cforall 766 ) ); 767 768 spliceBegin( mutTypeDecl->assertions, newAssertions ); 525 769 } // for 526 770 } // buildForall 527 771 528 772 529 Type * typebuild( const TypeData * td ) {773 ast::Type * typebuild( const TypeData * td ) { 530 774 assert( td ); 531 775 switch ( td->kind ) { 532 case TypeData::Unknown:776 case TypeData::Unknown: 533 777 // fill in implicit int 534 return new BasicType( buildQualifiers( td ), BasicType::SignedInt ); 535 case TypeData::Basic: 778 return new ast::BasicType( 779 ast::BasicType::SignedInt, 780 buildQualifiers( td ) 781 ); 782 case TypeData::Basic: 536 783 return buildBasicType( td ); 537 case TypeData::Pointer:784 case TypeData::Pointer: 538 785 return buildPointer( td ); 539 case TypeData::Array:786 case TypeData::Array: 540 787 return buildArray( td ); 541 case TypeData::Reference:788 case TypeData::Reference: 542 789 return buildReference( td ); 543 case TypeData::Function:544 return buildFunction ( td );545 case TypeData::AggregateInst:790 case TypeData::Function: 791 return buildFunctionType( td ); 792 case TypeData::AggregateInst: 546 793 return buildAggInst( td ); 547 case TypeData::EnumConstant:548 return new EnumInstType( buildQualifiers( td ), "");549 case TypeData::SymbolicInst:794 case TypeData::EnumConstant: 795 return new ast::EnumInstType( "", buildQualifiers( td ) ); 796 case TypeData::SymbolicInst: 550 797 return buildSymbolicInst( td ); 551 case TypeData::Tuple:798 case TypeData::Tuple: 552 799 return buildTuple( td ); 553 case TypeData::Typeof:554 case TypeData::Basetypeof:800 case TypeData::Typeof: 801 case TypeData::Basetypeof: 555 802 return buildTypeof( td ); 556 case TypeData::Vtable:803 case TypeData::Vtable: 557 804 return buildVtable( td ); 558 case TypeData::Builtin:805 case TypeData::Builtin: 559 806 switch ( td->builtintype ) { 560 case DeclarationNode::Zero:561 return new ZeroType( noQualifiers);562 case DeclarationNode::One:563 return new OneType( noQualifiers);564 default:565 return new VarArgsType( buildQualifiers( td ) );807 case DeclarationNode::Zero: 808 return new ast::ZeroType(); 809 case DeclarationNode::One: 810 return new ast::OneType(); 811 default: 812 return new ast::VarArgsType( buildQualifiers( td ) ); 566 813 } // switch 567 case TypeData::GlobalScope: 568 return new GlobalScopeType(); 569 case TypeData::Qualified: 570 return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) ); 571 case TypeData::Symbolic: 572 case TypeData::Enum: 573 case TypeData::Aggregate: 814 case TypeData::GlobalScope: 815 return new ast::GlobalScopeType(); 816 case TypeData::Qualified: 817 return new ast::QualifiedType( 818 typebuild( td->qualified.parent ), 819 typebuild( td->qualified.child ), 820 buildQualifiers( td ) 821 ); 822 case TypeData::Symbolic: 823 case TypeData::Enum: 824 case TypeData::Aggregate: 574 825 assert( false ); 575 826 } // switch … … 583 834 584 835 switch ( td->kind ) { 585 case TypeData::Aggregate:836 case TypeData::Aggregate: 586 837 if ( ! toplevel && td->aggregate.body ) { 587 838 ret = td->clone(); 588 839 } // if 589 840 break; 590 case TypeData::Enum:841 case TypeData::Enum: 591 842 if ( ! toplevel && td->enumeration.body ) { 592 843 ret = td->clone(); 593 844 } // if 594 845 break; 595 case TypeData::AggregateInst:846 case TypeData::AggregateInst: 596 847 if ( td->aggInst.aggregate ) { 597 848 ret = typeextractAggregate( td->aggInst.aggregate, false ); 598 849 } // if 599 850 break; 600 default:851 default: 601 852 if ( td->base ) { 602 853 ret = typeextractAggregate( td->base, false ); … … 607 858 608 859 609 Type::Qualifiers buildQualifiers( const TypeData * td ) {860 ast::CV::Qualifiers buildQualifiers( const TypeData * td ) { 610 861 return td->qualifiers; 611 862 } // buildQualifiers … … 616 867 } // genTSError 617 868 618 Type * buildBasicType( const TypeData * td ) {619 BasicType::Kind ret;869 ast::Type * buildBasicType( const TypeData * td ) { 870 ast::BasicType::Kind ret; 620 871 621 872 switch ( td->basictype ) { 622 case DeclarationNode::Void:873 case DeclarationNode::Void: 623 874 if ( td->signedness != DeclarationNode::NoSignedness ) { 624 875 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 627 878 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); 628 879 } // if 629 return new VoidType( buildQualifiers( td ) );630 break; 631 632 case DeclarationNode::Bool:880 return new ast::VoidType( buildQualifiers( td ) ); 881 break; 882 883 case DeclarationNode::Bool: 633 884 if ( td->signedness != DeclarationNode::NoSignedness ) { 634 885 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 638 889 } // if 639 890 640 ret = BasicType::Bool;641 break; 642 643 case DeclarationNode::Char:891 ret = ast::BasicType::Bool; 892 break; 893 894 case DeclarationNode::Char: 644 895 // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the 645 896 // character types. The implementation shall define char to have the same range, representation, and behavior as 646 897 // either signed char or unsigned char. 647 static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar,BasicType::Char };898 static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char }; 648 899 649 900 if ( td->length != DeclarationNode::NoLength ) { … … 654 905 break; 655 906 656 case DeclarationNode::Int:657 static BasicType::Kind inttype[2][4] = {658 { BasicType::ShortSignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt,BasicType::SignedInt },659 { BasicType::ShortUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt,BasicType::UnsignedInt },907 case DeclarationNode::Int: 908 static ast::BasicType::Kind inttype[2][4] = { 909 { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt }, 910 { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt }, 660 911 }; 661 912 662 Integral: ;913 Integral: ; 663 914 if ( td->signedness == DeclarationNode::NoSignedness ) { 664 915 const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed; … … 667 918 break; 668 919 669 case DeclarationNode::Int128:670 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 :BasicType::SignedInt128;920 case DeclarationNode::Int128: 921 ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128; 671 922 if ( td->length != DeclarationNode::NoLength ) { 672 923 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); … … 674 925 break; 675 926 676 case DeclarationNode::Float:677 case DeclarationNode::Double:678 case DeclarationNode::LongDouble: // not set until below679 case DeclarationNode::uuFloat80:680 case DeclarationNode::uuFloat128:681 case DeclarationNode::uFloat16:682 case DeclarationNode::uFloat32:683 case DeclarationNode::uFloat32x:684 case DeclarationNode::uFloat64:685 case DeclarationNode::uFloat64x:686 case DeclarationNode::uFloat128:687 case DeclarationNode::uFloat128x:688 static BasicType::Kind floattype[2][12] = {689 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, (BasicType::Kind)-1, (BasicType::Kind)-1, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex,BasicType::uFloat128xComplex, },690 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128,BasicType::uFloat128x, },927 case DeclarationNode::Float: 928 case DeclarationNode::Double: 929 case DeclarationNode::LongDouble: // not set until below 930 case DeclarationNode::uuFloat80: 931 case DeclarationNode::uuFloat128: 932 case DeclarationNode::uFloat16: 933 case DeclarationNode::uFloat32: 934 case DeclarationNode::uFloat32x: 935 case DeclarationNode::uFloat64: 936 case DeclarationNode::uFloat64x: 937 case DeclarationNode::uFloat128: 938 case DeclarationNode::uFloat128x: 939 static ast::BasicType::Kind floattype[2][12] = { 940 { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, }, 941 { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, }, 691 942 }; 692 943 693 FloatingPoint: ;944 FloatingPoint: ; 694 945 if ( td->signedness != DeclarationNode::NoSignedness ) { 695 946 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 715 966 break; 716 967 717 case DeclarationNode::NoBasicType:968 case DeclarationNode::NoBasicType: 718 969 // No basic type in declaration => default double for Complex/Imaginary and int type for integral types 719 970 if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) { … … 724 975 const_cast<TypeData *>(td)->basictype = DeclarationNode::Int; 725 976 goto Integral; 726 default:727 assertf( false, "unknown basic type" );977 default: 978 assertf( false, "unknown basic type" ); 728 979 return nullptr; 729 980 } // switch 730 981 731 BasicType * bt = new BasicType( buildQualifiers( td ), ret ); 732 buildForall( td->forall, bt->get_forall() ); 982 ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) ); 733 983 return bt; 734 984 } // buildBasicType 735 985 736 986 737 PointerType * buildPointer( const TypeData * td ) {738 PointerType * pt;987 ast::PointerType * buildPointer( const TypeData * td ) { 988 ast::PointerType * pt; 739 989 if ( td->base ) { 740 pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) ); 990 pt = new ast::PointerType( 991 typebuild( td->base ), 992 buildQualifiers( td ) 993 ); 741 994 } else { 742 pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 995 pt = new ast::PointerType( 996 new ast::BasicType( ast::BasicType::SignedInt ), 997 buildQualifiers( td ) 998 ); 743 999 } // if 744 buildForall( td->forall, pt->get_forall() );745 1000 return pt; 746 1001 } // buildPointer 747 1002 748 1003 749 ArrayType * buildArray( const TypeData * td ) {750 ArrayType * at;1004 ast::ArrayType * buildArray( const TypeData * td ) { 1005 ast::ArrayType * at; 751 1006 if ( td->base ) { 752 at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array.dimension ), 753 td->array.isVarLen, td->array.isStatic ); 1007 at = new ast::ArrayType( 1008 typebuild( td->base ), 1009 maybeBuild( td->array.dimension ), 1010 td->array.isVarLen ? ast::VariableLen : ast::FixedLen, 1011 td->array.isStatic ? ast::StaticDim : ast::DynamicDim, 1012 buildQualifiers( td ) 1013 ); 754 1014 } else { 755 at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 756 maybeBuild< Expression >( td->array.dimension ), td->array.isVarLen, td->array.isStatic ); 1015 at = new ast::ArrayType( 1016 new ast::BasicType( ast::BasicType::SignedInt ), 1017 maybeBuild( td->array.dimension ), 1018 td->array.isVarLen ? ast::VariableLen : ast::FixedLen, 1019 td->array.isStatic ? ast::StaticDim : ast::DynamicDim, 1020 buildQualifiers( td ) 1021 ); 757 1022 } // if 758 buildForall( td->forall, at->get_forall() );759 1023 return at; 760 1024 } // buildArray 761 1025 762 1026 763 ReferenceType * buildReference( const TypeData * td ) {764 ReferenceType * rt;1027 ast::ReferenceType * buildReference( const TypeData * td ) { 1028 ast::ReferenceType * rt; 765 1029 if ( td->base ) { 766 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) ); 1030 rt = new ast::ReferenceType( 1031 typebuild( td->base ), 1032 buildQualifiers( td ) 1033 ); 767 1034 } else { 768 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 1035 rt = new ast::ReferenceType( 1036 new ast::BasicType( ast::BasicType::SignedInt ), 1037 buildQualifiers( td ) 1038 ); 769 1039 } // if 770 buildForall( td->forall, rt->get_forall() );771 1040 return rt; 772 1041 } // buildReference 773 1042 774 1043 775 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {1044 ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) { 776 1045 assert( td->kind == TypeData::Aggregate ); 777 AggregateDecl * at;1046 ast::AggregateDecl * at; 778 1047 switch ( td->aggregate.kind ) { 779 case AggregateDecl::Struct: 780 case AggregateDecl::Coroutine: 781 case AggregateDecl::Exception: 782 case AggregateDecl::Generator: 783 case AggregateDecl::Monitor: 784 case AggregateDecl::Thread: 785 at = new StructDecl( *td->aggregate.name, td->aggregate.kind, attributes, linkage ); 786 buildForall( td->aggregate.params, at->get_parameters() ); 787 break; 788 case AggregateDecl::Union: 789 at = new UnionDecl( *td->aggregate.name, attributes, linkage ); 790 buildForall( td->aggregate.params, at->get_parameters() ); 791 break; 792 case AggregateDecl::Trait: 793 at = new TraitDecl( *td->aggregate.name, attributes, linkage ); 794 buildList( td->aggregate.params, at->get_parameters() ); 795 break; 796 default: 1048 case ast::AggregateDecl::Struct: 1049 case ast::AggregateDecl::Coroutine: 1050 case ast::AggregateDecl::Exception: 1051 case ast::AggregateDecl::Generator: 1052 case ast::AggregateDecl::Monitor: 1053 case ast::AggregateDecl::Thread: 1054 at = new ast::StructDecl( td->location, 1055 *td->aggregate.name, 1056 td->aggregate.kind, 1057 std::move( attributes ), 1058 linkage 1059 ); 1060 buildForall( td->aggregate.params, at->params ); 1061 break; 1062 case ast::AggregateDecl::Union: 1063 at = new ast::UnionDecl( td->location, 1064 *td->aggregate.name, 1065 std::move( attributes ), 1066 linkage 1067 ); 1068 buildForall( td->aggregate.params, at->params ); 1069 break; 1070 case ast::AggregateDecl::Trait: 1071 at = new ast::TraitDecl( td->location, 1072 *td->aggregate.name, 1073 std::move( attributes ), 1074 linkage 1075 ); 1076 buildList( td->aggregate.params, at->params ); 1077 break; 1078 default: 797 1079 assert( false ); 798 1080 } // switch 799 1081 800 buildList( td->aggregate.fields, at-> get_members());1082 buildList( td->aggregate.fields, at->members ); 801 1083 at->set_body( td->aggregate.body ); 802 1084 … … 805 1087 806 1088 807 ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1089 ast::BaseInstType * buildComAggInst( 1090 const TypeData * type, 1091 std::vector<ast::ptr<ast::Attribute>> && attributes, 1092 ast::Linkage::Spec linkage ) { 808 1093 switch ( type->kind ) { 809 case TypeData::Enum: { 810 if ( type->enumeration.body ) { 811 EnumDecl * typedecl = buildEnum( type, attributes, linkage ); 812 return new EnumInstType( buildQualifiers( type ), typedecl ); 813 } else { 814 return new EnumInstType( buildQualifiers( type ), *type->enumeration.name ); 815 } // if 816 } 817 case TypeData::Aggregate: { 818 ReferenceToType * ret; 819 if ( type->aggregate.body ) { 820 AggregateDecl * typedecl = buildAggregate( type, attributes, linkage ); 821 switch ( type->aggregate.kind ) { 822 case AggregateDecl::Struct: 823 case AggregateDecl::Coroutine: 824 case AggregateDecl::Monitor: 825 case AggregateDecl::Thread: 826 ret = new StructInstType( buildQualifiers( type ), (StructDecl *)typedecl ); 827 break; 828 case AggregateDecl::Union: 829 ret = new UnionInstType( buildQualifiers( type ), (UnionDecl *)typedecl ); 830 break; 831 case AggregateDecl::Trait: 832 assert( false ); 833 //ret = new TraitInstType( buildQualifiers( type ), (TraitDecl *)typedecl ); 834 break; 835 default: 836 assert( false ); 837 } // switch 838 } else { 839 switch ( type->aggregate.kind ) { 840 case AggregateDecl::Struct: 841 case AggregateDecl::Coroutine: 842 case AggregateDecl::Monitor: 843 case AggregateDecl::Thread: 844 ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name ); 845 break; 846 case AggregateDecl::Union: 847 ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name ); 848 break; 849 case AggregateDecl::Trait: 850 ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name ); 851 break; 852 default: 853 assert( false ); 854 } // switch 855 } // if 856 return ret; 857 } 858 default: 1094 case TypeData::Enum: 1095 if ( type->enumeration.body ) { 1096 ast::EnumDecl * typedecl = 1097 buildEnum( type, std::move( attributes ), linkage ); 1098 return new ast::EnumInstType( 1099 typedecl, 1100 buildQualifiers( type ) 1101 ); 1102 } else { 1103 return new ast::EnumInstType( 1104 *type->enumeration.name, 1105 buildQualifiers( type ) 1106 ); 1107 } // if 1108 break; 1109 case TypeData::Aggregate: 1110 if ( type->aggregate.body ) { 1111 ast::AggregateDecl * typedecl = 1112 buildAggregate( type, std::move( attributes ), linkage ); 1113 switch ( type->aggregate.kind ) { 1114 case ast::AggregateDecl::Struct: 1115 case ast::AggregateDecl::Coroutine: 1116 case ast::AggregateDecl::Monitor: 1117 case ast::AggregateDecl::Thread: 1118 return new ast::StructInstType( 1119 strict_dynamic_cast<ast::StructDecl *>( typedecl ), 1120 buildQualifiers( type ) 1121 ); 1122 case ast::AggregateDecl::Union: 1123 return new ast::UnionInstType( 1124 strict_dynamic_cast<ast::UnionDecl *>( typedecl ), 1125 buildQualifiers( type ) 1126 ); 1127 case ast::AggregateDecl::Trait: 1128 assert( false ); 1129 break; 1130 default: 1131 assert( false ); 1132 } // switch 1133 } else { 1134 switch ( type->aggregate.kind ) { 1135 case ast::AggregateDecl::Struct: 1136 case ast::AggregateDecl::Coroutine: 1137 case ast::AggregateDecl::Monitor: 1138 case ast::AggregateDecl::Thread: 1139 return new ast::StructInstType( 1140 *type->aggregate.name, 1141 buildQualifiers( type ) 1142 ); 1143 case ast::AggregateDecl::Union: 1144 return new ast::UnionInstType( 1145 *type->aggregate.name, 1146 buildQualifiers( type ) 1147 ); 1148 case ast::AggregateDecl::Trait: 1149 return new ast::TraitInstType( 1150 *type->aggregate.name, 1151 buildQualifiers( type ) 1152 ); 1153 default: 1154 assert( false ); 1155 } // switch 1156 break; 1157 } // if 1158 break; 1159 default: 859 1160 assert( false ); 860 1161 } // switch 1162 assert( false ); 861 1163 } // buildAggInst 862 1164 863 1165 864 ReferenceToType * buildAggInst( const TypeData * td ) {1166 ast::BaseInstType * buildAggInst( const TypeData * td ) { 865 1167 assert( td->kind == TypeData::AggregateInst ); 866 1168 867 // ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() ); 868 ReferenceToType * ret = nullptr; 1169 ast::BaseInstType * ret = nullptr; 869 1170 TypeData * type = td->aggInst.aggregate; 870 1171 switch ( type->kind ) { 871 case TypeData::Enum: { 872 return new EnumInstType( buildQualifiers( type ), *type->enumeration.name ); 873 } 874 case TypeData::Aggregate: { 875 switch ( type->aggregate.kind ) { 876 case AggregateDecl::Struct: 877 case AggregateDecl::Coroutine: 878 case AggregateDecl::Monitor: 879 case AggregateDecl::Thread: 880 ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name ); 881 break; 882 case AggregateDecl::Union: 883 ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name ); 884 break; 885 case AggregateDecl::Trait: 886 ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name ); 887 break; 888 default: 889 assert( false ); 890 } // switch 891 } 892 break; 893 default: 1172 case TypeData::Enum: 1173 return new ast::EnumInstType( 1174 *type->enumeration.name, 1175 buildQualifiers( type ) 1176 ); 1177 case TypeData::Aggregate: 1178 switch ( type->aggregate.kind ) { 1179 case ast::AggregateDecl::Struct: 1180 case ast::AggregateDecl::Coroutine: 1181 case ast::AggregateDecl::Monitor: 1182 case ast::AggregateDecl::Thread: 1183 ret = new ast::StructInstType( 1184 *type->aggregate.name, 1185 buildQualifiers( type ) 1186 ); 1187 break; 1188 case ast::AggregateDecl::Union: 1189 ret = new ast::UnionInstType( 1190 *type->aggregate.name, 1191 buildQualifiers( type ) 1192 ); 1193 break; 1194 case ast::AggregateDecl::Trait: 1195 ret = new ast::TraitInstType( 1196 *type->aggregate.name, 1197 buildQualifiers( type ) 1198 ); 1199 break; 1200 default: 1201 assert( false ); 1202 } // switch 1203 break; 1204 default: 894 1205 assert( false ); 895 1206 } // switch 896 1207 897 ret->set_hoistType( td->aggInst.hoistType ); 898 buildList( td->aggInst.params, ret->get_parameters() ); 899 buildForall( td->forall, ret->get_forall() ); 1208 ret->hoistType = td->aggInst.hoistType; 1209 buildList( td->aggInst.params, ret->params ); 900 1210 return ret; 901 1211 } // buildAggInst 902 1212 903 1213 904 NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) { 1214 ast::NamedTypeDecl * buildSymbolic( 1215 const TypeData * td, 1216 std::vector<ast::ptr<ast::Attribute>> attributes, 1217 const std::string & name, 1218 ast::Storage::Classes scs, 1219 ast::Linkage::Spec linkage ) { 905 1220 assert( td->kind == TypeData::Symbolic ); 906 NamedTypeDecl * ret;1221 ast::NamedTypeDecl * ret; 907 1222 assert( td->base ); 908 1223 if ( td->symbolic.isTypedef ) { 909 ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage ); 1224 ret = new ast::TypedefDecl( 1225 td->location, 1226 name, 1227 scs, 1228 typebuild( td->base ), 1229 linkage 1230 ); 910 1231 } else { 911 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); 1232 ret = new ast::TypeDecl( 1233 td->location, 1234 name, 1235 scs, 1236 typebuild( td->base ), 1237 ast::TypeDecl::Dtype, 1238 true 1239 ); 912 1240 } // if 913 buildList( td->symbolic.assertions, ret-> get_assertions());914 ret->base->attributes.splice( ret->base->attributes.end(), attributes );1241 buildList( td->symbolic.assertions, ret->assertions ); 1242 splice( ret->base.get_and_mutate()->attributes, attributes ); 915 1243 return ret; 916 1244 } // buildSymbolic 917 1245 918 1246 919 EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1247 ast::EnumDecl * buildEnum( 1248 const TypeData * td, 1249 std::vector<ast::ptr<ast::Attribute>> && attributes, 1250 ast::Linkage::Spec linkage ) { 920 1251 assert( td->kind == TypeData::Enum ); 921 Type * baseType = td->base ? typebuild(td->base) : nullptr; 922 EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType ); 923 buildList( td->enumeration.constants, ret->get_members() ); 924 list< Declaration * >::iterator members = ret->get_members().begin(); 925 ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible; 1252 ast::Type * baseType = td->base ? typebuild(td->base) : nullptr; 1253 ast::EnumDecl * ret = new ast::EnumDecl( 1254 td->location, 1255 *td->enumeration.name, 1256 td->enumeration.typed, 1257 std::move( attributes ), 1258 linkage, 1259 baseType 1260 ); 1261 buildList( td->enumeration.constants, ret->members ); 1262 auto members = ret->members.begin(); 1263 ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible; 926 1264 for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) { 927 1265 if ( cur->enumInLine ) { … … 930 1268 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 931 1269 } else if ( cur->has_enumeratorValue() ) { 932 ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members); 933 member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) ); 1270 ast::Decl * member = members->get_and_mutate(); 1271 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member ); 1272 object->init = new ast::SingleInit( 1273 td->location, 1274 maybeMoveBuild( cur->consume_enumeratorValue() ), 1275 ast::NoConstruct 1276 ); 934 1277 } else if ( !cur->initializer ) { 935 if ( baseType && (!dynamic_cast< BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isWholeNumber())) {1278 if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) { 936 1279 SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." ); 937 1280 } … … 940 1283 // if 941 1284 } // for 942 ret-> set_body( td->enumeration.body );1285 ret->body = td->enumeration.body; 943 1286 return ret; 944 1287 } // buildEnum 945 1288 946 1289 947 TypeInstType * buildSymbolicInst( const TypeData * td ) {1290 ast::TypeInstType * buildSymbolicInst( const TypeData * td ) { 948 1291 assert( td->kind == TypeData::SymbolicInst ); 949 TypeInstType * ret = new TypeInstType( buildQualifiers( td ), *td->symbolic.name, false ); 950 buildList( td->symbolic.actuals, ret->get_parameters() ); 951 buildForall( td->forall, ret->get_forall() ); 1292 ast::TypeInstType * ret = new ast::TypeInstType( 1293 *td->symbolic.name, 1294 ast::TypeDecl::Dtype, 1295 buildQualifiers( td ) 1296 ); 1297 buildList( td->symbolic.actuals, ret->params ); 952 1298 return ret; 953 1299 } // buildSymbolicInst 954 1300 955 1301 956 TupleType * buildTuple( const TypeData * td ) {1302 ast::TupleType * buildTuple( const TypeData * td ) { 957 1303 assert( td->kind == TypeData::Tuple ); 958 std:: list< Type *> types;1304 std::vector<ast::ptr<ast::Type>> types; 959 1305 buildTypeList( td->tuple, types ); 960 TupleType * ret = new TupleType( buildQualifiers( td ), types ); 961 buildForall( td->forall, ret->get_forall() ); 1306 ast::TupleType * ret = new ast::TupleType( 1307 std::move( types ), 1308 buildQualifiers( td ) 1309 ); 962 1310 return ret; 963 1311 } // buildTuple 964 1312 965 1313 966 TypeofType * buildTypeof( const TypeData * td ) {1314 ast::TypeofType * buildTypeof( const TypeData * td ) { 967 1315 assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof ); 968 1316 assert( td->typeexpr ); 969 // assert( td->typeexpr->expr ); 970 return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof }; 1317 return new ast::TypeofType( 1318 td->typeexpr->build(), 1319 td->kind == TypeData::Typeof 1320 ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof, 1321 buildQualifiers( td ) 1322 ); 971 1323 } // buildTypeof 972 1324 973 1325 974 VTableType * buildVtable( const TypeData * td ) {1326 ast::VTableType * buildVtable( const TypeData * td ) { 975 1327 assert( td->base ); 976 return new VTableType{ buildQualifiers( td ), typebuild( td->base ) }; 1328 return new ast::VTableType( 1329 typebuild( td->base ), 1330 buildQualifiers( td ) 1331 ); 977 1332 } // buildVtable 978 1333 979 1334 980 Declaration * buildDecl( const TypeData * td, const string &name, Type::StorageClasses scs, Expression * bitfieldWidth, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec linkage, Expression *asmName, Initializer * init, std::list< Attribute * > attributes ) { 1335 ast::FunctionDecl * buildFunctionDecl( 1336 const TypeData * td, 1337 const string &name, 1338 ast::Storage::Classes scs, 1339 ast::Function::Specs funcSpec, 1340 ast::Linkage::Spec linkage, 1341 ast::Expr * asmName, 1342 std::vector<ast::ptr<ast::Attribute>> && attributes ) { 1343 assert( td->kind == TypeData::Function ); 1344 // For some reason FunctionDecl takes a bool instead of an ArgumentFlag. 1345 bool isVarArgs = !td->function.params || td->function.params->hasEllipsis; 1346 ast::CV::Qualifiers cvq = buildQualifiers( td ); 1347 std::vector<ast::ptr<ast::TypeDecl>> forall; 1348 std::vector<ast::ptr<ast::DeclWithType>> assertions; 1349 std::vector<ast::ptr<ast::DeclWithType>> params; 1350 std::vector<ast::ptr<ast::DeclWithType>> returns; 1351 buildList( td->function.params, params ); 1352 buildForall( td->forall, forall ); 1353 // Functions do not store their assertions there anymore. 1354 for ( ast::ptr<ast::TypeDecl> & type_param : forall ) { 1355 auto mut = type_param.get_and_mutate(); 1356 splice( assertions, mut->assertions ); 1357 } 1358 if ( td->base ) { 1359 switch ( td->base->kind ) { 1360 case TypeData::Tuple: 1361 buildList( td->base->tuple, returns ); 1362 break; 1363 default: 1364 returns.push_back( dynamic_cast<ast::DeclWithType *>( 1365 buildDecl( 1366 td->base, 1367 "", 1368 ast::Storage::Classes(), 1369 (ast::Expr *)nullptr, // bitfieldWidth 1370 ast::Function::Specs(), 1371 ast::Linkage::Cforall, 1372 (ast::Expr *)nullptr // asmName 1373 ) 1374 ) ); 1375 } // switch 1376 } else { 1377 returns.push_back( new ast::ObjectDecl( 1378 td->location, 1379 "", 1380 new ast::BasicType( ast::BasicType::SignedInt ), 1381 (ast::Init *)nullptr, 1382 ast::Storage::Classes(), 1383 ast::Linkage::Cforall 1384 ) ); 1385 } // if 1386 ast::Stmt * stmt = maybeBuild( td->function.body ); 1387 ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt ); 1388 ast::FunctionDecl * decl = new ast::FunctionDecl( td->location, 1389 name, 1390 std::move( forall ), 1391 std::move( assertions ), 1392 std::move( params ), 1393 std::move( returns ), 1394 body, 1395 scs, 1396 linkage, 1397 std::move( attributes ), 1398 funcSpec, 1399 (isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1400 ); 1401 buildList( td->function.withExprs, decl->withExprs ); 1402 decl->asmName = asmName; 1403 // This may be redundant on a declaration. 1404 decl->type.get_and_mutate()->qualifiers = cvq; 1405 return decl; 1406 } // buildFunctionDecl 1407 1408 1409 ast::Decl * buildDecl( 1410 const TypeData * td, 1411 const string &name, 1412 ast::Storage::Classes scs, 1413 ast::Expr * bitfieldWidth, 1414 ast::Function::Specs funcSpec, 1415 ast::Linkage::Spec linkage, 1416 ast::Expr * asmName, 1417 ast::Init * init, 1418 std::vector<ast::ptr<ast::Attribute>> && attributes ) { 981 1419 if ( td->kind == TypeData::Function ) { 982 1420 if ( td->function.idList ) { // KR function ? … … 984 1422 } // if 985 1423 986 FunctionDecl * decl; 987 Statement * stmt = maybeBuild<Statement>( td->function.body ); 988 CompoundStmt * body = dynamic_cast< CompoundStmt * >( stmt ); 989 decl = new FunctionDecl( name, scs, linkage, buildFunction( td ), body, attributes, funcSpec ); 990 buildList( td->function.withExprs, decl->withExprs ); 991 return decl->set_asmName( asmName ); 1424 return buildFunctionDecl( 1425 td, name, scs, funcSpec, linkage, 1426 asmName, std::move( attributes ) ); 992 1427 } else if ( td->kind == TypeData::Aggregate ) { 993 return buildAggregate( td, attributes, linkage );1428 return buildAggregate( td, std::move( attributes ), linkage ); 994 1429 } else if ( td->kind == TypeData::Enum ) { 995 return buildEnum( td, attributes, linkage );1430 return buildEnum( td, std::move( attributes ), linkage ); 996 1431 } else if ( td->kind == TypeData::Symbolic ) { 997 return buildSymbolic( td, attributes, name, scs, linkage );1432 return buildSymbolic( td, std::move( attributes ), name, scs, linkage ); 998 1433 } else { 999 return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName ); 1434 auto ret = new ast::ObjectDecl( td->location, 1435 name, 1436 typebuild( td ), 1437 init, 1438 scs, 1439 linkage, 1440 bitfieldWidth, 1441 std::move( attributes ) 1442 ); 1443 ret->asmName = asmName; 1444 return ret; 1000 1445 } // if 1001 1446 return nullptr; … … 1003 1448 1004 1449 1005 FunctionType * buildFunction( const TypeData * td ) {1450 ast::FunctionType * buildFunctionType( const TypeData * td ) { 1006 1451 assert( td->kind == TypeData::Function ); 1007 FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis ); 1008 buildList( td->function.params, ft->parameters ); 1452 ast::FunctionType * ft = new ast::FunctionType( 1453 ( !td->function.params || td->function.params->hasEllipsis ) 1454 ? ast::VariableArgs : ast::FixedArgs, 1455 buildQualifiers( td ) 1456 ); 1457 buildTypeList( td->function.params, ft->params ); 1009 1458 buildForall( td->forall, ft->forall ); 1010 1459 if ( td->base ) { 1011 1460 switch ( td->base->kind ) { 1012 case TypeData::Tuple:1013 build List( td->base->tuple, ft->returnVals );1461 case TypeData::Tuple: 1462 buildTypeList( td->base->tuple, ft->returns ); 1014 1463 break; 1015 default: 1016 ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) ); 1464 default: 1465 ft->returns.push_back( typebuild( td->base ) ); 1466 break; 1017 1467 } // switch 1018 1468 } else { 1019 ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) ); 1469 ft->returns.push_back( 1470 new ast::BasicType( ast::BasicType::SignedInt ) ); 1020 1471 } // if 1021 1472 return ft; 1022 } // buildFunction 1473 } // buildFunctionType 1023 1474 1024 1475 … … 1051 1502 param->type = decl->type; // set copy declaration type to parameter type 1052 1503 decl->type = nullptr; // reset declaration type 1053 param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter 1504 // Copy and reset attributes from declaration to parameter: 1505 splice( param->attributes, decl->attributes ); 1054 1506 } // if 1055 1507 } // for -
src/Parser/TypeData.h
r34b4268 r24d6572 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 15:18:36 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 10 22:18:49 202213 // Update Count : 20 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 1 10:44:00 2023 13 // Update Count : 206 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <iosfwd> // for ostream19 #include <list> // for list20 #include <string> // for string18 #include <iosfwd> // for ostream 19 #include <list> // for list 20 #include <string> // for string 21 21 22 #include "ParseNode.h" // for DeclarationNode, DeclarationNode::Ag... 23 #include "SynTree/LinkageSpec.h" // for Spec 24 #include "SynTree/Type.h" // for Type, ReferenceToType (ptr only) 25 #include "SynTree/SynTree.h" // for Visitor Nodes 22 #include "AST/Type.hpp" // for Type 23 #include "DeclarationNode.h" // for DeclarationNode 26 24 27 25 struct TypeData { … … 30 28 31 29 struct Aggregate_t { 32 AggregateDecl::Aggregate kind;30 ast::AggregateDecl::Aggregate kind; 33 31 const std::string * name = nullptr; 34 32 DeclarationNode * params = nullptr; … … 37 35 bool body; 38 36 bool anon; 39 40 37 bool tagged; 41 38 const std::string * parent = nullptr; … … 94 91 DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType; 95 92 96 Type::Qualifiers qualifiers;93 ast::CV::Qualifiers qualifiers; 97 94 DeclarationNode * forall = nullptr; 98 95 … … 115 112 }; 116 113 117 Type * typebuild( const TypeData * );114 ast::Type * typebuild( const TypeData * ); 118 115 TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true ); 119 Type::Qualifiers buildQualifiers( const TypeData * td ); 120 Type * buildBasicType( const TypeData * ); 121 PointerType * buildPointer( const TypeData * ); 122 ArrayType * buildArray( const TypeData * ); 123 ReferenceType * buildReference( const TypeData * ); 124 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > ); 125 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ); 126 ReferenceToType * buildAggInst( const TypeData * ); 127 TypeDecl * buildVariable( const TypeData * ); 128 EnumDecl * buildEnum( const TypeData *, std::list< Attribute * >, LinkageSpec::Spec ); 129 TypeInstType * buildSymbolicInst( const TypeData * ); 130 TupleType * buildTuple( const TypeData * ); 131 TypeofType * buildTypeof( const TypeData * ); 132 VTableType * buildVtable( const TypeData * ); 133 Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName, 134 Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() ); 135 FunctionType * buildFunction( const TypeData * ); 136 Declaration * addEnumBase( Declaration *, const TypeData * ); 116 ast::CV::Qualifiers buildQualifiers( const TypeData * td ); 117 ast::Type * buildBasicType( const TypeData * ); 118 ast::PointerType * buildPointer( const TypeData * ); 119 ast::ArrayType * buildArray( const TypeData * ); 120 ast::ReferenceType * buildReference( const TypeData * ); 121 ast::AggregateDecl * buildAggregate( const TypeData *, std::vector<ast::ptr<ast::Attribute>> ); 122 ast::BaseInstType * buildComAggInst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> && attributes, ast::Linkage::Spec linkage ); 123 ast::BaseInstType * buildAggInst( const TypeData * ); 124 ast::TypeDecl * buildVariable( const TypeData * ); 125 ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec ); 126 ast::TypeInstType * buildSymbolicInst( const TypeData * ); 127 ast::TupleType * buildTuple( const TypeData * ); 128 ast::TypeofType * buildTypeof( const TypeData * ); 129 ast::VTableType * buildVtable( const TypeData * ); 130 ast::Decl * buildDecl( 131 const TypeData *, const std::string &, ast::Storage::Classes, ast::Expr *, 132 ast::Function::Specs funcSpec, ast::Linkage::Spec, ast::Expr * asmName, 133 ast::Init * init = nullptr, std::vector<ast::ptr<ast::Attribute>> && attributes = std::vector<ast::ptr<ast::Attribute>>() ); 134 ast::FunctionType * buildFunctionType( const TypeData * ); 135 ast::Decl * addEnumBase( Declaration *, const TypeData * ); 137 136 void buildKRFunction( const TypeData::Function_t & function ); 138 137 -
src/Parser/TypedefTable.cc
r34b4268 r24d6572 16 16 17 17 #include "TypedefTable.h" 18 #include <cassert> // for assert 19 #include <iostream> 18 19 #include <cassert> // for assert 20 #include <string> // for string 21 #include <iostream> // for iostream 22 23 #include "ExpressionNode.h" // for LabelNode 24 #include "ParserTypes.h" // for Token 25 #include "StatementNode.h" // for CondCtl, ForCtrl 26 // This (generated) header must come late as it is missing includes. 27 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname 28 20 29 using namespace std; 21 30 22 31 #if 0 23 32 #define debugPrint( code ) code 33 34 static const char *kindName( int kind ) { 35 switch ( kind ) { 36 case IDENTIFIER: return "identifier"; 37 case TYPEDIMname: return "typedim"; 38 case TYPEDEFname: return "typedef"; 39 case TYPEGENname: return "typegen"; 40 default: 41 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl; 42 abort(); 43 } // switch 44 } // kindName 24 45 #else 25 46 #define debugPrint( code ) 26 47 #endif 27 28 using namespace std; // string, iostream29 30 debugPrint(31 static const char *kindName( int kind ) {32 switch ( kind ) {33 case IDENTIFIER: return "identifier";34 case TYPEDIMname: return "typedim";35 case TYPEDEFname: return "typedef";36 case TYPEGENname: return "typegen";37 default:38 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;39 abort();40 } // switch41 } // kindName42 );43 48 44 49 TypedefTable::~TypedefTable() { … … 78 83 typedefTable.addToEnclosingScope( name, kind, "MTD" ); 79 84 } // if 85 } // TypedefTable::makeTypedef 86 87 void TypedefTable::makeTypedef( const string & name ) { 88 return makeTypedef( name, TYPEDEFname ); 80 89 } // TypedefTable::makeTypedef 81 90 -
src/Parser/TypedefTable.h
r34b4268 r24d6572 19 19 20 20 #include "Common/ScopedMap.h" // for ScopedMap 21 #include "ParserTypes.h"22 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname23 21 24 22 class TypedefTable { 25 23 struct Note { size_t level; bool forall; }; 26 24 typedef ScopedMap< std::string, int, Note > KindTable; 27 KindTable kindTable; 25 KindTable kindTable; 28 26 unsigned int level = 0; 29 27 public: … … 33 31 bool existsCurr( const std::string & identifier ) const; 34 32 int isKind( const std::string & identifier ) const; 35 void makeTypedef( const std::string & name, int kind = TYPEDEFname ); 33 void makeTypedef( const std::string & name, int kind ); 34 void makeTypedef( const std::string & name ); 36 35 void addToScope( const std::string & identifier, int kind, const char * ); 37 36 void addToEnclosingScope( const std::string & identifier, int kind, const char * ); -
src/Parser/lex.ll
r34b4268 r24d6572 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : T hu Oct 13 20:46:04 202213 * Update Count : 76 412 * Last Modified On : Tue May 2 08:45:21 2023 13 * Update Count : 769 14 14 */ 15 15 … … 23 23 // line-number directives) and C/C++ style comments, which are ignored. 24 24 25 // **************************** Includes and Defines ****************************25 // *************************** Includes and Defines **************************** 26 26 27 27 #ifdef __clang__ … … 44 44 45 45 #include "config.h" // configure info 46 #include "DeclarationNode.h" // for DeclarationNode 47 #include "ExpressionNode.h" // for LabelNode 48 #include "InitializerNode.h" // for InitializerNode 46 49 #include "ParseNode.h" 50 #include "ParserTypes.h" // for Token 51 #include "StatementNode.h" // for CondCtl, ForCtrl 47 52 #include "TypedefTable.h" 53 // This (generated) header must come late as it is missing includes. 54 #include "parser.hh" // generated info 48 55 49 56 string * build_postfix_name( string * name ); … … 214 221 __alignof { KEYWORD_RETURN(ALIGNOF); } // GCC 215 222 __alignof__ { KEYWORD_RETURN(ALIGNOF); } // GCC 223 and { QKEYWORD_RETURN(WAND); } // CFA 216 224 asm { KEYWORD_RETURN(ASM); } 217 225 __asm { KEYWORD_RETURN(ASM); } // GCC … … 250 258 enable { KEYWORD_RETURN(ENABLE); } // CFA 251 259 enum { KEYWORD_RETURN(ENUM); } 260 exception { KEYWORD_RETURN(EXCEPTION); } // CFA 252 261 __extension__ { KEYWORD_RETURN(EXTENSION); } // GCC 253 exception { KEYWORD_RETURN(EXCEPTION); } // CFA254 262 extern { KEYWORD_RETURN(EXTERN); } 255 263 fallthrough { KEYWORD_RETURN(FALLTHROUGH); } // CFA … … 340 348 vtable { KEYWORD_RETURN(VTABLE); } // CFA 341 349 waitfor { KEYWORD_RETURN(WAITFOR); } // CFA 350 waituntil { KEYWORD_RETURN(WAITUNTIL); } // CFA 342 351 when { KEYWORD_RETURN(WHEN); } // CFA 343 352 while { KEYWORD_RETURN(WHILE); } … … 502 511 SemanticErrorThrow = true; 503 512 cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1 504 << ": " << ErrorHelpers::error_str() << errmsg << " attoken \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;513 << ": " << ErrorHelpers::error_str() << errmsg << " before token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl; 505 514 } 506 515 -
src/Parser/module.mk
r34b4268 r24d6572 21 21 SRC += \ 22 22 Parser/DeclarationNode.cc \ 23 Parser/DeclarationNode.h \ 23 24 Parser/ExpressionNode.cc \ 25 Parser/ExpressionNode.h \ 24 26 Parser/InitializerNode.cc \ 27 Parser/InitializerNode.h \ 25 28 Parser/lex.ll \ 26 29 Parser/ParseNode.cc \ … … 30 33 Parser/parserutility.cc \ 31 34 Parser/parserutility.h \ 35 Parser/RunParser.cpp \ 36 Parser/RunParser.hpp \ 32 37 Parser/StatementNode.cc \ 38 Parser/StatementNode.h \ 33 39 Parser/TypeData.cc \ 34 40 Parser/TypeData.h \ -
src/Parser/parser.yy
r34b4268 r24d6572 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Nov 21 22:34:30 202213 // Update Count : 584812 // Last Modified On : Wed Apr 26 16:45:37 2023 13 // Update Count : 6330 14 14 // 15 15 … … 44 44 45 45 #include <cstdio> 46 #include <sstream> 46 47 #include <stack> 47 48 using namespace std; 48 49 49 #include "SynTree/Declaration.h" 50 #include "ParseNode.h" 50 #include "SynTree/Type.h" // for Type 51 #include "DeclarationNode.h" // for DeclarationNode, ... 52 #include "ExpressionNode.h" // for ExpressionNode, ... 53 #include "InitializerNode.h" // for InitializerNode, ... 54 #include "ParserTypes.h" 55 #include "StatementNode.h" // for build_... 51 56 #include "TypedefTable.h" 52 57 #include "TypeData.h" 53 #include "SynTree/LinkageSpec.h"54 58 #include "Common/SemanticError.h" // error_str 55 59 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 56 60 57 #include "SynTree/Attribute.h" // for Attribute61 #include "SynTree/Attribute.h" // for Attribute 58 62 59 63 // lex uses __null in a boolean context, it's fine. … … 63 67 64 68 extern DeclarationNode * parseTree; 65 extern LinkageSpec::Spec linkage;69 extern ast::Linkage::Spec linkage; 66 70 extern TypedefTable typedefTable; 67 71 68 stack< LinkageSpec::Spec> linkageStack;72 stack<ast::Linkage::Spec> linkageStack; 69 73 70 74 bool appendStr( string & to, string & from ) { … … 199 203 } // fieldDecl 200 204 201 #define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )202 #define NEW_ONE new ExpressionNode( build_constantInteger( *new string( "1" ) ) )205 #define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) ) 206 #define NEW_ONE new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) ) 203 207 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 204 208 #define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body." … … 206 210 #define MISSING_HIGH "Missing high value for down-to range so index is uninitialized." 207 211 208 ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 212 static ForCtrl * makeForCtrl( 213 const CodeLocation & location, 214 DeclarationNode * init, 215 enum OperKinds compop, 216 ExpressionNode * comp, 217 ExpressionNode * inc ) { 218 // Wrap both comp/inc if they are non-null. 219 if ( comp ) comp = new ExpressionNode( build_binary_val( location, 220 compop, 221 new ExpressionNode( build_varref( location, new string( *init->name ) ) ), 222 comp ) ); 223 if ( inc ) inc = new ExpressionNode( build_binary_val( location, 224 // choose += or -= for upto/downto 225 compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn, 226 new ExpressionNode( build_varref( location, new string( *init->name ) ) ), 227 inc ) ); 228 // The StatementNode call frees init->name, it must happen later. 229 return new ForCtrl( new StatementNode( init ), comp, inc ); 230 } 231 232 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 209 233 if ( index->initializer ) { 210 234 SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); … … 213 237 SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." ); 214 238 } // if 215 return new ForCtrl( index->addInitializer( new InitializerNode( start ) ), 216 // NULL comp/inc => leave blank 217 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr, 218 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 219 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr ); 239 DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) ); 240 return makeForCtrl( location, initDecl, compop, comp, inc ); 220 241 } // forCtrl 221 242 222 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {223 ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());224 if ( constant && (constant-> get_constant()->get_value() == "0" || constant->get_constant()->get_value()== "1") ) {225 type = new ExpressionNode( new CastExpr( maybeMoveBuild<Expression>(type), new BasicType( Type::Qualifiers(),BasicType::SignedInt ) ) );243 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 244 ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get()); 245 if ( constant && (constant->rep == "0" || constant->rep == "1") ) { 246 type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) ); 226 247 } // if 227 // type = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__for_control_index_constraints__" ) ) ), type ) ); 228 return new ForCtrl( 229 distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ), 230 // NULL comp/inc => leave blank 231 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr, 232 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 233 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr ); 248 DeclarationNode * initDecl = distAttr( 249 DeclarationNode::newTypeof( type, true ), 250 DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) 251 ); 252 return makeForCtrl( location, initDecl, compop, comp, inc ); 234 253 } // forCtrl 235 254 236 ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {237 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {238 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );239 } else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {240 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1) ) {241 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );255 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 256 if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) { 257 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 258 } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) { 259 if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) { 260 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 242 261 } else { 243 262 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr; … … 281 300 %union { 282 301 Token tok; 283 ParseNode * pn; 284 ExpressionNode * en; 302 ExpressionNode * expr; 285 303 DeclarationNode * decl; 286 AggregateDecl::Aggregate aggKey; 287 TypeDecl::Kind tclass; 288 StatementNode * sn; 289 WaitForStmt * wfs; 290 Expression * constant; 304 ast::AggregateDecl::Aggregate aggKey; 305 ast::TypeDecl::Kind tclass; 306 StatementNode * stmt; 307 ClauseNode * clause; 308 ast::WaitForStmt * wfs; 309 ast::WaitUntilStmt::ClauseNode * wucn; 291 310 CondCtl * ifctl; 292 ForCtrl * fctl; 293 OperKinds compop; 294 LabelNode * label; 295 InitializerNode * in; 296 OperKinds op; 311 ForCtrl * forctl; 312 LabelNode * labels; 313 InitializerNode * init; 314 OperKinds oper; 297 315 std::string * str; 298 bool flag;299 EnumHiding hide;300 CatchStmt::Kind catch_kind;301 GenericExpr * genexpr;316 bool is_volatile; 317 EnumHiding enum_hiding; 318 ast::ExceptionKind except_kind; 319 ast::GenericExpr * genexpr; 302 320 } 303 321 304 // ************************* TERMINAL TOKENS ********************************322 // ************************ TERMINAL TOKENS ******************************** 305 323 306 324 // keywords … … 331 349 %token ATTRIBUTE EXTENSION // GCC 332 350 %token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN 333 %token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR // CFA351 %token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR WAITUNTIL // CFA 334 352 %token DISABLE ENABLE TRY THROW THROWRESUME AT // CFA 335 353 %token ASM // C99, extension ISO/IEC 9899:1999 Section J.5.10(1) … … 337 355 338 356 // names and constants: lexer differentiates between identifier and typedef names 339 %token<tok> IDENTIFIER QUOTED_IDENTIFIERTYPEDIMname TYPEDEFname TYPEGENname340 %token<tok> TIMEOUT W ORCATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA357 %token<tok> IDENTIFIER TYPEDIMname TYPEDEFname TYPEGENname 358 %token<tok> TIMEOUT WAND WOR CATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA 341 359 %token<tok> INTEGERconstant CHARACTERconstant STRINGliteral 342 360 %token<tok> DIRECTIVE … … 364 382 %type<tok> identifier identifier_at identifier_or_type_name attr_name 365 383 %type<tok> quasi_keyword 366 %type< constant> string_literal384 %type<expr> string_literal 367 385 %type<str> string_literal_list 368 386 369 %type< hide> hide_opt visible_hide_opt387 %type<enum_hiding> hide_opt visible_hide_opt 370 388 371 389 // expressions 372 %type<e n> constant373 %type<e n> tuple tuple_expression_list374 %type<op > ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator375 %type<e n> primary_expression postfix_expression unary_expression376 %type<e n> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression377 %type<e n> shift_expression relational_expression equality_expression378 %type<e n> AND_expression exclusive_OR_expression inclusive_OR_expression379 %type<e n> logical_AND_expression logical_OR_expression380 %type<e n> conditional_expression constant_expression assignment_expression assignment_expression_opt381 %type<e n> comma_expression comma_expression_opt382 %type<e n> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt390 %type<expr> constant 391 %type<expr> tuple tuple_expression_list 392 %type<oper> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator 393 %type<expr> primary_expression postfix_expression unary_expression 394 %type<expr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression 395 %type<expr> shift_expression relational_expression equality_expression 396 %type<expr> AND_expression exclusive_OR_expression inclusive_OR_expression 397 %type<expr> logical_AND_expression logical_OR_expression 398 %type<expr> conditional_expression constant_expression assignment_expression assignment_expression_opt 399 %type<expr> comma_expression comma_expression_opt 400 %type<expr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt 383 401 %type<ifctl> conditional_declaration 384 %type<f ctl> for_control_expression for_control_expression_list385 %type< compop> upupeq updown updowneq downupdowneq386 %type<e n> subrange402 %type<forctl> for_control_expression for_control_expression_list 403 %type<oper> upupeq updown updowneq downupdowneq 404 %type<expr> subrange 387 405 %type<decl> asm_name_opt 388 %type<e n> asm_operands_opt asm_operands_list asm_operand389 %type<label > label_list390 %type<e n> asm_clobbers_list_opt391 %type< flag> asm_volatile_opt392 %type<e n> handler_predicate_opt406 %type<expr> asm_operands_opt asm_operands_list asm_operand 407 %type<labels> label_list 408 %type<expr> asm_clobbers_list_opt 409 %type<is_volatile> asm_volatile_opt 410 %type<expr> handler_predicate_opt 393 411 %type<genexpr> generic_association generic_assoc_list 394 412 395 413 // statements 396 %type<sn> statement labeled_statement compound_statement 397 %type<sn> statement_decl statement_decl_list statement_list_nodecl 398 %type<sn> selection_statement if_statement 399 %type<sn> switch_clause_list_opt switch_clause_list 400 %type<en> case_value 401 %type<sn> case_clause case_value_list case_label case_label_list 402 %type<sn> iteration_statement jump_statement 403 %type<sn> expression_statement asm_statement 404 %type<sn> with_statement 405 %type<en> with_clause_opt 406 %type<sn> exception_statement handler_clause finally_clause 407 %type<catch_kind> handler_key 408 %type<sn> mutex_statement 409 %type<en> when_clause when_clause_opt waitfor timeout 410 %type<sn> waitfor_statement 411 %type<wfs> waitfor_clause 414 %type<stmt> statement labeled_statement compound_statement 415 %type<stmt> statement_decl statement_decl_list statement_list_nodecl 416 %type<stmt> selection_statement if_statement 417 %type<clause> switch_clause_list_opt switch_clause_list 418 %type<expr> case_value 419 %type<clause> case_clause case_value_list case_label case_label_list 420 %type<stmt> iteration_statement jump_statement 421 %type<stmt> expression_statement asm_statement 422 %type<stmt> with_statement 423 %type<expr> with_clause_opt 424 %type<stmt> exception_statement 425 %type<clause> handler_clause finally_clause 426 %type<except_kind> handler_key 427 %type<stmt> mutex_statement 428 %type<expr> when_clause when_clause_opt waitfor waituntil timeout 429 %type<stmt> waitfor_statement waituntil_statement 430 %type<wfs> wor_waitfor_clause 431 %type<wucn> waituntil_clause wand_waituntil_clause wor_waituntil_clause 412 432 413 433 // declarations … … 421 441 %type<decl> assertion assertion_list assertion_list_opt 422 442 423 %type<e n> bit_subrange_size_opt bit_subrange_size443 %type<expr> bit_subrange_size_opt bit_subrange_size 424 444 425 445 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 434 454 435 455 %type<decl> enumerator_list enum_type enum_type_nobody 436 %type<in > enumerator_value_opt456 %type<init> enumerator_value_opt 437 457 438 458 %type<decl> external_definition external_definition_list external_definition_list_opt … … 441 461 442 462 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract 443 %type<e n> field field_name_list field_name fraction_constants_opt463 %type<expr> field field_name_list field_name fraction_constants_opt 444 464 445 465 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 482 502 %type<decl> typedef_name typedef_declaration typedef_expression 483 503 484 %type<decl> variable_type_redeclarator type_ptr type_array type_function 504 %type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function 505 %type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr 485 506 486 507 %type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function … … 489 510 %type<decl> type_parameter type_parameter_list type_initializer_opt 490 511 491 %type<e n> type_parameters_opt type_list array_type_list512 %type<expr> type_parameters_opt type_list array_type_list 492 513 493 514 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list … … 500 521 501 522 // initializers 502 %type<in > initializer initializer_list_opt initializer_opt523 %type<init> initializer initializer_list_opt initializer_opt 503 524 504 525 // designators 505 %type<e n> designator designator_list designation526 %type<expr> designator designator_list designation 506 527 507 528 … … 512 533 // Similar issues exit with the waitfor statement. 513 534 514 // Order of these lines matters (low-to-high precedence). THEN is left associative over W OR/TIMEOUT/ELSE, WOR is left515 // associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.535 // Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR 536 // is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE. 516 537 %precedence THEN // rule precedence for IF/WAITFOR statement 538 %precedence ANDAND // token precedence for start of WAND in WAITFOR statement 539 %precedence WAND // token precedence for start of WAND in WAITFOR statement 540 %precedence OROR // token precedence for start of WOR in WAITFOR statement 517 541 %precedence WOR // token precedence for start of WOR in WAITFOR statement 518 542 %precedence TIMEOUT // token precedence for start of TIMEOUT in WAITFOR statement … … 592 616 constant: 593 617 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant". 594 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( *$1 ) ); }595 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }596 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }597 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }598 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( *$1 ) ); }618 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); } 619 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 620 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 621 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 622 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); } 599 623 ; 600 624 601 625 quasi_keyword: // CFA 602 626 TIMEOUT 627 | WAND 603 628 | WOR 604 629 | CATCH … … 621 646 622 647 string_literal: 623 string_literal_list { $$ = build_constantStr( *$1); }648 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); } 624 649 ; 625 650 … … 638 663 primary_expression: 639 664 IDENTIFIER // typedef name cannot be used as a variable name 640 { $$ = new ExpressionNode( build_varref( $1 ) ); }665 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 641 666 | quasi_keyword 642 { $$ = new ExpressionNode( build_varref( $1 ) ); }667 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 643 668 | TYPEDIMname // CFA, generic length argument 644 669 // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); } 645 670 // { $$ = new ExpressionNode( build_varref( $1 ) ); } 646 { $$ = new ExpressionNode( build_dimensionref( $1 ) ); }671 { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); } 647 672 | tuple 648 673 | '(' comma_expression ')' 649 674 { $$ = $2; } 650 675 | '(' compound_statement ')' // GCC, lambda expression 651 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }676 { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); } 652 677 | type_name '.' identifier // CFA, nested type 653 { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref($3 ) ) ); }678 { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 654 679 | type_name '.' '[' field_name_list ']' // CFA, nested type / tuple field selector 655 680 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; } … … 657 682 { 658 683 // add the missing control expression to the GenericExpr and return it 659 $5->control = maybeMoveBuild <Expression>( $3 );684 $5->control = maybeMoveBuild( $3 ); 660 685 $$ = new ExpressionNode( $5 ); 661 686 } … … 683 708 { 684 709 // steal the association node from the singleton and delete the wrapper 685 $1->associations.splice($1->associations.end(), $3->associations); 710 assert( 1 == $3->associations.size() ); 711 $1->associations.push_back( $3->associations.front() ); 686 712 delete $3; 687 713 $$ = $1; … … 693 719 { 694 720 // create a GenericExpr wrapper with one association pair 695 $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } );721 $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } ); 696 722 } 697 723 | DEFAULT ':' assignment_expression 698 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); }724 { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); } 699 725 ; 700 726 … … 705 731 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts. 706 732 // Current: Commas in subscripts make tuples. 707 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple((ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }733 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); } 708 734 | postfix_expression '[' assignment_expression ']' 709 735 // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a … … 711 737 // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is 712 738 // equivalent to the old x[i,j]. 713 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }739 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 714 740 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a] 715 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 716 742 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 717 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }743 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 718 744 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 719 745 { 720 746 Token fn; 721 747 fn.str = new std::string( "?{}" ); // location undefined - use location of '{'? 722 $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref(fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );748 $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) ); 723 749 } 724 750 | postfix_expression '(' argument_expression_list_opt ')' 725 { $$ = new ExpressionNode( build_func( $1, $3 ) ); }751 { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); } 726 752 | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')' 727 753 // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; } 728 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(new string( "__builtin_va_arg") ) ),754 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ), 729 755 (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); } 730 756 | postfix_expression '`' identifier // CFA, postfix call 731 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(build_postfix_name( $3 ) ) ), $1 ) ); }757 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 732 758 | constant '`' identifier // CFA, postfix call 733 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(build_postfix_name( $3 ) ) ), $1 ) ); }759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 734 760 | string_literal '`' identifier // CFA, postfix call 735 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 )) ); }761 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 736 762 | postfix_expression '.' identifier 737 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref($3 ) ) ); }763 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 738 764 | postfix_expression '.' INTEGERconstant // CFA, tuple index 739 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger(*$3 ) ) ); }765 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); } 740 766 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index 741 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant(*$2 ) ) ); }767 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); } 742 768 | postfix_expression '.' '[' field_name_list ']' // CFA, tuple field selector 743 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple($4 ) ) ); }769 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 744 770 | postfix_expression '.' aggregate_control 745 { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }771 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); } 746 772 | postfix_expression ARROW identifier 747 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref($3 ) ) ); }773 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 748 774 | postfix_expression ARROW INTEGERconstant // CFA, tuple index 749 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger(*$3 ) ) ); }775 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); } 750 776 | postfix_expression ARROW '[' field_name_list ']' // CFA, tuple field selector 751 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple($4 ) ) ); }777 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 752 778 | postfix_expression ICR 753 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::IncrPost, $1 ) ); }779 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); } 754 780 | postfix_expression DECR 755 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::DecrPost, $1 ) ); }781 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); } 756 782 | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal 757 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }783 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); } 758 784 | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal 759 { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }785 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); } 760 786 | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call 761 787 { 762 788 Token fn; 763 789 fn.str = new string( "^?{}" ); // location undefined 764 $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );790 $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) ); 765 791 } 766 792 ; … … 781 807 '@' // CFA, default parameter 782 808 { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; } 783 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }809 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); } 784 810 | assignment_expression 785 811 ; … … 793 819 field_name 794 820 | FLOATING_DECIMALconstant field 795 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }821 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); } 796 822 | FLOATING_DECIMALconstant '[' field_name_list ']' 797 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple($3 ) ) ); }823 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); } 798 824 | field_name '.' field 799 { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }825 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); } 800 826 | field_name '.' '[' field_name_list ']' 801 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple($4 ) ) ); }827 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 802 828 | field_name ARROW field 803 { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }829 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); } 804 830 | field_name ARROW '[' field_name_list ']' 805 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple($4 ) ) ); }831 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 806 832 ; 807 833 808 834 field_name: 809 835 INTEGERconstant fraction_constants_opt 810 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger(*$1 ), $2 ) ); }836 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); } 811 837 | FLOATINGconstant fraction_constants_opt 812 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant(*$1 ), $2 ) ); }838 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); } 813 839 | identifier_at fraction_constants_opt // CFA, allow anonymous fields 814 840 { 815 $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref($1 ), $2 ) );841 $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) ); 816 842 } 817 843 ; … … 822 848 | fraction_constants_opt FLOATING_FRACTIONconstant 823 849 { 824 Expression * constant = build_field_name_FLOATING_FRACTIONconstant(*$2 );825 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1,constant ) ) : new ExpressionNode( constant );850 ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ); 851 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant ); 826 852 } 827 853 ; … … 833 859 | constant 834 860 | string_literal 835 { $$ = new ExpressionNode( $1 ); }861 { $$ = $1; } 836 862 | EXTENSION cast_expression // GCC 837 863 { $$ = $2->set_extension( true ); } … … 842 868 { 843 869 switch ( $1 ) { 844 case OperKinds::AddressOf:845 $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) );870 case OperKinds::AddressOf: 871 $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ); 846 872 break; 847 case OperKinds::PointTo:848 $$ = new ExpressionNode( build_unary_val( $1, $2 ) );873 case OperKinds::PointTo: 874 $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); 849 875 break; 850 case OperKinds::And:851 $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) );876 case OperKinds::And: 877 $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) ); 852 878 break; 853 default:879 default: 854 880 assert( false ); 855 881 } 856 882 } 857 883 | unary_operator cast_expression 858 { $$ = new ExpressionNode( build_unary_val($1, $2 ) ); }884 { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); } 859 885 | ICR unary_expression 860 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::Incr, $2 ) ); }886 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); } 861 887 | DECR unary_expression 862 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::Decr, $2 ) ); }888 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); } 863 889 | SIZEOF unary_expression 864 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }890 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); } 865 891 | SIZEOF '(' type_no_function ')' 866 { $$ = new ExpressionNode( new SizeofExpr(maybeMoveBuildType( $3 ) ) ); }892 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); } 867 893 | ALIGNOF unary_expression // GCC, variable alignment 868 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }894 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); } 869 895 | ALIGNOF '(' type_no_function ')' // GCC, type alignment 870 { $$ = new ExpressionNode( new AlignofExpr(maybeMoveBuildType( $3 ) ) ); }896 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); } 871 897 | OFFSETOF '(' type_no_function ',' identifier ')' 872 { $$ = new ExpressionNode( build_offsetOf( $3, build_varref($5 ) ) ); }898 { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); } 873 899 | TYPEID '(' type_no_function ')' 874 900 { … … 895 921 unary_expression 896 922 | '(' type_no_function ')' cast_expression 897 { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }923 { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); } 898 924 | '(' aggregate_control '&' ')' cast_expression // CFA 899 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }925 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); } 900 926 | '(' aggregate_control '*' ')' cast_expression // CFA 901 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }927 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); } 902 928 | '(' VIRTUAL ')' cast_expression // CFA 903 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); }929 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); } 904 930 | '(' VIRTUAL type_no_function ')' cast_expression // CFA 905 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); }931 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); } 906 932 | '(' RETURN type_no_function ')' cast_expression // CFA 907 { $$ = new ExpressionNode( build_cast( $3, $5,CastExpr::Return ) ); }933 { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); } 908 934 | '(' COERCE type_no_function ')' cast_expression // CFA 909 935 { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; } … … 911 937 { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; } 912 938 // | '(' type_no_function ')' tuple 913 // { $$ = new ExpressionNode( build_cast($2, $4 ) ); }939 // { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); } 914 940 ; 915 941 … … 929 955 cast_expression 930 956 | exponential_expression '\\' cast_expression 931 { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }957 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); } 932 958 ; 933 959 … … 935 961 exponential_expression 936 962 | multiplicative_expression '*' exponential_expression 937 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }963 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); } 938 964 | multiplicative_expression '/' exponential_expression 939 { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }965 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); } 940 966 | multiplicative_expression '%' exponential_expression 941 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }967 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); } 942 968 ; 943 969 … … 945 971 multiplicative_expression 946 972 | additive_expression '+' multiplicative_expression 947 { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }973 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); } 948 974 | additive_expression '-' multiplicative_expression 949 { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }975 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); } 950 976 ; 951 977 … … 953 979 additive_expression 954 980 | shift_expression LS additive_expression 955 { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }981 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); } 956 982 | shift_expression RS additive_expression 957 { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }983 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); } 958 984 ; 959 985 … … 961 987 shift_expression 962 988 | relational_expression '<' shift_expression 963 { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }989 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); } 964 990 | relational_expression '>' shift_expression 965 { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }991 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); } 966 992 | relational_expression LE shift_expression 967 { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }993 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); } 968 994 | relational_expression GE shift_expression 969 { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }995 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); } 970 996 ; 971 997 … … 973 999 relational_expression 974 1000 | equality_expression EQ relational_expression 975 { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }1001 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); } 976 1002 | equality_expression NE relational_expression 977 { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }1003 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); } 978 1004 ; 979 1005 … … 981 1007 equality_expression 982 1008 | AND_expression '&' equality_expression 983 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }1009 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); } 984 1010 ; 985 1011 … … 987 1013 AND_expression 988 1014 | exclusive_OR_expression '^' AND_expression 989 { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }1015 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); } 990 1016 ; 991 1017 … … 993 1019 exclusive_OR_expression 994 1020 | inclusive_OR_expression '|' exclusive_OR_expression 995 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }1021 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); } 996 1022 ; 997 1023 … … 999 1025 inclusive_OR_expression 1000 1026 | logical_AND_expression ANDAND inclusive_OR_expression 1001 { $$ = new ExpressionNode( build_and_or( $1, $3, true) ); }1027 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); } 1002 1028 ; 1003 1029 … … 1005 1031 logical_AND_expression 1006 1032 | logical_OR_expression OROR logical_AND_expression 1007 { $$ = new ExpressionNode( build_and_or( $1, $3, false) ); }1033 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); } 1008 1034 ; 1009 1035 … … 1011 1037 logical_OR_expression 1012 1038 | logical_OR_expression '?' comma_expression ':' conditional_expression 1013 { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }1039 { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); } 1014 1040 // FIX ME: computes $1 twice 1015 1041 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand 1016 { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }1042 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); } 1017 1043 ; 1018 1044 … … 1029 1055 // SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr; 1030 1056 // } else { 1031 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );1057 $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) ); 1032 1058 // } // if 1033 1059 } … … 1074 1100 // { $$ = new ExpressionNode( build_tuple( $3 ) ); } 1075 1101 '[' ',' tuple_expression_list ']' 1076 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }1102 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); } 1077 1103 | '[' push assignment_expression pop ',' tuple_expression_list ']' 1078 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }1104 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); } 1079 1105 ; 1080 1106 … … 1092 1118 assignment_expression 1093 1119 | comma_expression ',' assignment_expression 1094 { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }1120 { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1095 1121 ; 1096 1122 … … 1113 1139 | mutex_statement 1114 1140 | waitfor_statement 1141 | waituntil_statement 1115 1142 | exception_statement 1116 1143 | enable_disable_statement … … 1118 1145 | asm_statement 1119 1146 | DIRECTIVE 1120 { $$ = new StatementNode( build_directive( $1 ) ); }1147 { $$ = new StatementNode( build_directive( yylloc, $1 ) ); } 1121 1148 ; 1122 1149 … … 1124 1151 // labels cannot be identifiers 0 or 1 1125 1152 identifier_or_type_name ':' attribute_list_opt statement 1126 { $$ = $4->add_label( $1, $3 ); }1153 { $$ = $4->add_label( yylloc, $1, $3 ); } 1127 1154 | identifier_or_type_name ':' attribute_list_opt error // syntax error 1128 1155 { … … 1136 1163 compound_statement: 1137 1164 '{' '}' 1138 { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }1165 { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); } 1139 1166 | '{' push 1140 1167 local_label_declaration_opt // GCC, local labels appear at start of block 1141 1168 statement_decl_list // C99, intermix declarations and statements 1142 1169 pop '}' 1143 { $$ = new StatementNode( build_compound( $4 ) ); }1170 { $$ = new StatementNode( build_compound( yylloc, $4 ) ); } 1144 1171 ; 1145 1172 … … 1172 1199 expression_statement: 1173 1200 comma_expression_opt ';' 1174 { $$ = new StatementNode( build_expr( $1 ) ); } 1175 | MUTEX '(' ')' comma_expression ';' 1176 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); } 1201 { $$ = new StatementNode( build_expr( yylloc, $1 ) ); } 1177 1202 ; 1178 1203 … … 1183 1208 { $$ = $2; } 1184 1209 | SWITCH '(' comma_expression ')' case_clause 1185 { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }1210 { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); } 1186 1211 | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1187 1212 { 1188 StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );1213 StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) ); 1189 1214 // The semantics of the declaration list is changed to include associated initialization, which is performed 1190 1215 // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound … … 1192 1217 // therefore, are removed from the grammar even though C allows it. The change also applies to choose 1193 1218 // statement. 1194 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;1219 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1195 1220 } 1196 1221 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntax error 1197 1222 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1198 1223 | CHOOSE '(' comma_expression ')' case_clause // CFA 1199 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }1224 { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); } 1200 1225 | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1201 1226 { 1202 StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );1203 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;1227 StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) ); 1228 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1204 1229 } 1205 1230 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error … … 1210 1235 IF '(' conditional_declaration ')' statement %prec THEN 1211 1236 // explicitly deal with the shift/reduce conflict on if/else 1212 { $$ = new StatementNode( build_if( $3, maybe_build_compound($5 ), nullptr ) ); }1237 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); } 1213 1238 | IF '(' conditional_declaration ')' statement ELSE statement 1214 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound($7 ) ) ); }1239 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); } 1215 1240 ; 1216 1241 … … 1224 1249 | declaration comma_expression // semi-colon separated 1225 1250 { $$ = new CondCtl( $1, $2 ); } 1226 ;1251 ; 1227 1252 1228 1253 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case … … 1232 1257 constant_expression { $$ = $1; } 1233 1258 | constant_expression ELLIPSIS constant_expression // GCC, subrange 1234 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }1259 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1235 1260 | subrange // CFA, subrange 1236 1261 ; 1237 1262 1238 1263 case_value_list: // CFA 1239 case_value { $$ = new StatementNode( build_case($1 ) ); }1264 case_value { $$ = new ClauseNode( build_case( yylloc, $1 ) ); } 1240 1265 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5" 1241 | case_value_list ',' case_value { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 )) ) ); }1266 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); } 1242 1267 ; 1243 1268 … … 1248 1273 | CASE case_value_list error // syntax error 1249 1274 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1250 | DEFAULT ':' { $$ = new StatementNode( build_default() ); }1275 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); } 1251 1276 // A semantic check is required to ensure only one default clause per switch/choose statement. 1252 1277 | DEFAULT error // syntax error … … 1256 1281 case_label_list: // CFA 1257 1282 case_label 1258 | case_label_list case_label { $$ = (StatementNode *)( $1->set_last( $2 )); }1283 | case_label_list case_label { $$ = $1->set_last( $2 ); } 1259 1284 ; 1260 1285 1261 1286 case_clause: // CFA 1262 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }1287 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); } 1263 1288 ; 1264 1289 … … 1271 1296 switch_clause_list: // CFA 1272 1297 case_label_list statement_list_nodecl 1273 { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }1298 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); } 1274 1299 | switch_clause_list case_label_list statement_list_nodecl 1275 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 )) ) ) ); }1300 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); } 1276 1301 ; 1277 1302 1278 1303 iteration_statement: 1279 1304 WHILE '(' ')' statement %prec THEN // CFA => while ( 1 ) 1280 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound($4 ) ) ); }1305 { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); } 1281 1306 | WHILE '(' ')' statement ELSE statement // CFA 1282 1307 { 1283 $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound($4 ) ) );1284 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1308 $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); 1309 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1285 1310 } 1286 1311 | WHILE '(' conditional_declaration ')' statement %prec THEN 1287 { $$ = new StatementNode( build_while( $3, maybe_build_compound($5 ) ) ); }1312 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); } 1288 1313 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1289 { $$ = new StatementNode( build_while( $3, maybe_build_compound($5 ), $7 ) ); }1314 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); } 1290 1315 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) 1291 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound($2 ) ) ); }1316 { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); } 1292 1317 | DO statement WHILE '(' ')' ELSE statement // CFA 1293 1318 { 1294 $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound($2 ) ) );1295 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1319 $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); 1320 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1296 1321 } 1297 1322 | DO statement WHILE '(' comma_expression ')' ';' 1298 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound($2 ) ) ); }1323 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); } 1299 1324 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1300 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound($2 ), $8 ) ); }1325 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); } 1301 1326 | FOR '(' ')' statement %prec THEN // CFA => for ( ;; ) 1302 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound($4 ) ) ); }1327 { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); } 1303 1328 | FOR '(' ')' statement ELSE statement // CFA 1304 1329 { 1305 $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound($4 ) ) );1306 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1330 $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); 1331 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1307 1332 } 1308 1333 | FOR '(' for_control_expression_list ')' statement %prec THEN 1309 { $$ = new StatementNode( build_for( $3, maybe_build_compound($5 ) ) ); }1334 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); } 1310 1335 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1311 { $$ = new StatementNode( build_for( $3, maybe_build_compound($5 ), $7 ) ); }1336 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); } 1312 1337 ; 1313 1338 … … 1323 1348 if ( $1->condition ) { 1324 1349 if ( $3->condition ) { 1325 $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true) );1350 $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) ); 1326 1351 } // if 1327 1352 } else $1->condition = $3->condition; 1328 1353 if ( $1->change ) { 1329 1354 if ( $3->change ) { 1330 $1->change->expr.reset( new CommaExpr($1->change->expr.release(), $3->change->expr.release() ) );1355 $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) ); 1331 1356 } // if 1332 1357 } else $1->change = $3->change; … … 1337 1362 for_control_expression: 1338 1363 ';' comma_expression_opt ';' comma_expression_opt 1339 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }1364 { $$ = new ForCtrl( nullptr, $2, $4 ); } 1340 1365 | comma_expression ';' comma_expression_opt ';' comma_expression_opt 1341 { $$ = new ForCtrl( $1, $3, $5 ); } 1366 { 1367 StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr; 1368 $$ = new ForCtrl( init, $3, $5 ); 1369 } 1342 1370 | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';' 1343 { $$ = new ForCtrl( $1, $2, $4 ); }1371 { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); } 1344 1372 1345 1373 | '@' ';' comma_expression // CFA, empty loop-index 1346 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }1374 { $$ = new ForCtrl( nullptr, $3, nullptr ); } 1347 1375 | '@' ';' comma_expression ';' comma_expression // CFA, empty loop-index 1348 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }1376 { $$ = new ForCtrl( nullptr, $3, $5 ); } 1349 1377 1350 1378 | comma_expression // CFA, anonymous loop-index 1351 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }1379 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); } 1352 1380 | downupdowneq comma_expression // CFA, anonymous loop-index 1353 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }1381 { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); } 1354 1382 1355 1383 | comma_expression updowneq comma_expression // CFA, anonymous loop-index 1356 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }1384 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); } 1357 1385 | '@' updowneq comma_expression // CFA, anonymous loop-index 1358 1386 { 1359 1387 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1360 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );1388 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE ); 1361 1389 } 1362 1390 | comma_expression updowneq '@' // CFA, anonymous loop-index … … 1366 1394 } 1367 1395 | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1368 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }1396 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); } 1369 1397 | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1370 1398 { 1371 1399 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1372 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );1400 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 ); 1373 1401 } 1374 1402 | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index … … 1389 1417 1390 1418 | comma_expression ';' comma_expression // CFA 1391 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }1419 { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); } 1392 1420 | comma_expression ';' downupdowneq comma_expression // CFA 1393 { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }1421 { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); } 1394 1422 1395 1423 | comma_expression ';' comma_expression updowneq comma_expression // CFA 1396 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }1424 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); } 1397 1425 | comma_expression ';' '@' updowneq comma_expression // CFA 1398 1426 { 1399 1427 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1400 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );1428 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE ); 1401 1429 } 1402 1430 | comma_expression ';' comma_expression updowneq '@' // CFA … … 1404 1432 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1405 1433 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1406 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );1434 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE ); 1407 1435 } 1408 1436 | comma_expression ';' '@' updowneq '@' // CFA, error … … 1410 1438 1411 1439 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA 1412 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }1440 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); } 1413 1441 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error 1414 1442 { 1415 1443 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1416 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );1444 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 ); 1417 1445 } 1418 1446 | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA … … 1420 1448 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1421 1449 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1422 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );1450 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 ); 1423 1451 } 1424 1452 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA 1425 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }1453 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); } 1426 1454 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error 1427 1455 { 1428 1456 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1429 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );1457 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr ); 1430 1458 } 1431 1459 | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA … … 1433 1461 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1434 1462 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1435 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );1463 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr ); 1436 1464 } 1437 1465 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA … … 1439 1467 1440 1468 | declaration comma_expression // CFA 1441 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }1469 { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); } 1442 1470 | declaration downupdowneq comma_expression // CFA 1443 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }1471 { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); } 1444 1472 1445 1473 | declaration comma_expression updowneq comma_expression // CFA 1446 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }1474 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); } 1447 1475 | declaration '@' updowneq comma_expression // CFA 1448 1476 { 1449 1477 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1450 else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );1478 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE ); 1451 1479 } 1452 1480 | declaration comma_expression updowneq '@' // CFA … … 1454 1482 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1455 1483 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1456 else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );1484 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE ); 1457 1485 } 1458 1486 1459 1487 | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA 1460 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }1488 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); } 1461 1489 | declaration '@' updowneq comma_expression '~' comma_expression // CFA 1462 1490 { 1463 1491 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1464 else $$ = forCtrl( $1, $4, $3, nullptr, $6 );1492 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 ); 1465 1493 } 1466 1494 | declaration comma_expression updowneq '@' '~' comma_expression // CFA … … 1468 1496 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1469 1497 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1470 else $$ = forCtrl( $1, $2, $3, nullptr, $6 );1498 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 ); 1471 1499 } 1472 1500 | declaration comma_expression updowneq comma_expression '~' '@' // CFA 1473 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }1501 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); } 1474 1502 | declaration '@' updowneq comma_expression '~' '@' // CFA 1475 1503 { 1476 1504 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1477 else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );1505 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr ); 1478 1506 } 1479 1507 | declaration comma_expression updowneq '@' '~' '@' // CFA … … 1481 1509 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1482 1510 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1483 else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );1511 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr ); 1484 1512 } 1485 1513 | declaration '@' updowneq '@' '~' '@' // CFA, error … … 1496 1524 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1497 1525 } 1498 ;1526 ; 1499 1527 1500 1528 downupdowneq: … … 1505 1533 | ErangeDownEq 1506 1534 { $$ = OperKinds::GEThan; } 1507 ;1535 ; 1508 1536 1509 1537 updown: … … 1512 1540 | ErangeDown 1513 1541 { $$ = OperKinds::GThan; } 1514 ;1542 ; 1515 1543 1516 1544 updowneq: … … 1520 1548 | ErangeDownEq 1521 1549 { $$ = OperKinds::GEThan; } 1522 ;1550 ; 1523 1551 1524 1552 jump_statement: 1525 1553 GOTO identifier_or_type_name ';' 1526 { $$ = new StatementNode( build_branch( $2,BranchStmt::Goto ) ); }1554 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); } 1527 1555 | GOTO '*' comma_expression ';' // GCC, computed goto 1528 1556 // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3); … … 1531 1559 // A semantic check is required to ensure fallthru appears only in the body of a choose statement. 1532 1560 | fall_through_name ';' // CFA 1533 { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }1561 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); } 1534 1562 | fall_through_name identifier_or_type_name ';' // CFA 1535 { $$ = new StatementNode( build_branch( $2,BranchStmt::FallThrough ) ); }1563 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); } 1536 1564 | fall_through_name DEFAULT ';' // CFA 1537 { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }1565 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); } 1538 1566 | CONTINUE ';' 1539 1567 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1540 { $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); }1568 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); } 1541 1569 | CONTINUE identifier_or_type_name ';' // CFA, multi-level continue 1542 1570 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1543 1571 // the target of the transfer appears only at the start of an iteration statement. 1544 { $$ = new StatementNode( build_branch( $2,BranchStmt::Continue ) ); }1572 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); } 1545 1573 | BREAK ';' 1546 1574 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1547 { $$ = new StatementNode( build_branch( BranchStmt::Break ) ); }1575 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); } 1548 1576 | BREAK identifier_or_type_name ';' // CFA, multi-level exit 1549 1577 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1550 1578 // the target of the transfer appears only at the start of an iteration statement. 1551 { $$ = new StatementNode( build_branch( $2,BranchStmt::Break ) ); }1579 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); } 1552 1580 | RETURN comma_expression_opt ';' 1553 { $$ = new StatementNode( build_return( $2 ) ); }1581 { $$ = new StatementNode( build_return( yylloc, $2 ) ); } 1554 1582 | RETURN '{' initializer_list_opt comma_opt '}' ';' 1555 1583 { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; } 1556 1584 | SUSPEND ';' 1557 { $$ = new StatementNode( build_suspend( nullptr) ); }1585 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); } 1558 1586 | SUSPEND compound_statement 1559 { $$ = new StatementNode( build_suspend( $2) ); }1587 { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); } 1560 1588 | SUSPEND COROUTINE ';' 1561 { $$ = new StatementNode( build_suspend( nullptr,SuspendStmt::Coroutine ) ); }1589 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); } 1562 1590 | SUSPEND COROUTINE compound_statement 1563 { $$ = new StatementNode( build_suspend( $3,SuspendStmt::Coroutine ) ); }1591 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); } 1564 1592 | SUSPEND GENERATOR ';' 1565 { $$ = new StatementNode( build_suspend( nullptr,SuspendStmt::Generator ) ); }1593 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); } 1566 1594 | SUSPEND GENERATOR compound_statement 1567 { $$ = new StatementNode( build_suspend( $3,SuspendStmt::Generator ) ); }1595 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); } 1568 1596 | THROW assignment_expression_opt ';' // handles rethrow 1569 { $$ = new StatementNode( build_throw( $2 ) ); }1597 { $$ = new StatementNode( build_throw( yylloc, $2 ) ); } 1570 1598 | THROWRESUME assignment_expression_opt ';' // handles reresume 1571 { $$ = new StatementNode( build_resume( $2 ) ); }1599 { $$ = new StatementNode( build_resume( yylloc, $2 ) ); } 1572 1600 | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume 1573 1601 { $$ = new StatementNode( build_resume_at( $2, $4 ) ); } … … 1581 1609 with_statement: 1582 1610 WITH '(' tuple_expression_list ')' statement 1583 { $$ = new StatementNode( build_with( $3, $5 ) ); }1584 ; 1585 1586 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".1611 { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); } 1612 ; 1613 1614 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex". 1587 1615 mutex_statement: 1588 MUTEX '(' argument_expression_list ')' statement 1589 { $$ = new StatementNode( build_mutex( $3, $5 ) ); } 1616 MUTEX '(' argument_expression_list_opt ')' statement 1617 { 1618 if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; } 1619 $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) ); 1620 } 1590 1621 ; 1591 1622 … … 1598 1629 { $$ = nullptr; } 1599 1630 | when_clause 1600 ;1601 1602 waitfor:1603 WAITFOR '(' cast_expression ')'1604 { $$ = $3; }1605 // | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'1606 // { $$ = (ExpressionNode *)$3->set_last( $5 ); }1607 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'1608 { $$ = (ExpressionNode *)($3->set_last( $5 )); }1609 1631 ; 1610 1632 … … 1617 1639 1618 1640 timeout: 1619 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1620 ; 1621 1622 waitfor_clause: 1641 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1642 ; 1643 1644 wor: 1645 OROR 1646 | WOR 1647 1648 waitfor: 1649 WAITFOR '(' cast_expression ')' 1650 { $$ = $3; } 1651 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')' 1652 { $$ = (ExpressionNode *)($3->set_last( $5 )); } 1653 ; 1654 1655 wor_waitfor_clause: 1623 1656 when_clause_opt waitfor statement %prec THEN 1624 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); } 1625 | when_clause_opt waitfor statement WOR waitfor_clause 1626 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); } 1627 | when_clause_opt timeout statement %prec THEN 1628 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); } 1629 | when_clause_opt ELSE statement 1630 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); } 1657 // Called first: create header for WaitForStmt. 1658 { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); } 1659 | wor_waitfor_clause wor when_clause_opt waitfor statement 1660 { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1661 | wor_waitfor_clause wor when_clause_opt ELSE statement 1662 { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); } 1663 | wor_waitfor_clause wor when_clause_opt timeout statement %prec THEN 1664 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1631 1665 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1632 | w hen_clause_opt timeout statement WORELSE statement // syntax error1666 | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error 1633 1667 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1634 | w hen_clause_opt timeout statement WORwhen_clause ELSE statement1635 { $$ = build_waitfor_ timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5); }1668 | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1669 { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); } 1636 1670 ; 1637 1671 1638 1672 waitfor_statement: 1639 when_clause_opt waitfor statement %prec THEN 1640 { $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); } 1641 | when_clause_opt waitfor statement WOR waitfor_clause 1642 { $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); } 1673 wor_waitfor_clause %prec THEN 1674 { $$ = new StatementNode( $1 ); } 1675 ; 1676 1677 wand: 1678 ANDAND 1679 | WAND 1680 ; 1681 1682 waituntil: 1683 WAITUNTIL '(' comma_expression ')' 1684 { $$ = $3; } 1685 ; 1686 1687 waituntil_clause: 1688 when_clause_opt waituntil statement 1689 { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); } 1690 | '(' wor_waituntil_clause ')' 1691 { $$ = $2; } 1692 ; 1693 1694 wand_waituntil_clause: 1695 waituntil_clause %prec THEN 1696 { $$ = $1; } 1697 | waituntil_clause wand wand_waituntil_clause 1698 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); } 1699 ; 1700 1701 wor_waituntil_clause: 1702 wand_waituntil_clause 1703 { $$ = $1; } 1704 | wor_waituntil_clause wor wand_waituntil_clause 1705 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); } 1706 | wor_waituntil_clause wor when_clause_opt ELSE statement 1707 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); } 1708 | wor_waituntil_clause wor when_clause_opt timeout statement %prec THEN 1709 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); } 1710 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1711 | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error 1712 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1713 | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1714 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, 1715 new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, 1716 build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ), 1717 build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); } 1718 ; 1719 1720 waituntil_statement: 1721 wor_waituntil_clause %prec THEN 1722 // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement. 1723 { 1724 $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) ); 1725 // $$ = new StatementNode( build_compound( yylloc, nullptr ) ); 1726 } 1643 1727 ; 1644 1728 1645 1729 exception_statement: 1646 TRY compound_statement handler_clause %prec THEN1647 { $$ = new StatementNode( build_try( $2, $3, 0) ); }1730 TRY compound_statement handler_clause %prec THEN 1731 { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); } 1648 1732 | TRY compound_statement finally_clause 1649 { $$ = new StatementNode( build_try( $2, 0, $3 ) ); }1733 { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); } 1650 1734 | TRY compound_statement handler_clause finally_clause 1651 { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }1735 { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); } 1652 1736 ; 1653 1737 1654 1738 handler_clause: 1655 1739 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1656 { $$ = new StatementNode( build_catch($1, $4, $6, $8 ) ); }1740 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); } 1657 1741 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1658 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch($2, $5, $7, $9 ) ) ); }1742 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); } 1659 1743 ; 1660 1744 … … 1666 1750 1667 1751 handler_key: 1668 CATCH { $$ = CatchStmt::Terminate; }1669 | RECOVER { $$ = CatchStmt::Terminate; }1670 | CATCHRESUME { $$ = CatchStmt::Resume; }1671 | FIXUP { $$ = CatchStmt::Resume; }1752 CATCH { $$ = ast::Terminate; } 1753 | RECOVER { $$ = ast::Terminate; } 1754 | CATCHRESUME { $$ = ast::Resume; } 1755 | FIXUP { $$ = ast::Resume; } 1672 1756 ; 1673 1757 1674 1758 finally_clause: 1675 FINALLY compound_statement { $$ = new StatementNode( build_finally($2 ) ); }1759 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); } 1676 1760 ; 1677 1761 … … 1699 1783 asm_statement: 1700 1784 ASM asm_volatile_opt '(' string_literal ')' ';' 1701 { $$ = new StatementNode( build_asm( $2, $4, 0) ); }1785 { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); } 1702 1786 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC 1703 { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }1787 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); } 1704 1788 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';' 1705 { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }1789 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); } 1706 1790 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';' 1707 { $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }1791 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); } 1708 1792 | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';' 1709 { $$ = new StatementNode( build_asm( $2, $5, 0, $8, $10, $12 ) ); }1793 { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); } 1710 1794 ; 1711 1795 … … 1731 1815 asm_operand: // GCC 1732 1816 string_literal '(' constant_expression ')' 1733 { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); }1817 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1734 1818 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')' 1735 { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); } 1819 { 1820 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) ); 1821 delete $2.str; 1822 } 1736 1823 ; 1737 1824 … … 1740 1827 { $$ = nullptr; } // use default argument 1741 1828 | string_literal 1742 { $$ = new ExpressionNode( $1 ); }1829 { $$ = $1; } 1743 1830 | asm_clobbers_list_opt ',' string_literal 1744 { $$ = (ExpressionNode *)( $1->set_last( new ExpressionNode( $3 ) )); }1831 { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); } 1745 1832 ; 1746 1833 … … 1748 1835 identifier 1749 1836 { 1750 $$ = new LabelNode(); $$->labels. push_back(*$1 );1837 $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 ); 1751 1838 delete $1; // allocated by lexer 1752 1839 } 1753 1840 | label_list ',' identifier 1754 1841 { 1755 $$ = $1; $1->labels. push_back(*$3 );1842 $$ = $1; $1->labels.emplace_back( yylloc, *$3 ); 1756 1843 delete $3; // allocated by lexer 1757 1844 } … … 1804 1891 { 1805 1892 // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" ); 1806 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {1893 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 1807 1894 // printf( "\tattr %s\n", attr->name.c_str() ); 1808 1895 // } // for … … 1814 1901 static_assert: 1815 1902 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1816 { $$ = DeclarationNode::newStaticAssert( $3, $5); }1903 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); } 1817 1904 | STATICASSERT '(' constant_expression ')' ';' // CFA 1818 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }1905 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); } 1819 1906 1820 1907 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function … … 1880 1967 // '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict 1881 1968 // { 1882 // $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );1969 // $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true ); 1883 1970 // } 1884 1971 // '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')' 1885 1972 // { 1886 1973 // typedefTable.setNextIdentifier( *$5 ); 1887 // $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );1974 // $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true ); 1888 1975 // } 1889 1976 // | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')' 1890 1977 // { 1891 1978 // typedefTable.setNextIdentifier( *$5 ); 1892 // $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );1979 // $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true ); 1893 1980 // } 1894 1981 // | '[' ']' typegen_name … … 1902 1989 cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt 1903 1990 // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator). 1904 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0)->addQualifiers( $8 ); }1991 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); } 1905 1992 | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt 1906 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0)->addQualifiers( $8 ); }1993 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); } 1907 1994 ; 1908 1995 … … 1940 2027 { 1941 2028 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" ); 1942 $$ = $3->addType( $2 )->addTypedef(); 2029 if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) { 2030 SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr; 2031 } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3 1943 2032 } 1944 2033 | typedef_declaration pop ',' push declarator … … 1948 2037 } 1949 2038 | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 ) 1950 { 1951 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" ); 1952 $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef(); 1953 } 2039 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1954 2040 | type_specifier TYPEDEF declarator 1955 { 1956 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" ); 1957 $$ = $3->addType( $1 )->addTypedef(); 1958 } 2041 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1959 2042 | type_specifier TYPEDEF type_qualifier_list declarator 1960 { 1961 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" ); 1962 $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 ); 1963 } 2043 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1964 2044 ; 1965 2045 … … 1968 2048 TYPEDEF identifier '=' assignment_expression 1969 2049 { 1970 SemanticError( yylloc, "T ypedefexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;2050 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1971 2051 } 1972 2052 | typedef_expression pop ',' push identifier '=' assignment_expression 1973 2053 { 1974 SemanticError( yylloc, "T ypedefexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;2054 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1975 2055 } 1976 2056 ; … … 1982 2062 | typedef_expression // deprecated GCC, naming expression type 1983 2063 | sue_declaration_specifier 2064 { 2065 assert( $1->type ); 2066 if ( $1->type->qualifiers.any() ) { // CV qualifiers ? 2067 SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr; 2068 } 2069 // enums are never empty declarations because there must have at least one enumeration. 2070 if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ? 2071 SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr; 2072 } 2073 } 1984 2074 ; 1985 2075 … … 1987 2077 // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static 1988 2078 // storage-class 1989 declarator asm_name_opt initializer_opt2079 variable_declarator asm_name_opt initializer_opt 1990 2080 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); } 2081 | variable_type_redeclarator asm_name_opt initializer_opt 2082 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); } 2083 2084 | general_function_declarator asm_name_opt 2085 { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); } 2086 | general_function_declarator asm_name_opt '=' VOID 2087 { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); } 2088 1991 2089 | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt 1992 2090 { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); } 1993 2091 ; 1994 2092 2093 general_function_declarator: 2094 function_type_redeclarator 2095 | function_declarator 2096 ; 2097 1995 2098 declaration_specifier: // type specifier + storage class 1996 2099 basic_declaration_specifier 2100 | type_declaration_specifier 1997 2101 | sue_declaration_specifier 1998 | type_declaration_specifier 2102 | sue_declaration_specifier invalid_types 2103 { 2104 SemanticError( yylloc, ::toString( "Missing ';' after end of ", 2105 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ), 2106 " declaration" ) ); 2107 $$ = nullptr; 2108 } 2109 ; 2110 2111 invalid_types: 2112 aggregate_key 2113 | basic_type_name 2114 | indirect_type 1999 2115 ; 2000 2116 … … 2013 2129 basic_type_specifier 2014 2130 | sue_type_specifier 2015 {2016 // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2017 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2018 // printf( "\tattr %s\n", attr->name.c_str() );2019 // } // for2020 }2021 2131 | type_type_specifier 2022 2132 ; … … 2065 2175 { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); } 2066 2176 | forall 2177 { $$ = DeclarationNode::newForall( $1 ); } 2067 2178 ; 2068 2179 2069 2180 forall: 2070 2181 FORALL '(' type_parameter_list ')' // CFA 2071 { $$ = DeclarationNode::newForall( $3 ); }2182 { $$ = $3; } 2072 2183 ; 2073 2184 … … 2226 2337 { $$ = DeclarationNode::newTypeof( $3 ); } 2227 2338 | BASETYPEOF '(' type ')' // CFA: basetypeof( x ) y; 2228 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ), true ); }2339 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); } 2229 2340 | BASETYPEOF '(' comma_expression ')' // CFA: basetypeof( a+b ) y; 2230 2341 { $$ = DeclarationNode::newTypeof( $3, true ); } … … 2239 2350 { 2240 2351 // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2241 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2352 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2242 2353 // printf( "\tattr %s\n", attr->name.c_str() ); 2243 2354 // } // for … … 2255 2366 { 2256 2367 // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2257 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2368 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2258 2369 // printf( "\tattr %s\n", attr->name.c_str() ); 2259 2370 // } // for … … 2333 2444 { 2334 2445 // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2335 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2446 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2336 2447 // printf( "\tattr %s\n", attr->name.c_str() ); 2337 2448 // } // for … … 2357 2468 '{' field_declaration_list_opt '}' type_parameters_opt 2358 2469 { 2359 // printf( "aggregate_type1 %s\n", $3.str->c_str() );2360 // if ( $2 )2361 // for ( Attribute * attr: reverseIterate( $2->attributes ) ) {2362 // printf( "copySpecifiers12 %s\n", attr->name.c_str() );2363 // } // for2364 2470 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); 2365 // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2366 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2367 // printf( "aggregate_type3 %s\n", attr->name.c_str() );2368 // } // for2369 2471 } 2370 2472 | aggregate_key attribute_list_opt TYPEDEFname // unqualified type name … … 2375 2477 '{' field_declaration_list_opt '}' type_parameters_opt 2376 2478 { 2377 // printf( "AGG3\n" );2378 2479 DeclarationNode::newFromTypedef( $3 ); 2379 2480 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2386 2487 '{' field_declaration_list_opt '}' type_parameters_opt 2387 2488 { 2388 // printf( "AGG4\n" );2389 2489 DeclarationNode::newFromTypeGen( $3, nullptr ); 2390 2490 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2413 2513 // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and 2414 2514 // delete newFromTypeGen. 2415 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2416 $3->type->symbolic.name = nullptr; 2417 $3->type->symbolic.actuals = nullptr; 2418 delete $3; 2515 if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) { 2516 $$ = $3->addQualifiers( $2 ); 2517 } else { 2518 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2519 $3->type->symbolic.name = nullptr; // copied to $$ 2520 $3->type->symbolic.actuals = nullptr; 2521 delete $3; 2522 } 2419 2523 } 2420 2524 ; … … 2427 2531 aggregate_data: 2428 2532 STRUCT vtable_opt 2429 { $$ = AggregateDecl::Struct; }2533 { $$ = ast::AggregateDecl::Struct; } 2430 2534 | UNION 2431 { $$ = AggregateDecl::Union; }2535 { $$ = ast::AggregateDecl::Union; } 2432 2536 | EXCEPTION // CFA 2433 { $$ = AggregateDecl::Exception; }2434 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }2537 { $$ = ast::AggregateDecl::Exception; } 2538 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; } 2435 2539 ; 2436 2540 2437 2541 aggregate_control: // CFA 2438 2542 MONITOR 2439 { $$ = AggregateDecl::Monitor; }2543 { $$ = ast::AggregateDecl::Monitor; } 2440 2544 | MUTEX STRUCT 2441 { $$ = AggregateDecl::Monitor; }2545 { $$ = ast::AggregateDecl::Monitor; } 2442 2546 | GENERATOR 2443 { $$ = AggregateDecl::Generator; }2547 { $$ = ast::AggregateDecl::Generator; } 2444 2548 | MUTEX GENERATOR 2445 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2549 { 2550 SemanticError( yylloc, "monitor generator is currently unimplemented." ); 2551 $$ = ast::AggregateDecl::NoAggregate; 2552 } 2446 2553 | COROUTINE 2447 { $$ = AggregateDecl::Coroutine; }2554 { $$ = ast::AggregateDecl::Coroutine; } 2448 2555 | MUTEX COROUTINE 2449 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2556 { 2557 SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); 2558 $$ = ast::AggregateDecl::NoAggregate; 2559 } 2450 2560 | THREAD 2451 { $$ = AggregateDecl::Thread; }2561 { $$ = ast::AggregateDecl::Thread; } 2452 2562 | MUTEX THREAD 2453 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2563 { 2564 SemanticError( yylloc, "monitor thread is currently unimplemented." ); 2565 $$ = ast::AggregateDecl::NoAggregate; 2566 } 2454 2567 ; 2455 2568 … … 2467 2580 $$ = fieldDecl( $1, $2 ); 2468 2581 // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2469 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2582 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2470 2583 // printf( "\tattr %s\n", attr->name.c_str() ); 2471 2584 // } // for … … 2473 2586 | EXTENSION type_specifier field_declaring_list_opt ';' // GCC 2474 2587 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); } 2588 | STATIC type_specifier field_declaring_list_opt ';' // CFA 2589 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; } 2475 2590 | INLINE type_specifier field_abstract_list_opt ';' // CFA 2476 2591 { … … 2483 2598 } 2484 2599 | INLINE aggregate_control ';' // CFA 2485 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }2600 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; } 2486 2601 | typedef_declaration ';' // CFA 2487 2602 | cfa_field_declaring_list ';' // CFA, new style field declaration … … 2509 2624 { $$ = $1->addBitfield( $2 ); } 2510 2625 | variable_type_redeclarator bit_subrange_size_opt 2626 // A semantic check is required to ensure bit_subrange only appears on integral types. 2627 { $$ = $1->addBitfield( $2 ); } 2628 | function_type_redeclarator bit_subrange_size_opt 2511 2629 // A semantic check is required to ensure bit_subrange only appears on integral types. 2512 2630 { $$ = $1->addBitfield( $2 ); } … … 2563 2681 { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); } 2564 2682 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2565 {2566 if ( $3->storageClasses.val != 0 || $3->type->qualifiers. val != 0)2683 { 2684 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) 2567 2685 { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2568 2686 … … 2575 2693 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt 2576 2694 { 2577 if ( $3->storageClasses. val != 0|| $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }2695 if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2578 2696 typedefTable.makeTypedef( *$6 ); 2579 2697 } … … 2609 2727 enum_type_nobody: // enum - {...} 2610 2728 ENUM attribute_list_opt identifier 2611 { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false, false )->addQualifiers( $2 ); }2729 { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, nullptr, false, false )->addQualifiers( $2 ); } 2612 2730 | ENUM attribute_list_opt type_name 2613 { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false, false )->addQualifiers( $2 ); }2731 { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 ); } 2614 2732 ; 2615 2733 … … 2751 2869 type_no_function: // sizeof, alignof, cast (constructor) 2752 2870 cfa_abstract_declarator_tuple // CFA 2753 | type_specifier 2871 | type_specifier // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing 2754 2872 | type_specifier abstract_declarator 2755 2873 { $$ = $2->addType( $1 ); } … … 2796 2914 designator_list ':' // C99, CFA uses ":" instead of "=" 2797 2915 | identifier_at ':' // GCC, field name 2798 { $$ = new ExpressionNode( build_varref( $1 ) ); }2916 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 2799 2917 ; 2800 2918 … … 2808 2926 designator: 2809 2927 '.' identifier_at // C99, field name 2810 { $$ = new ExpressionNode( build_varref( $2 ) ); }2928 { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); } 2811 2929 | '[' push assignment_expression pop ']' // C99, single array element 2812 2930 // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple. … … 2815 2933 { $$ = $3; } 2816 2934 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements 2817 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); }2935 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); } 2818 2936 | '.' '[' push field_name_list pop ']' // CFA, tuple field selector 2819 2937 { $$ = $4; } … … 2855 2973 { 2856 2974 typedefTable.addToScope( *$2, TYPEDEFname, "9" ); 2857 if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }2858 if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }2859 if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }2975 if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); } 2976 if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); } 2977 if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); } 2860 2978 } 2861 2979 type_initializer_opt assertion_list_opt … … 2868 2986 { 2869 2987 typedefTable.addToScope( *$2, TYPEDIMname, "9" ); 2870 $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );2988 $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 ); 2871 2989 } 2872 2990 // | type_specifier identifier_parameter_declarator 2873 2991 | assertion_list 2874 { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }2992 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); } 2875 2993 ; 2876 2994 2877 2995 new_type_class: // CFA 2878 2996 // empty 2879 { $$ = TypeDecl::Otype; }2997 { $$ = ast::TypeDecl::Otype; } 2880 2998 | '&' 2881 { $$ = TypeDecl::Dtype; }2999 { $$ = ast::TypeDecl::Dtype; } 2882 3000 | '*' 2883 { $$ = TypeDecl::DStype; } // dtype + sized3001 { $$ = ast::TypeDecl::DStype; } // dtype + sized 2884 3002 // | '(' '*' ')' 2885 // { $$ = TypeDecl::Ftype; }3003 // { $$ = ast::TypeDecl::Ftype; } 2886 3004 | ELLIPSIS 2887 { $$ = TypeDecl::Ttype; }3005 { $$ = ast::TypeDecl::Ttype; } 2888 3006 ; 2889 3007 2890 3008 type_class: // CFA 2891 3009 OTYPE 2892 { $$ = TypeDecl::Otype; }3010 { $$ = ast::TypeDecl::Otype; } 2893 3011 | DTYPE 2894 { $$ = TypeDecl::Dtype; }3012 { $$ = ast::TypeDecl::Dtype; } 2895 3013 | FTYPE 2896 { $$ = TypeDecl::Ftype; }3014 { $$ = ast::TypeDecl::Ftype; } 2897 3015 | TTYPE 2898 { $$ = TypeDecl::Ttype; }3016 { $$ = ast::TypeDecl::Ttype; } 2899 3017 ; 2900 3018 … … 2922 3040 type_list: // CFA 2923 3041 type 2924 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3042 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 2925 3043 | assignment_expression 2926 3044 | type_list ',' type 2927 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3045 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 2928 3046 | type_list ',' assignment_expression 2929 3047 { $$ = (ExpressionNode *)( $1->set_last( $3 )); } … … 2950 3068 { 2951 3069 typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" ); 2952 $$ = DeclarationNode::newTypeDecl( $1, 0);3070 $$ = DeclarationNode::newTypeDecl( $1, nullptr ); 2953 3071 } 2954 3072 | identifier_or_type_name '(' type_parameter_list ')' … … 2961 3079 trait_specifier: // CFA 2962 3080 TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}' 2963 { $$ = DeclarationNode::newTrait( $2, $4, 0 ); } 3081 { 3082 SemanticWarning( yylloc, Warning::DeprecTraitSyntax ); 3083 $$ = DeclarationNode::newTrait( $2, $4, nullptr ); 3084 } 3085 | forall TRAIT identifier_or_type_name '{' '}' // alternate 3086 { $$ = DeclarationNode::newTrait( $3, $1, nullptr ); } 2964 3087 | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}' 2965 { $$ = DeclarationNode::newTrait( $2, $4, $8 ); } 3088 { 3089 SemanticWarning( yylloc, Warning::DeprecTraitSyntax ); 3090 $$ = DeclarationNode::newTrait( $2, $4, $8 ); 3091 } 3092 | forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate 3093 { $$ = DeclarationNode::newTrait( $3, $1, $6 ); } 2966 3094 ; 2967 3095 … … 3022 3150 external_definition: 3023 3151 DIRECTIVE 3024 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }3152 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); } 3025 3153 | declaration 3154 { 3155 // Variable declarations of anonymous types requires creating a unique type-name across multiple translation 3156 // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is 3157 // disallowed at the moment. 3158 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) { 3159 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) { 3160 SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr; 3161 } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union 3162 SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr; 3163 } 3164 } 3165 } 3026 3166 | IDENTIFIER IDENTIFIER 3027 3167 { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; } … … 3043 3183 } 3044 3184 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 3045 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0) ) ); }3185 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); } 3046 3186 | EXTERN STRINGliteral 3047 3187 { 3048 3188 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3049 linkage = LinkageSpec::update( yylloc, linkage, $2 );3189 linkage = ast::Linkage::update( yylloc, linkage, $2 ); 3050 3190 } 3051 3191 up external_definition down … … 3058 3198 { 3059 3199 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3060 linkage = LinkageSpec::update( yylloc, linkage, $2 );3200 linkage = ast::Linkage::update( yylloc, linkage, $2 ); 3061 3201 } 3062 3202 '{' up external_definition_list_opt down '}' … … 3069 3209 | type_qualifier_list 3070 3210 { 3071 if ( $1->type->qualifiers. val) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3211 if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3072 3212 if ( $1->type->forall ) forall = true; // remember generic type 3073 3213 } … … 3075 3215 { 3076 3216 distQual( $5, $1 ); 3077 forall = false;3217 forall = false; 3078 3218 $$ = $5; 3079 3219 } 3080 3220 | declaration_qualifier_list 3081 3221 { 3082 if ( $1->type && $1->type->qualifiers. val) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3222 if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3083 3223 if ( $1->type && $1->type->forall ) forall = true; // remember generic type 3084 3224 } … … 3086 3226 { 3087 3227 distQual( $5, $1 ); 3088 forall = false;3228 forall = false; 3089 3229 $$ = $5; 3090 3230 } 3091 3231 | declaration_qualifier_list type_qualifier_list 3092 3232 { 3093 if ( ($1->type && $1->type->qualifiers. val) || ($2->type && $2->type->qualifiers.val) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3233 if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3094 3234 if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type 3095 3235 } … … 3097 3237 { 3098 3238 distQual( $6, $1->addQualifiers( $2 ) ); 3099 forall = false;3239 forall = false; 3100 3240 $$ = $6; 3101 3241 } … … 3141 3281 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 ); 3142 3282 } 3143 | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement3283 | declaration_specifier function_type_redeclarator with_clause_opt compound_statement 3144 3284 { 3145 3285 rebindForall( $1, $2 ); … … 3177 3317 | variable_type_redeclarator 3178 3318 | function_declarator 3319 | function_type_redeclarator 3179 3320 ; 3180 3321 3181 3322 subrange: 3182 3323 constant_expression '~' constant_expression // CFA, integer subrange 3183 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }3324 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 3184 3325 ; 3185 3326 … … 3190 3331 { 3191 3332 DeclarationNode * name = new DeclarationNode(); 3192 name->asmName = $3;3333 name->asmName = maybeMoveBuild( $3 ); 3193 3334 $$ = name->addQualifiers( $5 ); 3194 3335 } … … 3287 3428 variable_ptr: 3288 3429 ptrref_operator variable_declarator 3289 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3430 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3290 3431 | ptrref_operator type_qualifier_list variable_declarator 3291 3432 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3303 3444 | '(' attribute_list variable_ptr ')' array_dimension 3304 3445 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3305 | '(' variable_array ')' multi_array_dimension // redundant parenthesis3446 | '(' variable_array ')' multi_array_dimension // redundant parenthesis 3306 3447 { $$ = $2->addArray( $4 ); } 3307 3448 | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis … … 3351 3492 function_ptr: 3352 3493 ptrref_operator function_declarator 3353 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3494 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3354 3495 | ptrref_operator type_qualifier_list function_declarator 3355 3496 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3403 3544 KR_function_ptr: 3404 3545 ptrref_operator KR_function_declarator 3405 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3546 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3406 3547 | ptrref_operator type_qualifier_list KR_function_declarator 3407 3548 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3427 3568 ; 3428 3569 3429 // This pattern parses a declaration for a variable or function prototypethat redefines a type name, e.g.:3570 // This pattern parses a declaration for a variable that redefines a type name, e.g.: 3430 3571 // 3431 3572 // typedef int foo; … … 3433 3574 // int foo; // redefine typedef name in new scope 3434 3575 // } 3435 //3436 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays3437 // and functions versus pointers to arrays and functions.3438 3576 3439 3577 paren_type: … … 3450 3588 paren_type attribute_list_opt 3451 3589 { $$ = $1->addQualifiers( $2 ); } 3452 | type_ptr3453 | type_array attribute_list_opt3590 | variable_type_ptr 3591 | variable_type_array attribute_list_opt 3454 3592 { $$ = $1->addQualifiers( $2 ); } 3455 | type_function attribute_list_opt3593 | variable_type_function attribute_list_opt 3456 3594 { $$ = $1->addQualifiers( $2 ); } 3457 3595 ; 3458 3596 3459 type_ptr:3597 variable_type_ptr: 3460 3598 ptrref_operator variable_type_redeclarator 3461 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3599 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3462 3600 | ptrref_operator type_qualifier_list variable_type_redeclarator 3463 3601 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3464 | '(' type_ptr ')' attribute_list_opt// redundant parenthesis3602 | '(' variable_type_ptr ')' attribute_list_opt // redundant parenthesis 3465 3603 { $$ = $2->addQualifiers( $4 ); } 3466 | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis3604 | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis 3467 3605 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3468 3606 ; 3469 3607 3470 type_array:3608 variable_type_array: 3471 3609 paren_type array_dimension 3472 3610 { $$ = $1->addArray( $2 ); } 3473 | '(' type_ptr ')' array_dimension3611 | '(' variable_type_ptr ')' array_dimension 3474 3612 { $$ = $2->addArray( $4 ); } 3475 | '(' attribute_list type_ptr ')' array_dimension3613 | '(' attribute_list variable_type_ptr ')' array_dimension 3476 3614 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3477 | '(' type_array ')' multi_array_dimension// redundant parenthesis3615 | '(' variable_type_array ')' multi_array_dimension // redundant parenthesis 3478 3616 { $$ = $2->addArray( $4 ); } 3479 | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis3617 | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis 3480 3618 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3481 | '(' type_array ')'// redundant parenthesis3619 | '(' variable_type_array ')' // redundant parenthesis 3482 3620 { $$ = $2; } 3483 | '(' attribute_list type_array ')'// redundant parenthesis3621 | '(' attribute_list variable_type_array ')' // redundant parenthesis 3484 3622 { $$ = $3->addQualifiers( $2 ); } 3485 3623 ; 3486 3624 3487 type_function: 3625 variable_type_function: 3626 '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3627 { $$ = $2->addParamList( $6 ); } 3628 | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3629 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3630 | '(' variable_type_function ')' // redundant parenthesis 3631 { $$ = $2; } 3632 | '(' attribute_list variable_type_function ')' // redundant parenthesis 3633 { $$ = $3->addQualifiers( $2 ); } 3634 ; 3635 3636 // This pattern parses a declaration for a function prototype that redefines a type name. It precludes declaring an 3637 // array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to 3638 // arrays and functions. 3639 3640 function_type_redeclarator: 3641 function_type_no_ptr attribute_list_opt 3642 { $$ = $1->addQualifiers( $2 ); } 3643 | function_type_ptr 3644 | function_type_array attribute_list_opt 3645 { $$ = $1->addQualifiers( $2 ); } 3646 ; 3647 3648 function_type_no_ptr: 3488 3649 paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3489 3650 { $$ = $1->addParamList( $4 ); } 3490 | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)3651 | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')' 3491 3652 { $$ = $2->addParamList( $6 ); } 3492 | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)3653 | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')' 3493 3654 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3494 | '(' type_function ')'// redundant parenthesis3655 | '(' function_type_no_ptr ')' // redundant parenthesis 3495 3656 { $$ = $2; } 3496 | '(' attribute_list type_function ')' // redundant parenthesis 3657 | '(' attribute_list function_type_no_ptr ')' // redundant parenthesis 3658 { $$ = $3->addQualifiers( $2 ); } 3659 ; 3660 3661 function_type_ptr: 3662 ptrref_operator function_type_redeclarator 3663 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3664 | ptrref_operator type_qualifier_list function_type_redeclarator 3665 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3666 | '(' function_type_ptr ')' attribute_list_opt 3667 { $$ = $2->addQualifiers( $4 ); } 3668 | '(' attribute_list function_type_ptr ')' attribute_list_opt 3669 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3670 ; 3671 3672 function_type_array: 3673 '(' function_type_ptr ')' array_dimension 3674 { $$ = $2->addArray( $4 ); } 3675 | '(' attribute_list function_type_ptr ')' array_dimension 3676 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3677 | '(' function_type_array ')' multi_array_dimension // redundant parenthesis 3678 { $$ = $2->addArray( $4 ); } 3679 | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis 3680 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3681 | '(' function_type_array ')' // redundant parenthesis 3682 { $$ = $2; } 3683 | '(' attribute_list function_type_array ')' // redundant parenthesis 3497 3684 { $$ = $3->addQualifiers( $2 ); } 3498 3685 ; … … 3517 3704 identifier_parameter_ptr: 3518 3705 ptrref_operator identifier_parameter_declarator 3519 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3706 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3520 3707 | ptrref_operator type_qualifier_list identifier_parameter_declarator 3521 3708 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3574 3761 type_parameter_ptr: 3575 3762 ptrref_operator type_parameter_redeclarator 3576 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3763 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3577 3764 | ptrref_operator type_qualifier_list type_parameter_redeclarator 3578 3765 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3617 3804 abstract_ptr: 3618 3805 ptrref_operator 3619 { $$ = DeclarationNode::newPointer( 0, $1 ); }3806 { $$ = DeclarationNode::newPointer( nullptr, $1 ); } 3620 3807 | ptrref_operator type_qualifier_list 3621 3808 { $$ = DeclarationNode::newPointer( $2, $1 ); } 3622 3809 | ptrref_operator abstract_declarator 3623 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }3810 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3624 3811 | ptrref_operator type_qualifier_list abstract_declarator 3625 3812 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3650 3837 // Only the first dimension can be empty. 3651 3838 '[' ']' 3652 { $$ = DeclarationNode::newArray( 0, 0, false ); }3839 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); } 3653 3840 | '[' ']' multi_array_dimension 3654 { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $3 ); }3841 { $$ = DeclarationNode::newArray( nullptr, nullptr, false )->addArray( $3 ); } 3655 3842 // Cannot use constant_expression because of tuples => semantic check 3656 3843 | '[' push assignment_expression pop ',' comma_expression ']' // CFA 3657 { $$ = DeclarationNode::newArray( $3, 0, false )->addArray( DeclarationNode::newArray( $6, 0, false ) ); }3844 { $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); } 3658 3845 // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; } 3659 3846 | '[' push array_type_list pop ']' // CFA … … 3664 3851 array_type_list: 3665 3852 basic_type_name 3666 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3853 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 3667 3854 | type_name 3668 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3855 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 3669 3856 | assignment_expression upupeq assignment_expression 3670 3857 | array_type_list ',' basic_type_name 3671 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3672 | array_type_list ',' type_name 3673 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3858 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 3859 | array_type_list ',' type_name 3860 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 3674 3861 | array_type_list ',' assignment_expression upupeq assignment_expression 3675 3862 ; … … 3680 3867 | ErangeUpEq 3681 3868 { $$ = OperKinds::LEThan; } 3682 ;3869 ; 3683 3870 3684 3871 multi_array_dimension: 3685 3872 '[' push assignment_expression pop ']' 3686 { $$ = DeclarationNode::newArray( $3, 0, false ); }3873 { $$ = DeclarationNode::newArray( $3, nullptr, false ); } 3687 3874 | '[' push '*' pop ']' // C99 3688 3875 { $$ = DeclarationNode::newVarArray( 0 ); } 3689 3876 | multi_array_dimension '[' push assignment_expression pop ']' 3690 { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }3877 { $$ = $1->addArray( DeclarationNode::newArray( $4, nullptr, false ) ); } 3691 3878 | multi_array_dimension '[' push '*' pop ']' // C99 3692 3879 { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); } … … 3785 3972 array_parameter_1st_dimension: 3786 3973 '[' ']' 3787 { $$ = DeclarationNode::newArray( 0, 0, false ); }3974 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); } 3788 3975 // multi_array_dimension handles the '[' '*' ']' case 3789 3976 | '[' push type_qualifier_list '*' pop ']' // remaining C99 3790 3977 { $$ = DeclarationNode::newVarArray( $3 ); } 3791 3978 | '[' push type_qualifier_list pop ']' 3792 { $$ = DeclarationNode::newArray( 0, $3, false ); }3979 { $$ = DeclarationNode::newArray( nullptr, $3, false ); } 3793 3980 // multi_array_dimension handles the '[' assignment_expression ']' case 3794 3981 | '[' push type_qualifier_list assignment_expression pop ']' … … 3819 4006 variable_abstract_ptr: 3820 4007 ptrref_operator 3821 { $$ = DeclarationNode::newPointer( 0, $1 ); }4008 { $$ = DeclarationNode::newPointer( nullptr, $1 ); } 3822 4009 | ptrref_operator type_qualifier_list 3823 4010 { $$ = DeclarationNode::newPointer( $2, $1 ); } 3824 4011 | ptrref_operator variable_abstract_declarator 3825 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }4012 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3826 4013 | ptrref_operator type_qualifier_list variable_abstract_declarator 3827 4014 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } … … 3865 4052 // No SUE declaration in parameter list. 3866 4053 ptrref_operator type_specifier_nobody 3867 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4054 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3868 4055 | type_qualifier_list ptrref_operator type_specifier_nobody 3869 4056 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3870 4057 | ptrref_operator cfa_abstract_function 3871 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4058 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3872 4059 | type_qualifier_list ptrref_operator cfa_abstract_function 3873 4060 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3874 4061 | ptrref_operator cfa_identifier_parameter_declarator_tuple 3875 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4062 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3876 4063 | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple 3877 4064 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } … … 3882 4069 // shift/reduce conflict with new-style empty (void) function return type. 3883 4070 '[' ']' type_specifier_nobody 3884 { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }4071 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); } 3885 4072 | cfa_array_parameter_1st_dimension type_specifier_nobody 3886 4073 { $$ = $2->addNewArray( $1 ); } 3887 4074 | '[' ']' multi_array_dimension type_specifier_nobody 3888 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }4075 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); } 3889 4076 | cfa_array_parameter_1st_dimension multi_array_dimension type_specifier_nobody 3890 4077 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); } … … 3893 4080 3894 4081 | '[' ']' cfa_identifier_parameter_ptr 3895 { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }4082 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); } 3896 4083 | cfa_array_parameter_1st_dimension cfa_identifier_parameter_ptr 3897 4084 { $$ = $2->addNewArray( $1 ); } 3898 4085 | '[' ']' multi_array_dimension cfa_identifier_parameter_ptr 3899 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }4086 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); } 3900 4087 | cfa_array_parameter_1st_dimension multi_array_dimension cfa_identifier_parameter_ptr 3901 4088 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); } … … 3953 4140 cfa_abstract_ptr: // CFA 3954 4141 ptrref_operator type_specifier 3955 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4142 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3956 4143 | type_qualifier_list ptrref_operator type_specifier 3957 4144 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3958 4145 | ptrref_operator cfa_abstract_function 3959 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4146 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3960 4147 | type_qualifier_list ptrref_operator cfa_abstract_function 3961 4148 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3962 4149 | ptrref_operator cfa_abstract_declarator_tuple 3963 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }4150 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3964 4151 | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple 3965 4152 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } -
src/Parser/parserutility.cc
r34b4268 r24d6572 10 10 // Created On : Sat May 16 15:30:39 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Jul 18 10:12:00 201713 // Update Count : 812 // Last Modified On : Wed Mar 1 10:42:00 2023 13 // Update Count : 9 14 14 // 15 15 … … 19 19 #include <string> // for string 20 20 21 #include "SynTree/Constant.h" // for Constant 22 #include "SynTree/Expression.h" // for UntypedExpr, CastExpr, ConstantExpr 23 #include "SynTree/Type.h" // for BasicType, ZeroType, BasicType::Kind... 21 #include "AST/Expr.hpp" // for UntypedExpr, CastExpr, ConstantExpr 22 #include "AST/Type.hpp" // for BasicType, ZeroType, BasicType::Kind... 24 23 25 24 // rewrite … … 28 27 // if ( (int)(x != 0) ) ... 29 28 30 Expression *notZeroExpr( Expression *orig ) { 31 if( !orig ) return nullptr; 32 UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) ); 33 comparison->get_args().push_back( orig ); 34 comparison->get_args().push_back( new ConstantExpr( Constant( new ZeroType( noQualifiers ), "0", (unsigned long long int)0 ) ) ); 35 return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 29 ast::Expr * notZeroExpr( ast::Expr * orig ) { 30 return ( !orig ) ? nullptr : new ast::CastExpr( orig->location, 31 ast::UntypedExpr::createCall( orig->location, 32 "?!=?", 33 { 34 orig, 35 new ast::ConstantExpr( orig->location, 36 new ast::ZeroType(), 37 "0", 38 std::optional<unsigned long long>( 0 ) 39 ), 40 } 41 ), 42 new ast::BasicType( ast::BasicType::SignedInt ) 43 ); 36 44 } 37 45 -
src/Parser/parserutility.h
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // parserutility.h -- 7 // parserutility.h -- Collected utilities for the parser. 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:31:46 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:32:58 201713 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 14:03:00 2023 13 // Update Count : 7 14 14 // 15 15 16 16 #pragma once 17 17 18 class Expression; 18 #include "AST/Copy.hpp" // for shallowCopy 19 namespace ast { 20 class Expr; 21 } 19 22 20 Expression *notZeroExpr( Expression *orig ); 23 ast::Expr * notZeroExpr( ast::Expr *orig ); 24 25 template< typename T > 26 static inline auto maybeBuild( T * orig ) -> decltype(orig->build()) { 27 return (orig) ? orig->build() : nullptr; 28 } 29 30 template< typename T > 31 static inline auto maybeMoveBuild( T * orig ) -> decltype(orig->build()) { 32 auto ret = maybeBuild<T>(orig); 33 delete orig; 34 return ret; 35 } 36 37 template<typename node_t> 38 node_t * maybeCopy( node_t const * node ) { 39 return node ? ast::shallowCopy( node ) : nullptr; 40 } 21 41 22 42 // Local Variables: // -
src/ResolvExpr/AlternativeFinder.cc
r34b4268 r24d6572 14 14 // 15 15 16 #include "AlternativeFinder.h" 17 16 18 #include <algorithm> // for copy 17 19 #include <cassert> // for strict_dynamic_cast, assert, assertf … … 26 28 27 29 #include "CompilationState.h" // for resolvep 30 #include "AdjustExprType.hpp" // for adjustExprType 28 31 #include "Alternative.h" // for AltList, Alternative 29 #include "AlternativeFinder.h"30 32 #include "AST/Expr.hpp" 31 33 #include "AST/SymbolTable.hpp" 32 34 #include "AST/Type.hpp" 35 #include "CastCost.hpp" // for castCost 33 36 #include "Common/SemanticError.h" // for SemanticError 34 37 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 38 #include "ConversionCost.h" // for conversionCost 35 39 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 36 40 #include "ExplodedActual.h" // for ExplodedActual 37 41 #include "InitTweak/InitTweak.h" // for getFunctionName 42 #include "PolyCost.hpp" // for polyCost 38 43 #include "RenameVars.h" // for RenameVars, global_renamer 39 44 #include "ResolveAssertions.h" // for resolveAssertions 40 45 #include "ResolveTypeof.h" // for resolveTypeof 41 46 #include "Resolver.h" // for resolveStmtExpr 47 #include "SpecCost.hpp" // for specCost 42 48 #include "SymTab/Indexer.h" // for Indexer 43 49 #include "SymTab/Mangler.h" // for Mangler … … 51 57 #include "Tuples/Explode.h" // for explode 52 58 #include "Tuples/Tuples.h" // for isTtype, handleTupleAssignment 59 #include "typeops.h" // for combos 53 60 #include "Unify.h" // for unify 54 #include "typeops.h" // for adjustExprType, polyCost, castCost55 61 56 62 #define PRINT( text ) if ( resolvep ) { text } -
src/ResolvExpr/AlternativeFinder.h
r34b4268 r24d6572 34 34 namespace ResolvExpr { 35 35 struct ArgPack; 36 37 Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue, 38 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 39 40 void referenceToRvalueConversion( Expression *& expr, Cost & cost ); 36 41 37 42 /// First index is which argument, second index is which alternative for that argument, -
src/ResolvExpr/Candidate.cpp
r34b4268 r24d6572 17 17 18 18 #include <iostream> 19 #include <sstream> 19 20 20 21 #include "AST/Print.hpp" … … 44 45 sorted.reserve(cands.size()); 45 46 for(const auto & c : cands) { 46 std:: stringstream ss;47 std::ostringstream ss; 47 48 print( ss, *c, indent ); 48 49 sorted.push_back(ss.str()); -
src/ResolvExpr/CandidateFinder.cpp
r34b4268 r24d6572 23 23 #include <vector> 24 24 25 #include "AdjustExprType.hpp" 25 26 #include "Candidate.hpp" 26 27 #include "CompilationState.h" 27 28 #include "Cost.h" 29 #include "CastCost.hpp" 30 #include "PolyCost.hpp" 31 #include "SpecCost.hpp" 32 #include "ConversionCost.h" 28 33 #include "ExplodedArg.hpp" 29 34 #include "RenameVars.h" // for renameTyVars … … 403 408 unify( 404 409 ttype, argType, newResult.env, newResult.need, newResult.have, 405 newResult.open , symtab)410 newResult.open ) 406 411 ) { 407 412 finalResults.emplace_back( std::move( newResult ) ); … … 474 479 ) 475 480 476 if ( unify( paramType, argType, env, need, have, open , symtab) ) {481 if ( unify( paramType, argType, env, need, have, open ) ) { 477 482 unsigned nextExpl = results[i].nextExpl + 1; 478 483 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } … … 493 498 ast::OpenVarSet open = results[i].open; 494 499 495 if ( unify( paramType, cnst->result, env, need, have, open , symtab) ) {500 if ( unify( paramType, cnst->result, env, need, have, open ) ) { 496 501 results.emplace_back( 497 502 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ), … … 536 541 537 542 // attempt to unify types 538 if ( unify( paramType, argType, env, need, have, open , symtab) ) {543 if ( unify( paramType, argType, env, need, have, open ) ) { 539 544 // add new result 540 545 results.emplace_back( … … 703 708 if ( selfFinder.strictMode ) { 704 709 if ( ! unifyExact( 705 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() , symtab) // xxx - is no widening correct?710 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() ) // xxx - is no widening correct? 706 711 ) { 707 712 // unification failed, do not pursue this candidate … … 711 716 else { 712 717 if ( ! unify( 713 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen , symtab)718 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen ) 714 719 ) { 715 720 // unification failed, do not pursue this candidate … … 1156 1161 1157 1162 // unification run for side-effects 1158 unify( toType, cand->expr->result, cand->env, need, have, open , symtab);1163 unify( toType, cand->expr->result, cand->env, need, have, open ); 1159 1164 Cost thisCost = 1160 1165 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) … … 1497 1502 if ( 1498 1503 unify( 1499 r2->expr->result, r3->expr->result, env, need, have, open, symtab,1504 r2->expr->result, r3->expr->result, env, need, have, open, 1500 1505 common ) 1501 1506 ) { … … 1571 1576 if ( 1572 1577 unify( 1573 r1->expr->result, r2->expr->result, env, need, have, open, symtab,1578 r1->expr->result, r2->expr->result, env, need, have, open, 1574 1579 common ) 1575 1580 ) { … … 1677 1682 1678 1683 // unification run for side-effects 1679 bool canUnify = unify( toType, cand->expr->result, env, need, have, open , symtab);1684 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1680 1685 (void) canUnify; 1681 1686 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), -
src/ResolvExpr/CandidateFinder.hpp
r34b4268 r24d6572 65 65 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 66 66 67 /// Create an expression that preforms reference to rvalue conversion on 68 /// the given expression and update the cost of the expression. 69 const ast::Expr * referenceToRvalueConversion( 70 const ast::Expr * expr, Cost & cost ); 71 67 72 } // namespace ResolvExpr 68 73 -
src/ResolvExpr/CastCost.cc
r34b4268 r24d6572 13 13 // Update Count : 9 14 14 // 15 16 #include "CastCost.hpp" 15 17 16 18 #include <cassert> // for assert … … 22 24 #include "ConversionCost.h" // for ConversionCost 23 25 #include "Cost.h" // for Cost, Cost::infinity 26 #include "ResolvExpr/ConversionCost.h" // for conversionCost 27 #include "ResolvExpr/PtrsCastable.hpp" // for ptrsCastable 24 28 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment, EqvClass 29 #include "ResolvExpr/typeops.h" // for ptrsCastable 30 #include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers 25 31 #include "SymTab/Indexer.h" // for Indexer 26 32 #include "SynTree/Declaration.h" // for TypeDecl, NamedTypeDecl 27 33 #include "SynTree/Type.h" // for PointerType, Type, TypeInstType 28 #include "typeops.h" // for typesCompatibleIgnoreQualifiers29 34 30 35 #if 0 … … 160 165 if ( 161 166 pointerType->qualifiers <= ptr->qualifiers 162 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab,env )167 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env ) 163 168 ) { 164 169 cost = Cost::safe; … … 227 232 ) 228 233 229 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab,env ) ) {234 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) { 230 235 PRINT( std::cerr << "compatible!" << std::endl; ) 231 236 if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) { -
src/ResolvExpr/CommonType.cc
r34b4268 r24d6572 14 14 // 15 15 16 #include "CommonType.hpp" 17 16 18 #include <cassert> // for strict_dynamic_cast 17 19 #include <map> // for _Rb_tree_const_iterator … … 19 21 20 22 #include "AST/Decl.hpp" 23 #include "AST/Pass.hpp" 21 24 #include "AST/Type.hpp" 22 25 #include "Common/PassVisitor.h" … … 673 676 const ast::Type * type2; 674 677 WidenMode widen; 675 const ast::SymbolTable & symtab;676 678 ast::TypeEnvironment & tenv; 677 679 const ast::OpenVarSet & open; … … 683 685 684 686 CommonType_new( 685 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,687 const ast::Type * t2, WidenMode w, 686 688 ast::TypeEnvironment & env, const ast::OpenVarSet & o, 687 689 ast::AssertionSet & need, ast::AssertionSet & have ) 688 : type2( t2 ), widen( w ), symtab( st ),tenv( env ), open( o ), need (need), have (have) ,result() {}690 : type2( t2 ), widen( w ), tenv( env ), open( o ), need (need), have (have) ,result() {} 689 691 690 692 void previsit( const ast::Node * ) { visit_children = false; } … … 764 766 ast::AssertionSet need, have; 765 767 if ( ! tenv.bindVar( 766 var, voidPtr->base, entry->second, need, have, open, widen , symtab)768 var, voidPtr->base, entry->second, need, have, open, widen ) 767 769 ) return; 768 770 } … … 777 779 ast::OpenVarSet newOpen{ open }; 778 780 if (enumInst->base->base 779 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen , symtab)) {781 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) { 780 782 result = type1; 781 783 return true; … … 814 816 815 817 ast::OpenVarSet newOpen{ open }; 816 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() , symtab) ) {818 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) { 817 819 result = pointer; 818 820 if ( q1.val != q2.val ) { … … 857 859 if (unifyExact( 858 860 arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 859 noWiden() , symtab)) {861 noWiden() )) { 860 862 break; 861 863 … … 866 868 if (unifyExact( 867 869 tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open, 868 noWiden() , symtab)) {870 noWiden() )) { 869 871 break; 870 872 … … 890 892 891 893 if ( ! unifyExact( 892 base1, base2, tenv, need, have, open, noWiden() , symtab)894 base1, base2, tenv, need, have, open, noWiden() ) 893 895 ) return; 894 896 } … … 910 912 911 913 if ( ! unifyExact( 912 base1, base2, tenv, need, have, open, noWiden() , symtab)914 base1, base2, tenv, need, have, open, noWiden() ) 913 915 ) return; 914 916 } … … 918 920 } 919 921 else if (! unifyExact( 920 arg1, arg2, tenv, need, have, open, noWiden() , symtab)) return;922 arg1, arg2, tenv, need, have, open, noWiden() )) return; 921 923 922 924 ++crnt1; ++crnt2; … … 928 930 if (! unifyExact( 929 931 t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 930 noWiden() , symtab)) return;932 noWiden() )) return; 931 933 } else if ( crnt2 != end2 ) { 932 934 // try unifying empty tuple with ttype … … 935 937 if (! unifyExact( 936 938 tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open, 937 noWiden() , symtab)) return;939 noWiden() )) return; 938 940 } 939 941 if ((f1->returns.size() == 0 && f2->returns.size() == 0) 940 || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden() , symtab))) {942 || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden()))) { 941 943 result = pointer; 942 944 … … 995 997 996 998 ast::OpenVarSet newOpen{ open }; 997 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() , symtab) ) {999 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) { 998 1000 result = ref; 999 1001 if ( q1.val != q2.val ) { … … 1010 1012 } else { 1011 1013 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 1012 result = commonType( type2, ref, tenv, need, have, open, widen , symtab);1014 result = commonType( type2, ref, tenv, need, have, open, widen ); 1013 1015 } 1014 1016 } … … 1028 1030 void postvisit( const ast::EnumInstType * enumInst ) { 1029 1031 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 1030 result = commonType( type2, enumInst, tenv, need, have, open, widen , symtab);1032 result = commonType( type2, enumInst, tenv, need, have, open, widen); 1031 1033 } 1032 1034 1033 1035 void postvisit( const ast::TraitInstType * ) {} 1034 1036 1035 void postvisit( const ast::TypeInstType * inst ) { 1036 if ( ! widen.first ) return; 1037 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 1038 if ( const ast::Type * base = 1039 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base 1040 ) { 1041 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers; 1042 1043 // force t{1,2} to be cloned if their qualifiers must be mutated 1044 ast::ptr< ast::Type > t1{ base }, t2{ type2 }; 1045 reset_qualifiers( t1, q1 ); 1046 reset_qualifiers( t2 ); 1047 1048 ast::OpenVarSet newOpen{ open }; 1049 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 1050 result = type2; 1051 reset_qualifiers( result, q1 | q2 ); 1052 } else { 1053 tryResolveWithTypedEnum( t1 ); 1054 } 1055 } 1056 } 1057 } 1037 void postvisit( const ast::TypeInstType * inst ) {} 1058 1038 1059 1039 void postvisit( const ast::TupleType * tuple) { … … 1118 1098 ast::ptr< ast::Type > handleReference( 1119 1099 const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen, 1120 const ast::SymbolTable & symtab,ast::TypeEnvironment & env,1100 ast::TypeEnvironment & env, 1121 1101 const ast::OpenVarSet & open 1122 1102 ) { … … 1126 1106 1127 1107 // need unify to bind type variables 1128 if ( unify( t1, t2, env, have, need, newOpen, symtab,common ) ) {1108 if ( unify( t1, t2, env, have, need, newOpen, common ) ) { 1129 1109 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers; 1130 1110 PRINT( … … 1150 1130 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 1151 1131 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1152 const ast::OpenVarSet & open, WidenMode widen , const ast::SymbolTable & symtab1132 const ast::OpenVarSet & open, WidenMode widen 1153 1133 ) { 1154 1134 unsigned depth1 = type1->referenceDepth(); … … 1165 1145 if ( depth1 > depth2 ) { 1166 1146 assert( ref1 ); 1167 result = handleReference( ref1->base, type2, widen, symtab,env, open );1147 result = handleReference( ref1->base, type2, widen, env, open ); 1168 1148 } else { // implies depth1 < depth2 1169 1149 assert( ref2 ); 1170 result = handleReference( type1, ref2->base, widen, symtab,env, open );1150 result = handleReference( type1, ref2->base, widen, env, open ); 1171 1151 } 1172 1152 … … 1186 1166 } 1187 1167 // otherwise both are reference types of the same depth and this is handled by the visitor 1188 ast::Pass<CommonType_new> visitor{ type2, widen, symtab,env, open, need, have };1168 ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have }; 1189 1169 type1->accept( visitor ); 1190 ast::ptr< ast::Type > result = visitor.core.result; 1191 1192 // handling for opaque type declarations (?) 1193 if ( ! result && widen.second ) { 1194 if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) { 1195 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 1196 auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt ); 1197 if ( type->base ) { 1198 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 1199 ast::OpenVarSet newOpen{ open }; 1200 1201 // force t{1,2} to be cloned if its qualifiers must be stripped, so that 1202 // type1 and type->base are left unchanged; calling convention forces 1203 // {type1,type->base}->strong_ref >= 1 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2, q1 ); 1207 1208 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) { 1209 result = t1; 1210 reset_qualifiers( result, q1 | q2 ); 1211 } 1212 } 1213 } 1214 } 1215 } 1216 1217 return result; 1170 // ast::ptr< ast::Type > result = visitor.core.result; 1171 1172 return visitor.core.result; 1218 1173 } 1219 1174 -
src/ResolvExpr/ConversionCost.cc
r34b4268 r24d6572 22 22 #include "ResolvExpr/Cost.h" // for Cost 23 23 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 24 #include "ResolvExpr/Unify.h" 24 #include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers 25 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable 25 26 #include "SymTab/Indexer.h" // for Indexer 26 27 #include "SynTree/Declaration.h" // for TypeDecl, NamedTypeDecl 27 28 #include "SynTree/Type.h" // for Type, BasicType, TypeInstType 28 #include "typeops.h" // for typesCompatibleIgnoreQualifiers29 29 30 30 … … 532 532 } 533 533 } 534 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab,env ) ) {534 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) { 535 535 return Cost::zero; 536 536 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { … … 566 566 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers; 567 567 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 568 srcAsRef->base, dstAsRef->base, symtab,env ) ) {568 srcAsRef->base, dstAsRef->base, env ) ) { 569 569 if ( tq1 == tq2 ) { 570 570 return Cost::zero; … … 587 587 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst ); 588 588 assert( dstAsRef ); 589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab,env ) ) {589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) { 590 590 if ( srcIsLvalue ) { 591 591 if ( src->qualifiers == dstAsRef->base->qualifiers ) { … … 653 653 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers; 654 654 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 655 pointerType->base, dstAsPtr->base, symtab,env ) ) {655 pointerType->base, dstAsPtr->base, env ) ) { 656 656 if ( tq1 == tq2 ) { 657 657 cost = Cost::zero; -
src/ResolvExpr/ConversionCost.h
r34b4268 r24d6572 32 32 namespace ResolvExpr { 33 33 class TypeEnvironment; 34 35 Cost conversionCost( 36 const Type * src, const Type * dest, bool srcIsLvalue, 37 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 34 38 35 39 typedef std::function<Cost(const Type *, const Type *, bool, … … 80 84 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 81 85 86 Cost conversionCost( 87 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 88 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 89 90 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest, 91 bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, 92 PtrsCalculation func ); 93 82 94 #warning when the old ConversionCost is removed, get ride of the _new suffix. 83 95 class ConversionCost_new : public ast::WithShortCircuiting { … … 119 131 }; 120 132 121 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,122 bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,123 PtrsCalculation func );124 125 133 } // namespace ResolvExpr 126 134 -
src/ResolvExpr/CurrentObject.cc
r34b4268 r24d6572 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 1 09:16:01 202213 // Update Count : 1 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 10 9:40:00 2023 13 // Update Count : 18 14 14 // 15 15 … … 26 26 #include "AST/Init.hpp" // for Designation 27 27 #include "AST/Node.hpp" // for readonly 28 #include "AST/Print.hpp" // for readonly28 #include "AST/Print.hpp" // for readonly 29 29 #include "AST/Type.hpp" 30 #include "Common/Eval.h" // for eval 30 31 #include "Common/Indenter.h" // for Indenter, operator<< 31 32 #include "Common/SemanticError.h" // for SemanticError … … 592 593 593 594 namespace ast { 595 /// Iterates members of a type by initializer. 596 class MemberIterator { 597 public: 598 virtual ~MemberIterator() {} 599 600 /// Internal set position based on iterator ranges. 601 virtual void setPosition( 602 std::deque< ptr< Expr > >::const_iterator it, 603 std::deque< ptr< Expr > >::const_iterator end ) = 0; 604 605 /// Walks the current object using the given designators as a guide. 606 void setPosition( const std::deque< ptr< Expr > > & designators ) { 607 setPosition( designators.begin(), designators.end() ); 608 } 609 610 /// Retrieve the list of possible (Type,Designation) pairs for the 611 /// current position in the current object. 612 virtual std::deque< InitAlternative > operator* () const = 0; 613 614 /// True if the iterator is not currently at the end. 615 virtual operator bool() const = 0; 616 617 /// Moves the iterator by one member in the current object. 618 virtual MemberIterator & bigStep() = 0; 619 620 /// Moves the iterator by one member in the current subobject. 621 virtual MemberIterator & smallStep() = 0; 622 623 /// The type of the current object. 624 virtual const Type * getType() = 0; 625 626 /// The type of the current subobject. 627 virtual const Type * getNext() = 0; 628 629 /// Helper for operator*; aggregates must add designator to each init 630 /// alternative, but adding designators in operator* creates duplicates. 631 virtual std::deque< InitAlternative > first() const = 0; 632 }; 633 594 634 /// create a new MemberIterator that traverses a type correctly 595 635 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); … … 631 671 }; 632 672 633 /// Iterates array types 634 class ArrayIterator final : public MemberIterator { 673 /// Iterates over an indexed type: 674 class IndexIterator : public MemberIterator { 675 protected: 635 676 CodeLocation location; 636 const ArrayType * array = nullptr;637 const Type * base = nullptr;638 677 size_t index = 0; 639 678 size_t size = 0; 640 std::unique_ptr< MemberIterator > memberIter; 641 642 void setSize( const Expr * expr ) { 643 auto res = eval( expr ); 644 if ( ! res.second ) { 645 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 646 } 647 size = res.first; 648 } 649 650 public: 651 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) { 652 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 653 memberIter.reset( createMemberIterator( loc, base ) ); 654 if ( at->isVarLen ) { 655 SemanticError( location, at, "VLA initialization does not support @=: " ); 656 } 657 setSize( at->dimension ); 658 } 679 std::unique_ptr<MemberIterator> memberIter; 680 public: 681 IndexIterator( const CodeLocation & loc, size_t size ) : 682 location( loc ), size( size ) 683 {} 659 684 660 685 void setPosition( const Expr * expr ) { … … 665 690 auto arg = eval( expr ); 666 691 index = arg.first; 667 return;668 692 669 693 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 683 707 684 708 void setPosition( 685 std::deque< ptr< Expr >>::const_iterator begin,686 std::deque< ptr< Expr >>::const_iterator end709 std::deque<ast::ptr<ast::Expr>>::const_iterator begin, 710 std::deque<ast::ptr<ast::Expr>>::const_iterator end 687 711 ) override { 688 712 if ( begin == end ) return; … … 695 719 696 720 operator bool() const override { return index < size; } 721 }; 722 723 /// Iterates over the members of array types: 724 class ArrayIterator final : public IndexIterator { 725 const ArrayType * array = nullptr; 726 const Type * base = nullptr; 727 728 size_t getSize( const Expr * expr ) { 729 auto res = eval( expr ); 730 if ( !res.second ) { 731 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 732 } 733 return res.first; 734 } 735 736 public: 737 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : 738 IndexIterator( loc, getSize( at->dimension) ), 739 array( at ), base( at->base ) { 740 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 741 memberIter.reset( createMemberIterator( loc, base ) ); 742 if ( at->isVarLen ) { 743 SemanticError( location, at, "VLA initialization does not support @=: " ); 744 } 745 } 697 746 698 747 ArrayIterator & bigStep() override { … … 833 882 834 883 const Type * getNext() final { 835 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 884 bool hasMember = memberIter && *memberIter; 885 return hasMember ? memberIter->getType() : nullptr; 836 886 } 837 887 … … 897 947 }; 898 948 899 class TupleIterator final : public AggregateIterator { 900 public: 901 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 902 : AggregateIterator( 903 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 904 ) {} 905 906 operator bool() const override { 907 return curMember != members.end() || (memberIter && *memberIter); 949 /// Iterates across the positions in a tuple: 950 class TupleIterator final : public IndexIterator { 951 ast::TupleType const * const tuple; 952 953 const ast::Type * typeAtIndex() const { 954 assert( index < size ); 955 return tuple->types[ index ].get(); 956 } 957 958 public: 959 TupleIterator( const CodeLocation & loc, const TupleType * type ) 960 : IndexIterator( loc, type->size() ), tuple( type ) { 961 PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; ) 962 memberIter.reset( createMemberIterator( loc, typeAtIndex() ) ); 908 963 } 909 964 910 965 TupleIterator & bigStep() override { 911 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 912 atbegin = false; 913 memberIter = nullptr; 914 curType = nullptr; 915 while ( curMember != members.end() ) { 916 ++curMember; 917 if ( init() ) return *this; 918 } 966 ++index; 967 memberIter.reset( index < size ? 968 createMemberIterator( location, typeAtIndex() ) : nullptr ); 919 969 return *this; 970 } 971 972 TupleIterator & smallStep() override { 973 if ( memberIter ) { 974 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; ) 975 memberIter->smallStep(); 976 if ( !memberIter ) { 977 PRINT( std::cerr << "has valid member iter" << std::endl; ) 978 return *this; 979 } 980 } 981 return bigStep(); 982 } 983 984 const ast::Type * getType() override { 985 return tuple; 986 } 987 988 const ast::Type * getNext() override { 989 bool hasMember = memberIter && *memberIter; 990 return hasMember ? memberIter->getType() : nullptr; 991 } 992 993 std::deque< InitAlternative > first() const override { 994 PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; ) 995 if ( memberIter && *memberIter ) { 996 std::deque< InitAlternative > ret = memberIter->first(); 997 for ( InitAlternative & alt : ret ) { 998 alt.designation.get_and_mutate()->designators.emplace_front( 999 ConstantExpr::from_ulong( location, index ) ); 1000 } 1001 return ret; 1002 } 1003 return {}; 920 1004 } 921 1005 }; -
src/ResolvExpr/CurrentObject.h
r34b4268 r24d6572 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Jun 8 11:07:25 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:48 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 16:14:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 65 65 66 66 /// Iterates members of a type by initializer 67 class MemberIterator { 68 public: 69 virtual ~MemberIterator() {} 70 71 /// Internal set position based on iterator ranges 72 virtual void setPosition( 73 std::deque< ptr< Expr > >::const_iterator it, 74 std::deque< ptr< Expr > >::const_iterator end ) = 0; 75 76 /// walks the current object using the given designators as a guide 77 void setPosition( const std::deque< ptr< Expr > > & designators ) { 78 setPosition( designators.begin(), designators.end() ); 79 } 80 81 /// retrieve the list of possible (Type,Designation) pairs for the current position in the 82 /// current object 83 virtual std::deque< InitAlternative > operator* () const = 0; 84 85 /// true if the iterator is not currently at the end 86 virtual operator bool() const = 0; 87 88 /// moves the iterator by one member in the current object 89 virtual MemberIterator & bigStep() = 0; 90 91 /// moves the iterator by one member in the current subobject 92 virtual MemberIterator & smallStep() = 0; 93 94 /// the type of the current object 95 virtual const Type * getType() = 0; 96 97 /// the type of the current subobject 98 virtual const Type * getNext() = 0; 99 100 /// helper for operator*; aggregates must add designator to each init alternative, but 101 /// adding designators in operator* creates duplicates 102 virtual std::deque< InitAlternative > first() const = 0; 103 }; 67 class MemberIterator; 104 68 105 69 /// Builds initializer lists in resolution -
src/ResolvExpr/ExplodedArg.hpp
r34b4268 r24d6572 35 35 ExplodedArg() : env(), cost( Cost::zero ), exprs() {} 36 36 ExplodedArg( const Candidate & arg, const ast::SymbolTable & symtab ); 37 37 38 38 ExplodedArg( ExplodedArg && ) = default; 39 39 ExplodedArg & operator= ( ExplodedArg && ) = default; -
src/ResolvExpr/PolyCost.cc
r34b4268 r24d6572 15 15 16 16 #include "AST/SymbolTable.hpp" 17 #include "AST/Pass.hpp" 17 18 #include "AST/Type.hpp" 18 19 #include "AST/TypeEnvironment.hpp" -
src/ResolvExpr/PtrsAssignable.cc
r34b4268 r24d6572 14 14 // 15 15 16 #include " typeops.h"16 #include "PtrsAssignable.hpp" 17 17 18 18 #include "AST/Pass.hpp" -
src/ResolvExpr/PtrsCastable.cc
r34b4268 r24d6572 14 14 // 15 15 16 #include "PtrsCastable.hpp" 17 16 18 #include "AST/Decl.hpp" 17 19 #include "AST/Pass.hpp" … … 19 21 #include "AST/TypeEnvironment.hpp" 20 22 #include "Common/PassVisitor.h" 23 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable 21 24 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 22 25 #include "SymTab/Indexer.h" // for Indexer … … 24 27 #include "SynTree/Type.h" // for TypeInstType, Type, BasicType 25 28 #include "SynTree/Visitor.h" // for Visitor 26 #include "typeops.h" // for ptrsAssignable27 29 28 30 namespace ResolvExpr { … … 291 293 return objectCast( src, env, symtab ); 292 294 } else { 293 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab }; 294 src->accept( ptrs ); 295 return ptrs.core.result; 295 return ast::Pass<PtrsCastable_new>::read( src, dst, env, symtab ); 296 296 } 297 297 } -
src/ResolvExpr/RenameVars.cc
r34b4268 r24d6572 83 83 84 84 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 85 // rename86 85 auto it = idMap.find( type->name ); 87 if ( it != idMap.end() ) { 88 // unconditionally mutate because map will *always* have different name 89 ast::TypeInstType * mut = ast::shallowCopy( type ); 90 // reconcile base node since some copies might have been made 91 mut->base = it->second.base; 92 mut->formal_usage = it->second.formal_usage; 93 mut->expr_id = it->second.expr_id; 94 type = mut; 95 } 96 97 return type; 86 if ( it == idMap.end() ) return type; 87 88 // Unconditionally mutate because map will *always* have different name. 89 ast::TypeInstType * mut = ast::shallowCopy( type ); 90 // Reconcile base node since some copies might have been made. 91 mut->base = it->second.base; 92 mut->formal_usage = it->second.formal_usage; 93 mut->expr_id = it->second.expr_id; 94 return mut; 98 95 } 99 96 … … 187 184 188 185 const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) { 189 // ast::Type *tc = ast::deepCopy(t);190 186 ast::Pass<RenameVars_new> renamer; 191 187 renamer.core.mode = mode; -
src/ResolvExpr/ResolveAssertions.cc
r34b4268 r24d6572 26 26 #include <vector> // for vector 27 27 28 #include "AdjustExprType.hpp" // for adjustExprType 28 29 #include "Alternative.h" // for Alternative, AssertionItem, AssertionList 29 30 #include "Common/FilterCombos.h" // for filterCombos 30 31 #include "Common/Indenter.h" // for Indenter 31 #include "Common/utility.h" // for sort_mins32 32 #include "GenPoly/GenPoly.h" // for getFunctionType 33 #include "ResolvExpr/AlternativeFinder.h" // for computeConversionCost 33 34 #include "ResolvExpr/RenameVars.h" // for renameTyVars 35 #include "SpecCost.hpp" // for specCost 34 36 #include "SymTab/Indexer.h" // for Indexer 35 37 #include "SymTab/Mangler.h" // for Mangler 36 38 #include "SynTree/Expression.h" // for InferredParams 37 39 #include "TypeEnvironment.h" // for TypeEnvironment, etc. 38 #include "typeops.h" // for adjustExprType, specCost39 40 #include "Unify.h" // for unify 40 41 -
src/ResolvExpr/Resolver.cc
r34b4268 r24d6572 38 38 #include "AST/SymbolTable.hpp" 39 39 #include "AST/Type.hpp" 40 #include "Common/Eval.h" // for eval 41 #include "Common/Iterate.hpp" // for group_iterate 40 42 #include "Common/PassVisitor.h" // for PassVisitor 41 43 #include "Common/SemanticError.h" // for SemanticError 42 44 #include "Common/Stats/ResolveTime.h" // for ResolveTime::start(), ResolveTime::stop() 43 #include "Common/ utility.h" // for ValueGuard, group_iterate45 #include "Common/ToString.hpp" // for toCString 44 46 #include "InitTweak/GenInit.h" 45 47 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt … … 1107 1109 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) { 1108 1110 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1109 if ( typesCompatible( castExpr->arg->result, castExpr->result , symtab) ) {1111 if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) { 1110 1112 // cast is to the same type as its argument, remove it 1111 1113 swap_and_save_env( expr, castExpr->arg ); … … 1729 1731 1730 1732 // Find all candidates for a function in canonical form 1731 funcFinder.find( clause.target _func, ResolvMode::withAdjustment() );1733 funcFinder.find( clause.target, ResolvMode::withAdjustment() ); 1732 1734 1733 1735 if ( funcFinder.candidates.empty() ) { 1734 1736 stringstream ss; 1735 1737 ss << "Use of undeclared indentifier '"; 1736 ss << clause.target _func.strict_as< ast::NameExpr >()->name;1738 ss << clause.target.strict_as< ast::NameExpr >()->name; 1737 1739 ss << "' in call to waitfor"; 1738 1740 SemanticError( stmt->location, ss.str() ); … … 1833 1835 if ( 1834 1836 ! unify( 1835 arg->expr->result, *param, resultEnv, need, have, open, 1836 symtab ) 1837 arg->expr->result, *param, resultEnv, need, have, open ) 1837 1838 ) { 1838 1839 // Type doesn't match … … 1921 1922 auto clause2 = new ast::WaitForClause( clause.location ); 1922 1923 1923 clause2->target _func= funcCandidates.front()->expr;1924 clause2->target = funcCandidates.front()->expr; 1924 1925 1925 1926 clause2->target_args.reserve( clause.target_args.size() ); … … 1944 1945 1945 1946 // Resolve the conditions as if it were an IfStmt, statements normally 1946 clause2-> cond = findSingleExpression( clause.cond, context );1947 clause2->when_cond = findSingleExpression( clause.when_cond, context ); 1947 1948 clause2->stmt = clause.stmt->accept( *visitor ); 1948 1949 -
src/ResolvExpr/Resolver.h
r34b4268 r24d6572 34 34 class Decl; 35 35 class DeletedExpr; 36 class Expr; 36 37 class Init; 37 38 class StmtExpr; -
src/ResolvExpr/SatisfyAssertions.cpp
r34b4268 r24d6572 24 24 #include <vector> 25 25 26 #include "AdjustExprType.hpp" 26 27 #include "Candidate.hpp" 27 28 #include "CandidateFinder.hpp" 29 #include "CommonType.hpp" 28 30 #include "Cost.h" 29 31 #include "RenameVars.h" 32 #include "SpecCost.hpp" 30 33 #include "typeops.h" 31 34 #include "Unify.h" … … 181 184 .strict_as<ast::FunctionType>()->params[0] 182 185 .strict_as<ast::ReferenceType>()->base; 183 sat.cand->env.apply(thisArgType); 186 // sat.cand->env.apply(thisArgType); 187 188 if (auto inst = thisArgType.as<ast::TypeInstType>()) { 189 auto cls = sat.cand->env.lookup(*inst); 190 if (cls && cls->bound) thisArgType = cls->bound; 191 } 184 192 185 193 std::string otypeKey = ""; … … 218 226 ast::TypeEnvironment tempNewEnv {newEnv}; 219 227 220 if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} , sat.symtab) ) {228 if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 221 229 // set up binding slot for recursive assertions 222 230 ast::UniqueId crntResnSlot = 0; … … 234 242 // newEnv = sat.cand->env; 235 243 // newNeed.clear(); 236 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} , sat.symtab) ) {244 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 237 245 // set up binding slot for recursive assertions 238 246 ast::UniqueId crntResnSlot = 0; … … 398 406 mergeOpenVars( open, i.match.open ); 399 407 400 if ( ! env.combine( i.match.env, open , symtab) ) return false;408 if ( ! env.combine( i.match.env, open ) ) return false; 401 409 402 410 crnt.emplace_back( i ); -
src/ResolvExpr/Unify.cc
r34b4268 r24d6572 33 33 #include "AST/TypeEnvironment.hpp" 34 34 #include "Common/PassVisitor.h" // for PassVisitor 35 #include "CommonType.hpp" // for commonType 35 36 #include "FindOpenVars.h" // for findOpenVars 37 #include "SpecCost.hpp" // for SpecCost 36 38 #include "SynTree/LinkageSpec.h" // for C 37 39 #include "SynTree/Constant.h" // for Constant … … 43 45 #include "Tuples/Tuples.h" // for isTtype 44 46 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 45 #include "typeops.h" // for flatten, occurs , commonType47 #include "typeops.h" // for flatten, occurs 46 48 47 49 namespace ast { … … 50 52 51 53 namespace SymTab { 52 class Indexer;54 class Indexer; 53 55 } // namespace SymTab 54 56 … … 56 58 57 59 namespace ResolvExpr { 60 61 // Template Helpers: 62 template< typename Iterator1, typename Iterator2 > 63 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) { 64 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 65 Type *commonType = 0; 66 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 67 return false; 68 } // if 69 commonTypes.push_back( commonType ); 70 } // for 71 return ( list1Begin == list1End && list2Begin == list2End ); 72 } 73 74 template< typename Iterator1, typename Iterator2 > 75 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 76 std::list< Type* > commonTypes; 77 if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) { 78 deleteAll( commonTypes ); 79 return true; 80 } else { 81 return false; 82 } // if 83 } 58 84 59 85 struct Unify_old : public WithShortCircuiting { … … 102 128 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 103 129 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 104 WidenMode widen , const ast::SymbolTable & symtab);130 WidenMode widen ); 105 131 106 132 bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { … … 124 150 125 151 bool typesCompatible( 126 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,152 const ast::Type * first, const ast::Type * second, 127 153 const ast::TypeEnvironment & env ) { 128 154 ast::TypeEnvironment newEnv; … … 137 163 findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen ); 138 164 139 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() , symtab);165 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() ); 140 166 } 141 167 … … 157 183 158 184 bool typesCompatibleIgnoreQualifiers( 159 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,185 const ast::Type * first, const ast::Type * second, 160 186 const ast::TypeEnvironment & env ) { 161 187 ast::TypeEnvironment newEnv; … … 190 216 subFirst, 191 217 subSecond, 192 newEnv, need, have, open, noWiden() , symtab);218 newEnv, need, have, open, noWiden() ); 193 219 } 194 220 … … 760 786 const ast::OpenVarSet & open; 761 787 WidenMode widen; 762 const ast::SymbolTable & symtab;763 788 public: 764 789 static size_t traceId; … … 767 792 Unify_new( 768 793 const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need, 769 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen, 770 const ast::SymbolTable & symtab ) 794 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen ) 771 795 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen), 772 symtab(symtab),result(false) {}796 result(false) {} 773 797 774 798 void previsit( const ast::Node * ) { visit_children = false; } … … 788 812 result = unifyExact( 789 813 pointer->base, pointer2->base, tenv, need, have, open, 790 noWiden() , symtab);814 noWiden()); 791 815 } 792 816 } … … 811 835 812 836 result = unifyExact( 813 array->base, array2->base, tenv, need, have, open, noWiden(), 814 symtab ); 837 array->base, array2->base, tenv, need, have, open, noWiden()); 815 838 } 816 839 … … 818 841 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 819 842 result = unifyExact( 820 ref->base, ref2->base, tenv, need, have, open, noWiden(), 821 symtab ); 843 ref->base, ref2->base, tenv, need, have, open, noWiden()); 822 844 } 823 845 } … … 828 850 static bool unifyTypeList( 829 851 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 830 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 831 const ast::SymbolTable & symtab 852 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open 832 853 ) { 833 854 while ( crnt1 != end1 && crnt2 != end2 ) { … … 842 863 return unifyExact( 843 864 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 844 noWiden() , symtab);865 noWiden() ); 845 866 } else if ( ! isTuple1 && isTuple2 ) { 846 867 // combine remainder of list1, then unify 847 868 return unifyExact( 848 869 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 849 noWiden() , symtab);870 noWiden() ); 850 871 } 851 872 852 873 if ( ! unifyExact( 853 t1, t2, env, need, have, open, noWiden() , symtab)874 t1, t2, env, need, have, open, noWiden() ) 854 875 ) return false; 855 876 … … 865 886 return unifyExact( 866 887 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 867 noWiden() , symtab);888 noWiden() ); 868 889 } else if ( crnt2 != end2 ) { 869 890 // try unifying empty tuple with ttype … … 872 893 return unifyExact( 873 894 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 874 noWiden() , symtab);895 noWiden() ); 875 896 } 876 897 … … 882 903 const std::vector< ast::ptr< ast::Type > > & list2, 883 904 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 884 const ast::OpenVarSet & open , const ast::SymbolTable & symtab905 const ast::OpenVarSet & open 885 906 ) { 886 907 return unifyTypeList( 887 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 888 symtab ); 908 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open); 889 909 } 890 910 … … 927 947 ) return; 928 948 929 if ( ! unifyTypeList( params, params2, tenv, need, have, open , symtab) ) return;949 if ( ! unifyTypeList( params, params2, tenv, need, have, open ) ) return; 930 950 if ( ! unifyTypeList( 931 func->returns, func2->returns, tenv, need, have, open , symtab) ) return;951 func->returns, func2->returns, tenv, need, have, open ) ) return; 932 952 933 953 markAssertions( have, need, func ); … … 944 964 // check that the other type is compatible and named the same 945 965 auto otherInst = dynamic_cast< const XInstType * >( other ); 946 if (otherInst && inst->name == otherInst->name) this->result = otherInst; 966 if (otherInst && inst->name == otherInst->name) 967 this->result = otherInst; 947 968 return otherInst; 948 969 } … … 1000 1021 1001 1022 if ( ! unifyExact( 1002 pty, pty2, tenv, need, have, open, noWiden() , symtab) ) {1023 pty, pty2, tenv, need, have, open, noWiden() ) ) { 1003 1024 result = false; 1004 1025 return; … … 1030 1051 void postvisit( const ast::TypeInstType * typeInst ) { 1031 1052 // assert( open.find( *typeInst ) == open.end() ); 1032 handleRefType( typeInst, type2 ); 1053 auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 ); 1054 if (otherInst && typeInst->name == otherInst->name) 1055 this->result = otherInst; 1056 // return otherInst; 1033 1057 } 1034 1058 … … 1039 1063 const std::vector< ast::ptr< ast::Type > > & list1, 1040 1064 const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env, 1041 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1042 const ast::SymbolTable & symtab 1065 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open 1043 1066 ) { 1044 1067 auto crnt1 = list1.begin(); … … 1055 1078 return unifyExact( 1056 1079 t1, tupleFromTypes( list2 ), env, need, have, open, 1057 noWiden() , symtab);1080 noWiden() ); 1058 1081 } else if ( ! isTuple1 && isTuple2 ) { 1059 1082 // combine entirety of list1, then unify 1060 1083 return unifyExact( 1061 1084 tupleFromTypes( list1 ), t2, env, need, have, open, 1062 noWiden() , symtab);1085 noWiden() ); 1063 1086 } 1064 1087 1065 1088 if ( ! unifyExact( 1066 t1, t2, env, need, have, open, noWiden() , symtab)1089 t1, t2, env, need, have, open, noWiden() ) 1067 1090 ) return false; 1068 1091 … … 1078 1101 return unifyExact( 1079 1102 t1, tupleFromTypes( list2 ), env, need, have, open, 1080 noWiden() , symtab);1103 noWiden() ); 1081 1104 } else if ( crnt2 != list2.end() ) { 1082 1105 // try unifying empty tuple with ttype … … 1087 1110 return unifyExact( 1088 1111 tupleFromTypes( list1 ), t2, env, need, have, open, 1089 noWiden() , symtab);1112 noWiden() ); 1090 1113 } 1091 1114 … … 1106 1129 auto types2 = flatten( flat2 ); 1107 1130 1108 result = unifyList( types, types2, tenv, need, have, open , symtab);1131 result = unifyList( types, types2, tenv, need, have, open ); 1109 1132 } 1110 1133 … … 1130 1153 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1131 1154 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1132 ast::OpenVarSet & open , const ast::SymbolTable & symtab1155 ast::OpenVarSet & open 1133 1156 ) { 1134 1157 ast::ptr<ast::Type> common; 1135 return unify( type1, type2, env, need, have, open, symtab,common );1158 return unify( type1, type2, env, need, have, open, common ); 1136 1159 } 1137 1160 … … 1139 1162 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1140 1163 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1141 ast::OpenVarSet & open, const ast::SymbolTable & symtab,ast::ptr<ast::Type> & common1164 ast::OpenVarSet & open, ast::ptr<ast::Type> & common 1142 1165 ) { 1143 1166 ast::OpenVarSet closed; … … 1145 1168 findOpenVars( type2, open, closed, need, have, env, FirstOpen ); 1146 1169 return unifyInexact( 1147 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab,common );1170 type1, type2, env, need, have, open, WidenMode{ true, true }, common ); 1148 1171 } 1149 1172 … … 1151 1174 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 1152 1175 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1153 WidenMode widen , const ast::SymbolTable & symtab1176 WidenMode widen 1154 1177 ) { 1155 1178 if ( type1->qualifiers != type2->qualifiers ) return false; … … 1170 1193 return env.bindVarToVar( 1171 1194 var1, var2, ast::TypeData{ entry1->second, entry2->second }, need, have, 1172 open, widen , symtab);1195 open, widen ); 1173 1196 } else if ( isopen1 ) { 1174 return env.bindVar( var1, type2, entry1->second, need, have, open, widen , symtab);1197 return env.bindVar( var1, type2, entry1->second, need, have, open, widen ); 1175 1198 } else if ( isopen2 ) { 1176 1199 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); … … 1180 1203 return env.bindVarToVar( 1181 1204 var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have, 1182 open, widen , symtab);1205 open, widen ); 1183 1206 } else if ( isopen1 ) { 1184 return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen , symtab);1207 return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen ); 1185 1208 } else if ( isopen2 ) { 1186 return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen , symtab);1209 return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen ); 1187 1210 }else { 1188 1211 return ast::Pass<Unify_new>::read( 1189 type1, type2, env, need, have, open, widen , symtab);1212 type1, type2, env, need, have, open, widen ); 1190 1213 } 1191 1214 … … 1195 1218 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1196 1219 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1197 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,1220 const ast::OpenVarSet & open, WidenMode widen, 1198 1221 ast::ptr<ast::Type> & common 1199 1222 ) { … … 1209 1232 ast::ptr< ast::Type > t2_(t2); 1210 1233 1211 if ( unifyExact( t1, t2, env, need, have, open, widen , symtab) ) {1234 if ( unifyExact( t1, t2, env, need, have, open, widen ) ) { 1212 1235 // if exact unification on unqualified types, try to merge qualifiers 1213 1236 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { … … 1219 1242 } 1220 1243 1221 } else if (( common = commonType( t1, t2, env, need, have, open, widen , symtab))) {1244 } else if (( common = commonType( t1, t2, env, need, have, open, widen ))) { 1222 1245 // no exact unification, but common type 1223 1246 auto c = shallowCopy(common.get()); -
src/ResolvExpr/Unify.h
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 13:09:04 2015 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Mon Jun 18 11:58:00 201813 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Jan 17 11:12:00 2023 13 // Update Count : 5 14 14 // 15 15 … … 37 37 38 38 namespace ResolvExpr { 39 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );41 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );42 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );43 39 44 template< typename Iterator1, typename Iterator2 > 45 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) { 46 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 47 Type *commonType = 0; 48 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 49 return false; 50 } // if 51 commonTypes.push_back( commonType ); 52 } // for 53 if ( list1Begin != list1End || list2Begin != list2End ) { 54 return false; 55 } else { 56 return true; 57 } // if 58 } 40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 41 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ); 42 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 43 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 59 44 60 template< typename Iterator1, typename Iterator2 > 61 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 62 std::list< Type* > commonTypes; 63 if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) { 64 deleteAll( commonTypes ); 65 return true; 66 } else { 67 return false; 68 } // if 69 } 45 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 46 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 70 47 71 bool unify( 72 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,73 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,74 ast::OpenVarSet & open, const ast::SymbolTable & symtab ); 48 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 49 TypeEnvironment env; 50 return typesCompatible( t1, t2, indexer, env ); 51 } 75 52 76 bool unify( 77 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,78 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,79 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 53 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 54 TypeEnvironment env; 55 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env ); 56 } 80 57 81 bool unifyExact( 82 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,83 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,84 WidenMode widen, const ast::SymbolTable & symtab);58 bool unify( 59 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 60 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 61 ast::OpenVarSet & open ); 85 62 86 bool unifyInexact( 87 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 88 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 89 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 90 ast::ptr<ast::Type> & common ); 63 bool unify( 64 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 65 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 66 ast::OpenVarSet & open, ast::ptr<ast::Type> & common ); 67 68 bool unifyExact( 69 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 70 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 71 WidenMode widen ); 72 73 bool unifyInexact( 74 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 75 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 76 const ast::OpenVarSet & open, WidenMode widen, 77 ast::ptr<ast::Type> & common ); 78 79 bool typesCompatible( 80 const ast::Type *, const ast::Type *, 81 const ast::TypeEnvironment & env = {} ); 82 83 bool typesCompatibleIgnoreQualifiers( 84 const ast::Type *, const ast::Type *, 85 const ast::TypeEnvironment & env = {} ); 86 87 /// Creates the type represented by the list of returnVals in a FunctionType. 88 /// The caller owns the return value. 89 Type * extractResultType( FunctionType * functionType ); 90 /// Creates or extracts the type represented by returns in a `FunctionType`. 91 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ); 92 93 std::vector<ast::ptr<ast::Type>> flattenList( 94 const std::vector<ast::ptr<ast::Type>> & src, ast::TypeEnvironment & env 95 ); 91 96 92 97 } // namespace ResolvExpr -
src/ResolvExpr/WidenMode.h
r34b4268 r24d6572 19 19 struct WidenMode { 20 20 WidenMode( bool first, bool second ): first( first ), second( second ) {} 21 21 22 22 WidenMode &operator|=( const WidenMode &other ) { 23 23 first |= other.first; second |= other.second; return *this; … … 35 35 WidenMode newWM( *this ); newWM &= other; return newWM; 36 36 } 37 37 38 38 operator bool() { return first && second; } 39 39 -
src/ResolvExpr/module.mk
r34b4268 r24d6572 17 17 SRC_RESOLVEXPR = \ 18 18 ResolvExpr/AdjustExprType.cc \ 19 ResolvExpr/AdjustExprType.hpp \ 19 20 ResolvExpr/Alternative.cc \ 20 21 ResolvExpr/AlternativeFinder.cc \ … … 26 27 ResolvExpr/Candidate.hpp \ 27 28 ResolvExpr/CastCost.cc \ 29 ResolvExpr/CastCost.hpp \ 28 30 ResolvExpr/CommonType.cc \ 31 ResolvExpr/CommonType.hpp \ 29 32 ResolvExpr/ConversionCost.cc \ 30 33 ResolvExpr/ConversionCost.h \ … … 40 43 ResolvExpr/Occurs.cc \ 41 44 ResolvExpr/PolyCost.cc \ 45 ResolvExpr/PolyCost.hpp \ 42 46 ResolvExpr/PtrsAssignable.cc \ 47 ResolvExpr/PtrsAssignable.hpp \ 43 48 ResolvExpr/PtrsCastable.cc \ 49 ResolvExpr/PtrsCastable.hpp \ 44 50 ResolvExpr/RenameVars.cc \ 45 51 ResolvExpr/RenameVars.h \ … … 54 60 ResolvExpr/SatisfyAssertions.hpp \ 55 61 ResolvExpr/SpecCost.cc \ 62 ResolvExpr/SpecCost.hpp \ 56 63 ResolvExpr/TypeEnvironment.cc \ 57 64 ResolvExpr/TypeEnvironment.h \ -
src/ResolvExpr/typeops.h
r34b4268 r24d6572 10 10 // Created On : Sun May 17 07:28:22 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 09:45:00 201913 // Update Count : 612 // Last Modified On : Wed Jan 18 11:54:00 2023 13 // Update Count : 7 14 14 // 15 15 … … 18 18 #include <vector> 19 19 20 #include "Cost.h"21 #include "TypeEnvironment.h"22 #include "WidenMode.h"23 #include "AST/Fwd.hpp"24 #include "AST/Node.hpp"25 #include "AST/SymbolTable.hpp"26 20 #include "AST/Type.hpp" 27 #include "AST/TypeEnvironment.hpp"28 #include "SynTree/SynTree.h"29 21 #include "SynTree/Type.h" 30 22 … … 34 26 35 27 namespace ResolvExpr { 28 class TypeEnvironment; 29 36 30 // combos: takes a list of sets and returns a set of lists representing every possible way of forming a list by 37 31 // picking one element out of each set … … 61 55 } 62 56 63 // in AdjustExprType.cc64 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function65 void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );66 67 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer68 void adjustExprType( Type *& type );69 70 template< typename ForwardIterator >71 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {72 while ( begin != end ) {73 adjustExprType( *begin++, env, indexer );74 } // while75 }76 77 /// Replaces array types with equivalent pointer, and function types with a pointer-to-function78 const ast::Type * adjustExprType(79 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );80 81 // in CastCost.cc82 Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,83 const SymTab::Indexer & indexer, const TypeEnvironment & env );84 Cost castCost(85 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,86 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );87 88 // in ConversionCost.cc89 Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,90 const SymTab::Indexer & indexer, const TypeEnvironment & env );91 Cost conversionCost(92 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,93 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );94 95 // in AlternativeFinder.cc96 Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,97 const SymTab::Indexer & indexer, const TypeEnvironment & env );98 99 // in PtrsAssignable.cc100 int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );101 int ptrsAssignable( const ast::Type * src, const ast::Type * dst,102 const ast::TypeEnvironment & env );103 104 // in PtrsCastable.cc105 int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer );106 int ptrsCastable(107 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,108 const ast::TypeEnvironment & env );109 110 // in Unify.cc111 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );112 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );113 114 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {115 TypeEnvironment env;116 return typesCompatible( t1, t2, indexer, env );117 }118 119 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {120 TypeEnvironment env;121 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );122 }123 124 bool typesCompatible(125 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},126 const ast::TypeEnvironment & env = {} );127 128 bool typesCompatibleIgnoreQualifiers(129 const ast::Type *, const ast::Type *, const ast::SymbolTable &,130 const ast::TypeEnvironment & env = {} );131 132 /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.133 Type * extractResultType( FunctionType * functionType );134 /// Creates or extracts the type represented by the list of returns in a `FunctionType`.135 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );136 137 // in CommonType.cc138 Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );139 ast::ptr< ast::Type > commonType(140 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,141 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,142 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab143 );144 // in Unify.cc145 std::vector< ast::ptr< ast::Type > > flattenList(146 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env147 );148 149 // in PolyCost.cc150 int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );151 int polyCost(152 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );153 154 // in SpecCost.cc155 int specCost( Type * type );156 int specCost( const ast::Type * type );157 158 57 // in Occurs.cc 159 58 bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env ); … … 168 67 return false; 169 68 } 170 171 // in AlternativeFinder.cc172 void referenceToRvalueConversion( Expression *& expr, Cost & cost );173 // in CandidateFinder.cpp174 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );175 69 176 70 /// flatten tuple type into list of types … … 218 112 } 219 113 220 221 114 return new ast::TupleType{ std::move(types) }; 222 115 } … … 227 120 return tupleFromTypes( tys.begin(), tys.end() ); 228 121 } 229 230 231 122 232 123 // in TypeEnvironment.cc -
src/SymTab/Autogen.cc
r34b4268 r24d6572 10 10 // Created On : Thu Mar 03 15:45:56 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 27 14:39:06 201813 // Update Count : 6 312 // Last Modified On : Fri Apr 14 15:03:00 2023 13 // Update Count : 64 14 14 // 15 15 … … 211 211 } 212 212 213 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {214 return obj && obj->name.empty() && obj->bitfieldWidth;215 }216 217 213 /// inserts a forward declaration for functionDecl into declsToAdd 218 214 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 234 230 } 235 231 236 // shallow copy the pointer list for return237 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {238 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {239 return structInst->base->params;240 }241 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {242 return unionInst->base->params;243 }244 return {};245 }246 247 232 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 248 233 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 256 241 ftype->parameters.push_back( dstParam ); 257 242 return ftype; 258 }259 260 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).261 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {262 std::vector<ast::ptr<ast::TypeDecl>> typeParams;263 if (maybePolymorphic) typeParams = getGenericParams(paramType);264 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);265 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);266 243 } 267 244 -
src/SymTab/Autogen.h
r34b4268 r24d6572 9 9 // Author : Rob Schluntz 10 10 // Created On : Sun May 17 21:53:34 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 16:38:06 201913 // Update Count : 1 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:06:00 2023 13 // Update Count : 17 14 14 // 15 15 … … 20 20 #include <string> // for string 21 21 22 #include "AST/Decl.hpp"23 #include "AST/Expr.hpp"24 #include "AST/Init.hpp"25 #include "AST/Node.hpp"26 #include "AST/Stmt.hpp"27 #include "AST/Type.hpp"28 22 #include "CodeGen/OperatorTable.h" 29 23 #include "Common/UniqueName.h" // for UniqueName … … 45 39 /// returns true if obj's name is the empty string and it has a bitfield width 46 40 bool isUnnamedBitfield( ObjectDecl * obj ); 47 bool isUnnamedBitfield( const ast::ObjectDecl * obj );48 41 49 42 /// generate the type of an assignment function for paramType. … … 55 48 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 56 49 57 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);58 59 50 /// generate the type of a copy constructor for paramType. 60 51 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 61 52 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true ); 62 53 63 /// Enum for loop direction64 enum LoopDirection { LoopBackward, LoopForward };65 66 54 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 67 55 template< typename OutputIterator > 68 56 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 69 70 template< typename OutIter >71 ast::ptr< ast::Stmt > genCall(72 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,73 const CodeLocation & loc, const std::string & fname, OutIter && out,74 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );75 57 76 58 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. … … 121 103 122 104 *out++ = new ExprStmt( fExpr ); 123 124 srcParam.clearArrayIndices();125 126 return listInit;127 }128 129 /// inserts into out a generated call expression to function fname with arguments dstParam and130 /// srcParam. Should only be called with non-array types.131 /// optionally returns a statement which must be inserted prior to the containing loop, if132 /// there is one133 template< typename OutIter >134 ast::ptr< ast::Stmt > genScalarCall(135 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,136 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,137 const ast::Type * addCast = nullptr138 ) {139 bool isReferenceCtorDtor = false;140 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {141 // reference constructors are essentially application of the rebind operator.142 // apply & to both arguments, do not need a cast143 fname = "?=?";144 dstParam = new ast::AddressExpr{ dstParam };145 addCast = nullptr;146 isReferenceCtorDtor = true;147 }148 149 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of150 // "?=?", "?{}", or "^?{}"151 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };152 153 if ( addCast ) {154 // cast to T& with qualifiers removed, so that qualified objects can be constructed and155 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue156 // is considered a qualifier - for AddressExpr to resolve, its argument must have an157 // lvalue-qualified type, so remove all qualifiers except lvalue.158 // xxx -- old code actually removed lvalue too...159 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast160 ast::ptr< ast::Type > castType = addCast;161 ast::remove_qualifiers(162 castType,163 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );164 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };165 }166 fExpr->args.emplace_back( dstParam );167 168 ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );169 170 // fetch next set of arguments171 ++srcParam;172 173 // return if adding reference fails -- will happen on default ctor and dtor174 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;175 176 std::vector< ast::ptr< ast::Expr > > args = *srcParam;177 splice( fExpr->args, args );178 179 *out++ = new ast::ExprStmt{ loc, fExpr };180 105 181 106 srcParam.clearArrayIndices(); … … 248 173 } 249 174 250 /// Store in out a loop which calls fname on each element of the array with srcParam and251 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0252 template< typename OutIter >253 void genArrayCall(254 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,255 const CodeLocation & loc, const std::string & fname, OutIter && out,256 const ast::ArrayType * array, const ast::Type * addCast = nullptr,257 LoopDirection forward = LoopForward258 ) {259 static UniqueName indexName( "_index" );260 261 // for a flexible array member nothing is done -- user must define own assignment262 if ( ! array->dimension ) return;263 264 if ( addCast ) {265 // peel off array layer from cast266 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;267 }268 269 ast::ptr< ast::Expr > begin, end;270 std::string cmp, update;271 272 if ( forward ) {273 // generate: for ( int i = 0; i < N; ++i )274 begin = ast::ConstantExpr::from_int( loc, 0 );275 end = array->dimension;276 cmp = "?<?";277 update = "++?";278 } else {279 // generate: for ( int i = N-1; i >= 0; --i )280 begin = ast::UntypedExpr::createCall( loc, "?-?",281 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );282 end = ast::ConstantExpr::from_int( loc, 0 );283 cmp = "?>=?";284 update = "--?";285 }286 287 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{288 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },289 new ast::SingleInit{ loc, begin } };290 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };291 292 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(293 loc, cmp, { indexVar, end } );294 295 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(296 loc, update, { indexVar } );297 298 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(299 loc, "?[?]", { dstParam, indexVar } );300 301 // srcParam must keep track of the array indices to build the source parameter and/or302 // array list initializer303 srcParam.addArrayIndex( indexVar, array->dimension );304 305 // for stmt's body, eventually containing call306 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };307 ast::ptr< ast::Stmt > listInit = genCall(308 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,309 forward );310 311 // block containing the stmt and index variable312 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };313 block->push_back( new ast::DeclStmt{ loc, index } );314 if ( listInit ) { block->push_back( listInit ); }315 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );316 317 *out++ = block;318 }319 320 175 template< typename OutputIterator > 321 176 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { … … 325 180 } else { 326 181 return genScalarCall( srcParam, dstParam, fname, out, type, addCast ); 327 }328 }329 330 template< typename OutIter >331 ast::ptr< ast::Stmt > genCall(332 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,333 const CodeLocation & loc, const std::string & fname, OutIter && out,334 const ast::Type * type, const ast::Type * addCast, LoopDirection forward335 ) {336 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {337 genArrayCall(338 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,339 forward );340 return {};341 } else {342 return genScalarCall(343 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );344 182 } 345 183 } … … 379 217 } 380 218 381 static inline ast::ptr< ast::Stmt > genImplicitCall(382 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,383 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,384 LoopDirection forward = LoopForward385 ) {386 // unnamed bit fields are not copied as they cannot be accessed387 if ( isUnnamedBitfield( obj ) ) return {};388 389 ast::ptr< ast::Type > addCast;390 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {391 assert( dstParam->result );392 addCast = dstParam->result;393 }394 395 std::vector< ast::ptr< ast::Stmt > > stmts;396 genCall(397 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );398 399 if ( stmts.empty() ) {400 return {};401 } else if ( stmts.size() == 1 ) {402 const ast::Stmt * callStmt = stmts.front();403 if ( addCast ) {404 // implicitly generated ctor/dtor calls should be wrapped so that later passes are405 // aware they were generated.406 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };407 }408 return callStmt;409 } else {410 assert( false );411 return {};412 }413 }414 219 } // namespace SymTab 415 220 -
src/SymTab/FixFunction.cc
r34b4268 r24d6572 21 21 #include "AST/Pass.hpp" 22 22 #include "AST/Type.hpp" 23 #include "Common/utility.h" // for maybeClone,copy23 #include "Common/utility.h" // for copy 24 24 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarati... 25 25 #include "SynTree/Expression.h" // for Expression -
src/SymTab/Indexer.cc
r34b4268 r24d6572 31 31 #include "InitTweak/InitTweak.h" // for isConstructor, isCopyFunction, isC... 32 32 #include "Mangler.h" // for Mangler 33 #include "ResolvExpr/typeops.h" // for typesCompatible 33 #include "ResolvExpr/AlternativeFinder.h" // for referenceToRvalueConversion 34 #include "ResolvExpr/Unify.h" // for typesCompatible 34 35 #include "SynTree/LinkageSpec.h" // for isMangled, isOverridable, Spec 35 36 #include "SynTree/Constant.h" // for Constant -
src/SymTab/Mangler.cc
r34b4268 r24d6572 24 24 #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup 25 25 #include "Common/PassVisitor.h" 26 #include "Common/ToString.hpp" // for toCString 26 27 #include "Common/SemanticError.h" // for SemanticError 27 #include "Common/utility.h" // for toString28 28 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 29 29 #include "SynTree/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... … … 439 439 private: 440 440 void mangleDecl( const ast::DeclWithType *declaration ); 441 void mangleRef( const ast::BaseInstType *refType, std::stringprefix );441 void mangleRef( const ast::BaseInstType *refType, const std::string & prefix ); 442 442 443 443 void printQualifiers( const ast::Type *type ); … … 535 535 } 536 536 537 __attribute__((unused))538 inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {539 std::vector< ast::ptr< ast::Type > > ret;540 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),541 std::mem_fun( &ast::DeclWithType::get_type ) );542 return ret;543 }544 545 537 void Mangler_new::postvisit( const ast::FunctionType * functionType ) { 546 538 printQualifiers( functionType ); … … 558 550 } 559 551 560 void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) { 552 void Mangler_new::mangleRef( 553 const ast::BaseInstType * refType, const std::string & prefix ) { 561 554 printQualifiers( refType ); 562 555 563 556 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name; 564 557 565 if ( mangleGenericParams ) { 566 if ( ! refType->params.empty() ) { 567 mangleName += "_"; 568 for ( const ast::Expr * param : refType->params ) { 569 auto paramType = dynamic_cast< const ast::TypeExpr * >( param ); 570 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 571 maybeAccept( paramType->type.get(), *visitor ); 572 } 573 mangleName += "_"; 558 if ( mangleGenericParams && ! refType->params.empty() ) { 559 mangleName += "_"; 560 for ( const ast::Expr * param : refType->params ) { 561 auto paramType = dynamic_cast< const ast::TypeExpr * >( param ); 562 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 563 maybeAccept( paramType->type.get(), *visitor ); 574 564 } 565 mangleName += "_"; 575 566 } 576 567 } … … 656 647 } 657 648 649 // For debugging: 658 650 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) { 659 651 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) { … … 665 657 // skip if not including qualifiers 666 658 if ( typeMode ) return; 667 if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) { 668 if ( ! ptype->forall.empty() ) { 669 std::list< std::string > assertionNames; 670 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 671 mangleName += Encoding::forall; 672 for ( auto & decl : ptype->forall ) { 673 switch ( decl->kind ) { 674 case ast::TypeDecl::Kind::Dtype: 675 dcount++; 676 break; 677 case ast::TypeDecl::Kind::Ftype: 678 fcount++; 679 break; 680 case ast::TypeDecl::Kind::Ttype: 681 vcount++; 682 break; 683 default: 684 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() ); 685 } // switch 686 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 687 } // for 688 for ( auto & assert : ptype->assertions ) { 689 assertionNames.push_back( ast::Pass<Mangler_new>::read( 690 assert->var.get(), 691 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) ); 692 acount++; 693 } // for 694 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_"; 695 for(const auto & a : assertionNames) mangleName += a; 696 // std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); 697 mangleName += "_"; 698 } // if 659 auto funcType = dynamic_cast<const ast::FunctionType *>( type ); 660 if ( funcType && !funcType->forall.empty() ) { 661 std::list< std::string > assertionNames; 662 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 663 mangleName += Encoding::forall; 664 for ( auto & decl : funcType->forall ) { 665 switch ( decl->kind ) { 666 case ast::TypeDecl::Dtype: 667 dcount++; 668 break; 669 case ast::TypeDecl::Ftype: 670 fcount++; 671 break; 672 case ast::TypeDecl::Ttype: 673 vcount++; 674 break; 675 default: 676 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() ); 677 } // switch 678 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 679 } // for 680 for ( auto & assert : funcType->assertions ) { 681 assertionNames.push_back( ast::Pass<Mangler_new>::read( 682 assert->var.get(), 683 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) ); 684 acount++; 685 } // for 686 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_"; 687 for ( const auto & a : assertionNames ) mangleName += a; 688 mangleName += "_"; 699 689 } // if 700 690 if ( ! inFunctionType ) { -
src/SymTab/Validate.cc
r34b4268 r24d6572 55 55 #include "Common/ScopedMap.h" // for ScopedMap 56 56 #include "Common/SemanticError.h" // for SemanticError 57 #include "Common/ToString.hpp" // for toCString 57 58 #include "Common/UniqueName.h" // for UniqueName 58 #include "Common/utility.h" // for operator+,cloneAll, deleteAll59 #include "Common/utility.h" // for cloneAll, deleteAll 59 60 #include "CompilationState.h" // skip some passes in new-ast build 60 61 #include "Concurrency/Keywords.h" // for applyKeywords … … 63 64 #include "InitTweak/GenInit.h" // for fixReturnStatements 64 65 #include "InitTweak/InitTweak.h" // for isCtorDtorAssign 65 #include "ResolvExpr/typeops.h" // for typesCompatible 66 #include "ResolvExpr/typeops.h" // for extractResultType 67 #include "ResolvExpr/Unify.h" // for typesCompatible 66 68 #include "ResolvExpr/Resolver.h" // for findSingleExpression 67 69 #include "ResolvExpr/ResolveTypeof.h" // for resolveTypeof … … 862 864 863 865 void ReplaceTypedef::premutate( TypeDecl * typeDecl ) { 864 TypedefMap::iterator i = typedefNames.find( typeDecl->name ); 865 if ( i != typedefNames.end() ) { 866 typedefNames.erase( i ) ; 867 } // if 868 866 typedefNames.erase( typeDecl->name ); 869 867 typedeclNames.insert( typeDecl->name, typeDecl ); 870 868 } -
src/SymTab/ValidateType.cc
r34b4268 r24d6572 18 18 #include "CodeGen/OperatorTable.h" 19 19 #include "Common/PassVisitor.h" 20 #include "Common/ToString.hpp" 20 21 #include "SymTab/FixFunction.h" 21 22 #include "SynTree/Declaration.h" -
src/SymTab/module.mk
r34b4268 r24d6572 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/FixFunction.h \ 22 SymTab/GenImplicitCall.cpp \ 23 SymTab/GenImplicitCall.hpp \ 22 24 SymTab/Indexer.cc \ 23 25 SymTab/Indexer.h \ -
src/SynTree/AggregateDecl.cc
r34b4268 r24d6572 19 19 20 20 #include "Attribute.h" // for Attribute 21 #include "Common/Eval.h" // for eval 21 22 #include "Common/utility.h" // for printAll, cloneAll, deleteAll 22 23 #include "Declaration.h" // for AggregateDecl, TypeDecl, Declaration -
src/SynTree/ApplicationExpr.cc
r34b4268 r24d6572 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ApplicationExpr.cc .cc--7 // ApplicationExpr.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 26 26 #include "Expression.h" // for ParamEntry, ApplicationExpr, Expression 27 27 #include "InitTweak/InitTweak.h" // for getFunction 28 #include "ResolvExpr/ typeops.h"// for extractResultType28 #include "ResolvExpr/Unify.h" // for extractResultType 29 29 #include "Type.h" // for Type, PointerType, FunctionType 30 30 -
src/SynTree/BasicType.cc
r34b4268 r24d6572 29 29 } 30 30 31 bool BasicType::isWholeNumber() const {32 return kind == Bool ||33 kind ==Char ||34 kind == SignedChar ||35 kind == UnsignedChar ||36 kind == ShortSignedInt ||37 kind == ShortUnsignedInt ||38 kind == SignedInt ||39 kind == UnsignedInt ||40 kind == LongSignedInt ||41 kind == LongUnsignedInt ||42 kind == LongLongSignedInt ||43 kind ==LongLongUnsignedInt ||44 kind == SignedInt128 ||45 kind == UnsignedInt128;46 }47 48 31 bool BasicType::isInteger() const { 49 32 return kind <= UnsignedInt128; -
src/SynTree/FunctionDecl.cc
r34b4268 r24d6572 87 87 } // if 88 88 89 if ( !withExprs.empty() ) { 90 os << indent << "... with clause" << std::endl; 91 os << indent + 1; 92 printAll( withExprs, os, indent + 1 ); 93 } 94 89 95 if ( statements ) { 90 96 os << indent << "... with body" << endl << indent+1; -
src/SynTree/Type.cc
r34b4268 r24d6572 16 16 17 17 #include "Attribute.h" // for Attribute 18 #include "Common/ToString.hpp" // for toCString 18 19 #include "Common/utility.h" // for cloneAll, deleteAll, printAll 19 20 #include "InitTweak/InitTweak.h" // for getPointerBase … … 105 106 int Type::referenceDepth() const { return 0; } 106 107 108 AggregateDecl * Type::getAggr() const { 109 assertf( false, "Non-aggregate type: %s", toCString( this ) ); 110 } 111 107 112 TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); } 108 113 -
src/SynTree/Type.h
r34b4268 r24d6572 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Jul 14 15:40:00 202113 // Update Count : 17 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 19 22:37:10 2023 13 // Update Count : 176 14 14 // 15 15 … … 23 23 24 24 #include "BaseSyntaxNode.h" // for BaseSyntaxNode 25 #include "Common/ utility.h"// for operator+25 #include "Common/Iterate.hpp"// for operator+ 26 26 #include "Mutator.h" // for Mutator 27 27 #include "SynTree.h" // for AST nodes … … 124 124 bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); } 125 125 bool operator<=( Qualifiers other ) const { 126 return is_const <= other.is_const // Any non-const converts to const without cost127 && is_volatile <= other.is_volatile //Any non-volatile converts to volatile without cost128 && is_mutex >= other.is_mutex //Any mutex converts to non-mutex without cost129 && is_atomic == other.is_atomic; //No conversion from atomic to non atomic is free126 return is_const <= other.is_const // Any non-const converts to const without cost 127 && is_volatile <= other.is_volatile // Any non-volatile converts to volatile without cost 128 && is_mutex >= other.is_mutex // Any mutex converts to non-mutex without cost 129 && is_atomic == other.is_atomic; // No conversion from atomic to non atomic is free 130 130 } 131 131 bool operator<( Qualifiers other ) const { return *this != other && *this <= other; } … … 185 185 virtual bool isComplete() const { return true; } 186 186 187 virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }187 virtual AggregateDecl * getAggr() const; 188 188 189 189 virtual TypeSubstitution genericSubstitution() const; 190 190 191 virtual Type * clone() const = 0;191 virtual Type * clone() const = 0; 192 192 virtual void accept( Visitor & v ) = 0; 193 193 virtual void accept( Visitor & v ) const = 0; 194 virtual Type * acceptMutator( Mutator & m ) = 0;194 virtual Type * acceptMutator( Mutator & m ) = 0; 195 195 virtual void print( std::ostream & os, Indenter indent = {} ) const; 196 196 }; … … 207 207 virtual bool isComplete() const override { return false; } 208 208 209 virtual VoidType * clone() const override { return new VoidType( *this ); }210 virtual void accept( Visitor & v ) override { v.visit( this ); } 211 virtual void accept( Visitor & v ) const override { v.visit( this ); } 212 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }209 virtual VoidType * clone() const override { return new VoidType( *this ); } 210 virtual void accept( Visitor & v ) override { v.visit( this ); } 211 virtual void accept( Visitor & v ) const override { v.visit( this ); } 212 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 213 213 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 214 214 }; … … 259 259 // GENERATED END 260 260 261 static const char * typeNames[];// string names for basic types, MUST MATCH with Kind261 static const char * typeNames[]; // string names for basic types, MUST MATCH with Kind 262 262 263 263 BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); … … 266 266 void set_kind( Kind newValue ) { kind = newValue; } 267 267 268 virtual BasicType *clone() const override { return new BasicType( *this ); } 269 virtual void accept( Visitor & v ) override { v.visit( this ); } 270 virtual void accept( Visitor & v ) const override { v.visit( this ); } 271 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 272 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 273 bool isWholeNumber() const; 268 virtual BasicType * clone() const override { return new BasicType( *this ); } 269 virtual void accept( Visitor & v ) override { v.visit( this ); } 270 virtual void accept( Visitor & v ) const override { v.visit( this ); } 271 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 272 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 274 273 bool isInteger() const; 275 274 }; … … 280 279 281 280 // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] ) 282 Expression * dimension;281 Expression * dimension; 283 282 bool isVarLen; 284 283 bool isStatic; 285 284 286 PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );287 PointerType( const Type::Qualifiers & tq, Type * base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );285 PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 286 PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 288 287 PointerType( const PointerType& ); 289 288 virtual ~PointerType(); 290 289 291 Type * get_base() { return base; }292 void set_base( Type * newValue ) { base = newValue; }293 Expression * get_dimension() { return dimension; }294 void set_dimension( Expression * newValue ) { dimension = newValue; }290 Type * get_base() { return base; } 291 void set_base( Type * newValue ) { base = newValue; } 292 Expression * get_dimension() { return dimension; } 293 void set_dimension( Expression * newValue ) { dimension = newValue; } 295 294 bool get_isVarLen() { return isVarLen; } 296 295 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 302 301 virtual bool isComplete() const override { return ! isVarLen; } 303 302 304 virtual PointerType * clone() const override { return new PointerType( *this ); }305 virtual void accept( Visitor & v ) override { v.visit( this ); } 306 virtual void accept( Visitor & v ) const override { v.visit( this ); } 307 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }303 virtual PointerType * clone() const override { return new PointerType( * this ); } 304 virtual void accept( Visitor & v ) override { v.visit( this ); } 305 virtual void accept( Visitor & v ) const override { v.visit( this ); } 306 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 308 307 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 309 308 }; … … 311 310 class ArrayType : public Type { 312 311 public: 313 Type * base;314 Expression * dimension;312 Type * base; 313 Expression * dimension; 315 314 bool isVarLen; 316 315 bool isStatic; 317 316 318 ArrayType( const Type::Qualifiers & tq, Type * base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );317 ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 319 318 ArrayType( const ArrayType& ); 320 319 virtual ~ArrayType(); 321 320 322 Type * get_base() { return base; }323 void set_base( Type * newValue ) { base = newValue; }324 Expression * get_dimension() { return dimension; }325 void set_dimension( Expression * newValue ) { dimension = newValue; }321 Type * get_base() { return base; } 322 void set_base( Type * newValue ) { base = newValue; } 323 Expression * get_dimension() { return dimension; } 324 void set_dimension( Expression * newValue ) { dimension = newValue; } 326 325 bool get_isVarLen() { return isVarLen; } 327 326 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 334 333 virtual bool isComplete() const override { return dimension || isVarLen; } 335 334 336 virtual ArrayType * clone() const override { return new ArrayType( *this ); }337 virtual void accept( Visitor & v ) override { v.visit( this ); } 338 virtual void accept( Visitor & v ) const override { v.visit( this ); } 339 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }335 virtual ArrayType * clone() const override { return new ArrayType( *this ); } 336 virtual void accept( Visitor & v ) override { v.visit( this ); } 337 virtual void accept( Visitor & v ) const override { v.visit( this ); } 338 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 340 339 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 341 340 }; … … 349 348 virtual ~QualifiedType(); 350 349 351 virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }352 virtual void accept( Visitor & v ) override { v.visit( this ); } 353 virtual void accept( Visitor & v ) const override { v.visit( this ); } 354 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }350 virtual QualifiedType * clone() const override { return new QualifiedType( *this ); } 351 virtual void accept( Visitor & v ) override { v.visit( this ); } 352 virtual void accept( Visitor & v ) const override { v.visit( this ); } 353 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 355 354 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 356 355 }; … … 358 357 class ReferenceType : public Type { 359 358 public: 360 Type * base;361 362 ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );359 Type * base; 360 361 ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 363 362 ReferenceType( const ReferenceType & ); 364 363 virtual ~ReferenceType(); 365 364 366 Type * get_base() { return base; }367 void set_base( Type * newValue ) { base = newValue; }365 Type * get_base() { return base; } 366 void set_base( Type * newValue ) { base = newValue; } 368 367 369 368 virtual int referenceDepth() const override; … … 376 375 virtual TypeSubstitution genericSubstitution() const override; 377 376 378 virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }379 virtual void accept( Visitor & v ) override { v.visit( this ); } 380 virtual void accept( Visitor & v ) const override { v.visit( this ); } 381 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }377 virtual ReferenceType * clone() const override { return new ReferenceType( *this ); } 378 virtual void accept( Visitor & v ) override { v.visit( this ); } 379 virtual void accept( Visitor & v ) const override { v.visit( this ); } 380 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 382 381 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 383 382 }; … … 406 405 bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; } 407 406 408 virtual FunctionType * clone() const override { return new FunctionType( *this ); }409 virtual void accept( Visitor & v ) override { v.visit( this ); } 410 virtual void accept( Visitor & v ) const override { v.visit( this ); } 411 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }407 virtual FunctionType * clone() const override { return new FunctionType( *this ); } 408 virtual void accept( Visitor & v ) override { v.visit( this ); } 409 virtual void accept( Visitor & v ) const override { v.visit( this ); } 410 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 412 411 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 413 412 }; … … 415 414 class ReferenceToType : public Type { 416 415 public: 417 std::list< Expression * > parameters;416 std::list< Expression * > parameters; 418 417 std::string name; 419 418 bool hoistType; … … 429 428 void set_hoistType( bool newValue ) { hoistType = newValue; } 430 429 431 virtual ReferenceToType * clone() const override = 0;430 virtual ReferenceToType * clone() const override = 0; 432 431 virtual void accept( Visitor & v ) override = 0; 433 virtual Type * acceptMutator( Mutator & m ) override = 0;432 virtual Type * acceptMutator( Mutator & m ) override = 0; 434 433 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 435 434 … … 444 443 // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree, 445 444 // where the structure used in this type is actually defined 446 StructDecl * baseStruct;445 StructDecl * baseStruct; 447 446 448 447 StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseStruct( 0 ) {} … … 450 449 StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {} 451 450 452 StructDecl * get_baseStruct() const { return baseStruct; }453 void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }451 StructDecl * get_baseStruct() const { return baseStruct; } 452 void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; } 454 453 455 454 /// Accesses generic parameters of base struct (NULL if none such) … … 467 466 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 468 467 469 virtual StructInstType * clone() const override { return new StructInstType( *this ); }470 virtual void accept( Visitor & v ) override { v.visit( this ); } 471 virtual void accept( Visitor & v ) const override { v.visit( this ); } 472 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }468 virtual StructInstType * clone() const override { return new StructInstType( *this ); } 469 virtual void accept( Visitor & v ) override { v.visit( this ); } 470 virtual void accept( Visitor & v ) const override { v.visit( this ); } 471 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 473 472 474 473 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 482 481 // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, 483 482 // where the union used in this type is actually defined 484 UnionDecl * baseUnion;483 UnionDecl * baseUnion; 485 484 486 485 UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseUnion( 0 ) {} … … 488 487 UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {} 489 488 490 UnionDecl * get_baseUnion() const { return baseUnion; }489 UnionDecl * get_baseUnion() const { return baseUnion; } 491 490 void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; } 492 491 … … 505 504 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 506 505 507 virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }508 virtual void accept( Visitor & v ) override { v.visit( this ); } 509 virtual void accept( Visitor & v ) const override { v.visit( this ); } 510 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }506 virtual UnionInstType * clone() const override { return new UnionInstType( *this ); } 507 virtual void accept( Visitor & v ) override { v.visit( this ); } 508 virtual void accept( Visitor & v ) const override { v.visit( this ); } 509 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 511 510 512 511 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 520 519 // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree, 521 520 // where the enum used in this type is actually defined 522 EnumDecl * baseEnum = nullptr;521 EnumDecl * baseEnum = nullptr; 523 522 524 523 EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {} … … 526 525 EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {} 527 526 528 EnumDecl * get_baseEnum() const { return baseEnum; }529 void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }527 EnumDecl * get_baseEnum() const { return baseEnum; } 528 void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; } 530 529 531 530 virtual bool isComplete() const override; … … 533 532 virtual AggregateDecl * getAggr() const override; 534 533 535 virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }536 virtual void accept( Visitor & v ) override { v.visit( this ); } 537 virtual void accept( Visitor & v ) const override { v.visit( this ); } 538 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }534 virtual EnumInstType * clone() const override { return new EnumInstType( *this ); } 535 virtual void accept( Visitor & v ) override { v.visit( this ); } 536 virtual void accept( Visitor & v ) const override { v.visit( this ); } 537 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 539 538 540 539 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 557 556 virtual bool isComplete() const override; 558 557 559 virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }560 virtual void accept( Visitor & v ) override { v.visit( this ); } 561 virtual void accept( Visitor & v ) const override { v.visit( this ); } 562 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }558 virtual TraitInstType * clone() const override { return new TraitInstType( *this ); } 559 virtual void accept( Visitor & v ) override { v.visit( this ); } 560 virtual void accept( Visitor & v ) const override { v.visit( this ); } 561 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 563 562 private: 564 563 virtual std::string typeString() const override; … … 570 569 // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree, 571 570 // where the type used here is actually defined 572 TypeDecl * baseType;571 TypeDecl * baseType; 573 572 bool isFtype; 574 573 575 TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >() );574 TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 576 575 TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 577 576 TypeInstType( const TypeInstType & other ); 578 577 ~TypeInstType(); 579 578 580 TypeDecl * get_baseType() const { return baseType; }581 void set_baseType( TypeDecl * newValue );579 TypeDecl * get_baseType() const { return baseType; } 580 void set_baseType( TypeDecl * newValue ); 582 581 bool get_isFtype() const { return isFtype; } 583 582 void set_isFtype( bool newValue ) { isFtype = newValue; } … … 585 584 virtual bool isComplete() const override; 586 585 587 virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }588 virtual void accept( Visitor & v ) override { v.visit( this ); } 589 virtual void accept( Visitor & v ) const override { v.visit( this ); } 590 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }586 virtual TypeInstType * clone() const override { return new TypeInstType( *this ); } 587 virtual void accept( Visitor & v ) override { v.visit( this ); } 588 virtual void accept( Visitor & v ) const override { v.visit( this ); } 589 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 591 590 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 592 591 private: … … 623 622 // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness 624 623 625 virtual TupleType * clone() const override { return new TupleType( *this ); }626 virtual void accept( Visitor & v ) override { v.visit( this ); } 627 virtual void accept( Visitor & v ) const override { v.visit( this ); } 628 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }624 virtual TupleType * clone() const override { return new TupleType( *this ); } 625 virtual void accept( Visitor & v ) override { v.visit( this ); } 626 virtual void accept( Visitor & v ) const override { v.visit( this ); } 627 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 629 628 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 630 629 }; … … 632 631 class TypeofType : public Type { 633 632 public: 634 Expression * expr;///< expression to take the type of635 bool is_basetypeof; ///< true iff is basetypeof type636 637 TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );638 TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof,633 Expression * expr; ///< expression to take the type of 634 bool is_basetypeof; ///< true iff is basetypeof type 635 636 TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 637 TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof, 639 638 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 640 639 TypeofType( const TypeofType& ); 641 640 virtual ~TypeofType(); 642 641 643 Expression * get_expr() const { return expr; }644 void set_expr( Expression * newValue ) { expr = newValue; }642 Expression * get_expr() const { return expr; } 643 void set_expr( Expression * newValue ) { expr = newValue; } 645 644 646 645 virtual bool isComplete() const override { assert( false ); return false; } 647 646 648 virtual TypeofType * clone() const override { return new TypeofType( *this ); }649 virtual void accept( Visitor & v ) override { v.visit( this ); } 650 virtual void accept( Visitor & v ) const override { v.visit( this ); } 651 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }647 virtual TypeofType * clone() const override { return new TypeofType( *this ); } 648 virtual void accept( Visitor & v ) override { v.visit( this ); } 649 virtual void accept( Visitor & v ) const override { v.visit( this ); } 650 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 652 651 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 653 652 }; … … 655 654 class VTableType : public Type { 656 655 public: 657 Type * base;658 659 VTableType( const Type::Qualifiers & tq, Type * base,656 Type * base; 657 658 VTableType( const Type::Qualifiers & tq, Type * base, 660 659 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 661 660 VTableType( const VTableType & ); 662 661 virtual ~VTableType(); 663 662 664 Type * get_base() { return base; }665 void set_base( Type * newValue ) { base = newValue; }666 667 virtual VTableType * clone() const override { return new VTableType( *this ); }668 virtual void accept( Visitor & v ) override { v.visit( this ); } 669 virtual void accept( Visitor & v ) const override { v.visit( this ); } 670 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }663 Type * get_base() { return base; } 664 void set_base( Type * newValue ) { base = newValue; } 665 666 virtual VTableType * clone() const override { return new VTableType( *this ); } 667 virtual void accept( Visitor & v ) override { v.visit( this ); } 668 virtual void accept( Visitor & v ) const override { v.visit( this ); } 669 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 671 670 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 672 671 }; … … 675 674 public: 676 675 std::string name; 677 Expression * expr;678 Type * type;676 Expression * expr; 677 Type * type; 679 678 bool isType; 680 679 681 AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );682 AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >() );680 AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 681 AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 683 682 AttrType( const AttrType& ); 684 683 virtual ~AttrType(); … … 686 685 const std::string & get_name() const { return name; } 687 686 void set_name( const std::string & newValue ) { name = newValue; } 688 Expression * get_expr() const { return expr; }689 void set_expr( Expression * newValue ) { expr = newValue; }690 Type * get_type() const { return type; }691 void set_type( Type * newValue ) { type = newValue; }687 Expression * get_expr() const { return expr; } 688 void set_expr( Expression * newValue ) { expr = newValue; } 689 Type * get_type() const { return type; } 690 void set_type( Type * newValue ) { type = newValue; } 692 691 bool get_isType() const { return isType; } 693 692 void set_isType( bool newValue ) { isType = newValue; } … … 695 694 virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here 696 695 697 virtual AttrType * clone() const override { return new AttrType( *this ); }698 virtual void accept( Visitor & v ) override { v.visit( this ); } 699 virtual void accept( Visitor & v ) const override { v.visit( this ); } 700 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }696 virtual AttrType * clone() const override { return new AttrType( *this ); } 697 virtual void accept( Visitor & v ) override { v.visit( this ); } 698 virtual void accept( Visitor & v ) const override { v.visit( this ); } 699 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 701 700 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 702 701 }; … … 710 709 virtual bool isComplete() const override{ return true; } // xxx - is this right? 711 710 712 virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }713 virtual void accept( Visitor & v ) override { v.visit( this ); } 714 virtual void accept( Visitor & v ) const override { v.visit( this ); } 715 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }711 virtual VarArgsType * clone() const override { return new VarArgsType( *this ); } 712 virtual void accept( Visitor & v ) override { v.visit( this ); } 713 virtual void accept( Visitor & v ) const override { v.visit( this ); } 714 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 716 715 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 717 716 }; … … 723 722 ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 724 723 725 virtual ZeroType * clone() const override { return new ZeroType( *this ); }726 virtual void accept( Visitor & v ) override { v.visit( this ); } 727 virtual void accept( Visitor & v ) const override { v.visit( this ); } 728 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }724 virtual ZeroType * clone() const override { return new ZeroType( *this ); } 725 virtual void accept( Visitor & v ) override { v.visit( this ); } 726 virtual void accept( Visitor & v ) const override { v.visit( this ); } 727 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 729 728 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 730 729 }; … … 736 735 OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 737 736 738 virtual OneType * clone() const override { return new OneType( *this ); }739 virtual void accept( Visitor & v ) override { v.visit( this ); } 740 virtual void accept( Visitor & v ) const override { v.visit( this ); } 741 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }737 virtual OneType * clone() const override { return new OneType( *this ); } 738 virtual void accept( Visitor & v ) override { v.visit( this ); } 739 virtual void accept( Visitor & v ) const override { v.visit( this ); } 740 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 742 741 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 743 742 }; … … 747 746 GlobalScopeType(); 748 747 749 virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }750 virtual void accept( Visitor & v ) override { v.visit( this ); } 751 virtual void accept( Visitor & v ) const override { v.visit( this ); } 752 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }748 virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); } 749 virtual void accept( Visitor & v ) override { v.visit( this ); } 750 virtual void accept( Visitor & v ) const override { v.visit( this ); } 751 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 753 752 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 754 753 }; -
src/Tuples/Explode.cc
r34b4268 r24d6572 17 17 #include <list> // for list 18 18 19 #include "AST/Pass.hpp" // for Pass 19 20 #include "SynTree/Mutator.h" // for Mutator 20 21 #include "Common/PassVisitor.h" // for PassVisitor -
src/Validate/Autogen.cpp
r34b4268 r24d6572 25 25 26 26 #include "AST/Attribute.hpp" 27 #include "AST/Copy.hpp" 27 28 #include "AST/Create.hpp" 28 29 #include "AST/Decl.hpp" … … 39 40 #include "InitTweak/GenInit.h" // for fixReturnStatements 40 41 #include "InitTweak/InitTweak.h" // for isAssignment, isCopyConstructor 42 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 41 43 #include "SymTab/Mangler.h" // for Mangler 42 44 #include "CompilationState.h" 43 44 // TODO: The other new ast function should be moved over to this file.45 #include "SymTab/Autogen.h"46 45 47 46 namespace Validate { … … 94 93 95 94 const CodeLocation& getLocation() const { return getDecl()->location; } 96 ast::FunctionDecl * genProto( const std::string& name,95 ast::FunctionDecl * genProto( std::string&& name, 97 96 std::vector<ast::ptr<ast::DeclWithType>>&& params, 98 97 std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const; … … 322 321 void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) { 323 322 assert( nullptr != decl->stmts ); 323 const auto & oldParams = getGenericParams(type); 324 assert( decl->type_params.size() == oldParams.size()); 325 326 /* 327 ast::DeclReplacer::TypeMap typeMap; 328 for (auto it = oldParams.begin(), jt = decl->type_params.begin(); it != oldParams.end(); ++it, ++jt) { 329 typeMap.emplace(*it, *jt); 330 } 331 332 const ast::FunctionDecl * mut = strict_dynamic_cast<const ast::FunctionDecl *>(ast::DeclReplacer::replace(decl, typeMap)); 333 assert (mut == decl); 334 */ 324 335 325 336 definitions.push_back( decl ); … … 335 346 } 336 347 348 void replaceAll( std::vector<ast::ptr<ast::DeclWithType>> & dwts, 349 const ast::DeclReplacer::TypeMap & map ) { 350 for ( auto & dwt : dwts ) { 351 dwt = strict_dynamic_cast<const ast::DeclWithType *>( 352 ast::DeclReplacer::replace( dwt, map ) ); 353 } 354 } 355 337 356 /// Generates a basic prototype function declaration. 338 ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,357 ast::FunctionDecl * FuncGenerator::genProto( std::string&& name, 339 358 std::vector<ast::ptr<ast::DeclWithType>>&& params, 340 359 std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const { … … 342 361 // Handle generic prameters and assertions, if any. 343 362 auto const & old_type_params = getGenericParams( type ); 363 ast::DeclReplacer::TypeMap oldToNew; 344 364 std::vector<ast::ptr<ast::TypeDecl>> type_params; 345 365 std::vector<ast::ptr<ast::DeclWithType>> assertions; 366 367 ast::DeclReplacer::TypeMap typeMap; 346 368 for ( auto & old_param : old_type_params ) { 347 369 ast::TypeDecl * decl = ast::deepCopy( old_param ); 348 for ( auto assertion : decl->assertions ) { 349 assertions.push_back( assertion ); 350 } 351 decl->assertions.clear(); 370 decl->init = nullptr; 371 splice( assertions, decl->assertions ); 372 oldToNew.emplace( std::make_pair( old_param, decl ) ); 352 373 type_params.push_back( decl ); 353 } 354 // TODO: The values in params and returns still may point at the old 355 // generic params, that does not appear to be an issue but perhaps it 356 // should be addressed. 374 typeMap.emplace(old_param, decl); 375 } 376 377 for (auto & param : params) { 378 param = ast::DeclReplacer::replace(param, typeMap); 379 } 380 for (auto & param : returns) { 381 param = ast::DeclReplacer::replace(param, typeMap); 382 } 383 replaceAll( params, oldToNew ); 384 replaceAll( returns, oldToNew ); 385 replaceAll( assertions, oldToNew ); 357 386 358 387 ast::FunctionDecl * decl = new ast::FunctionDecl( 359 388 // Auto-generated routines use the type declaration's location. 360 389 getLocation(), 361 name,390 std::move( name ), 362 391 std::move( type_params ), 363 392 std::move( assertions ), … … 423 452 for ( unsigned int index = 0 ; index < fields ; ++index ) { 424 453 auto member = aggr->members[index].strict_as<ast::DeclWithType>(); 425 if ( SymTab::isUnnamedBitfield(454 if ( ast::isUnnamedBitfield( 426 455 dynamic_cast<const ast::ObjectDecl *>( member ) ) ) { 427 456 if ( index == fields - 1 ) { … … 515 544 InitTweak::InitExpander_new srcParam( src ); 516 545 // Assign to destination. 517 ast:: Expr * dstSelect = new ast::MemberExpr(546 ast::MemberExpr * dstSelect = new ast::MemberExpr( 518 547 location, 519 548 field, … … 567 596 } 568 597 569 ast:: Expr * srcSelect = (srcParam) ? new ast::MemberExpr(598 ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr( 570 599 location, field, new ast::VariableExpr( location, srcParam ) 571 600 ) : nullptr; … … 599 628 // Not sure why it could be null. 600 629 // Don't make a function for a parameter that is an unnamed bitfield. 601 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {630 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) { 602 631 continue; 603 632 // Matching Parameter: Initialize the field by copy. -
src/Validate/FixQualifiedTypes.cpp
r34b4268 r24d6572 16 16 #include "Validate/FixQualifiedTypes.hpp" 17 17 18 #include "AST/Copy.hpp" 19 #include "AST/LinkageSpec.hpp" // for Linkage 18 20 #include "AST/Pass.hpp" 19 21 #include "AST/TranslationUnit.hpp" 22 #include "Common/ToString.hpp" // for toString 23 #include "SymTab/Mangler.h" // for Mangler 20 24 #include "Validate/NoIdSymbolTable.hpp" 21 #include "SymTab/Mangler.h" // for Mangler22 #include "AST/LinkageSpec.hpp" // for Linkage23 25 24 26 namespace Validate { -
src/Validate/FixReturnTypes.cpp
r34b4268 r24d6572 20 20 #include "AST/Type.hpp" 21 21 #include "CodeGen/CodeGenerator.h" 22 #include "ResolvExpr/ typeops.h"22 #include "ResolvExpr/Unify.h" 23 23 24 24 namespace ast { -
src/Validate/ForallPointerDecay.cpp
r34b4268 r24d6572 22 22 #include "CodeGen/OperatorTable.h" 23 23 #include "Common/CodeLocation.h" 24 #include "Common/ToString.hpp" 24 25 #include "SymTab/FixFunction.h" 25 26 -
src/Validate/GenericParameter.cpp
r34b4268 r24d6572 16 16 #include "GenericParameter.hpp" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Decl.hpp" 19 20 #include "AST/Expr.hpp" -
src/Validate/HandleAttributes.cc
r34b4268 r24d6572 17 17 18 18 #include "CompilationState.h" 19 #include "Common/Eval.h" 19 20 #include "Common/PassVisitor.h" 21 #include "Common/ToString.hpp" 20 22 #include "Common/SemanticError.h" 21 23 #include "ResolvExpr/Resolver.h" -
src/Validate/HoistStruct.cpp
r34b4268 r24d6572 16 16 #include "Validate/HoistStruct.hpp" 17 17 18 #include <sstream> 19 18 20 #include "AST/Pass.hpp" 19 21 #include "AST/TranslationUnit.hpp" 20 #include "Common/utility.h"21 22 22 23 namespace Validate { -
src/Validate/ReplaceTypedef.cpp
r34b4268 r24d6572 16 16 #include "ReplaceTypedef.hpp" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Pass.hpp" 19 20 #include "Common/ScopedMap.h" 20 21 #include "Common/UniqueName.h" 21 22 #include "Common/utility.h" 22 #include "ResolvExpr/ typeops.h"23 #include "ResolvExpr/Unify.h" 23 24 24 25 namespace Validate { … … 149 150 // constant/enumerator. The effort required to fix this corner case 150 151 // likely outweighs the utility of allowing it. 151 if ( !ResolvExpr::typesCompatible( t0, t1 , ast::SymbolTable())152 if ( !ResolvExpr::typesCompatible( t0, t1 ) 152 153 || ast::Pass<VarLenChecker>::read( t0 ) 153 154 || ast::Pass<VarLenChecker>::read( t1 ) ) { … … 186 187 187 188 void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) { 188 TypedefMap::iterator iter = typedefNames.find( decl->name ); 189 if ( iter != typedefNames.end() ) { 190 typedefNames.erase( iter ); 191 } 189 typedefNames.erase( decl->name ); 192 190 typedeclNames.insert( decl->name, decl ); 193 191 } -
src/Virtual/ExpandCasts.cc
r34b4268 r24d6572 20 20 #include <string> // for string, allocator, operator==, ope... 21 21 22 #include "AST/Copy.hpp" 22 23 #include "AST/Decl.hpp" 23 24 #include "AST/Expr.hpp" -
src/Virtual/module.mk
r34b4268 r24d6572 19 19 Virtual/ExpandCasts.h \ 20 20 Virtual/Tables.cc \ 21 Virtual/Tables.h 21 Virtual/Tables.h \ 22 Virtual/VirtualDtor.cpp \ 23 Virtual/VirtualDtor.hpp -
src/include/cassert
r34b4268 r24d6572 20 20 #include_next <cassert> 21 21 22 #include <string> 23 24 template < typename ... Params > 25 std::string toString( const Params & ... params ); 22 #include "Common/ToString.hpp" 26 23 27 24 #ifdef NDEBUG -
src/main.cc
r34b4268 r24d6572 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Oct 5 12:06:00 202213 // Update Count : 6 7911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 21:12:17 2023 13 // Update Count : 682 14 14 // 15 15 … … 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Pass.hpp" // for pass_visitor_stats 35 #include "AST/TranslationUnit.hpp" // for TranslationUnit 36 #include "AST/Util.hpp" // for checkInvariants 34 37 #include "CompilationState.h" 35 38 #include "../config.h" // for CFA_LIBDIR … … 40 43 #include "CodeTools/TrackLoc.h" // for fillLocations 41 44 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 42 #include "Common/CompilerError.h" // for CompilerError43 45 #include "Common/DeclStats.hpp" // for printDeclStats 44 46 #include "Common/ResolvProtoDump.hpp" // for dumpAsResolverProto 45 47 #include "Common/Stats.h" // for Stats 46 #include "Common/UnimplementedError.h" // for UnimplementedError47 48 #include "Common/utility.h" // for deleteAll, filter, printAll 49 #include "Concurrency/Actors.hpp" // for implementActors 48 50 #include "Concurrency/Keywords.h" // for implementMutex, implement... 49 51 #include "Concurrency/Waitfor.h" // for generateWaitfor 52 #include "Concurrency/Waituntil.hpp" // for generateWaitUntil 50 53 #include "ControlStruct/ExceptDecl.h" // for translateExcept 51 54 #include "ControlStruct/ExceptTranslate.h" // for translateThrows, translat... … … 59 62 #include "InitTweak/GenInit.h" // for genInit 60 63 #include "MakeLibCfa.h" // for makeLibCfa 61 #include "Parser/ParseNode.h" // for DeclarationNode, buildList 62 #include "Parser/TypedefTable.h" // for TypedefTable 64 #include "Parser/RunParser.hpp" // for buildList, dumpParseTree,... 63 65 #include "ResolvExpr/CandidatePrinter.hpp" // for printCandidates 64 66 #include "ResolvExpr/Resolver.h" // for resolve … … 84 86 #include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign 85 87 #include "Virtual/ExpandCasts.h" // for expandCasts 88 #include "Virtual/VirtualDtor.hpp" // for implementVirtDtors 86 89 87 90 static void NewPass( const char * const name ) { … … 102 105 } 103 106 104 #define PASS( name, pass ) \ 107 // Helpers for checkInvariant: 108 void checkInvariants( std::list< Declaration * > & ) {} 109 using ast::checkInvariants; 110 111 #define PASS( name, pass, unit, ... ) \ 105 112 if ( errorp ) { cerr << name << endl; } \ 106 113 NewPass(name); \ 107 114 Stats::Time::StartBlock(name); \ 108 pass; \ 109 Stats::Time::StopBlock(); 110 111 LinkageSpec::Spec linkage = LinkageSpec::Cforall; 112 TypedefTable typedefTable; 113 DeclarationNode * parseTree = nullptr; // program parse tree 115 pass(unit,##__VA_ARGS__); \ 116 Stats::Time::StopBlock(); \ 117 if ( invariant ) { \ 118 checkInvariants(unit); \ 119 } 120 121 #define DUMP( cond, unit ) \ 122 if ( cond ) { \ 123 dump(unit); \ 124 return EXIT_SUCCESS; \ 125 } 114 126 115 127 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start … … 118 130 119 131 static void parse_cmdline( int argc, char * argv[] ); 120 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );121 132 static void dump( list< Declaration * > & translationUnit, ostream & out = cout ); 122 133 static void dump( ast::TranslationUnit && transUnit, ostream & out = cout ); … … 234 245 ostream * output = & cout; 235 246 list< Declaration * > translationUnit; 247 ast::TranslationUnit transUnit; 236 248 237 249 Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO ); … … 278 290 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" ); 279 291 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 280 parse( gcc_builtins, LinkageSpec::Compiler );292 parse( gcc_builtins, ast::Linkage::Compiler ); 281 293 282 294 // read the extra prelude in, if not generating the cfa library 283 295 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" ); 284 296 assertf( extras, "cannot open extras.cf\n" ); 285 parse( extras, LinkageSpec::BuiltinC );297 parse( extras, ast::Linkage::BuiltinC ); 286 298 287 299 if ( ! libcfap ) { … … 289 301 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" ); 290 302 assertf( prelude, "cannot open prelude.cfa\n" ); 291 parse( prelude, LinkageSpec::Intrinsic );303 parse( prelude, ast::Linkage::Intrinsic ); 292 304 293 305 // Read to cfa builtins, if not generating the cfa library 294 306 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" ); 295 307 assertf( builtins, "cannot open builtins.cf\n" ); 296 parse( builtins, LinkageSpec::BuiltinCFA ); 297 } // if 298 } // if 299 300 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug ); 301 302 if ( parsep ) { 303 parseTree->printList( cout ); 304 delete parseTree; 305 return EXIT_SUCCESS; 306 } // if 307 308 buildList( parseTree, translationUnit ); 309 delete parseTree; 310 parseTree = nullptr; 311 312 if ( astp ) { 313 dump( translationUnit ); 314 return EXIT_SUCCESS; 315 } // if 316 317 // Temporary: fill locations after parsing so that every node has a location, for early error messages. 318 // Eventually we should pass the locations from the parser to every node, but this quick and dirty solution 319 // works okay for now. 320 CodeTools::fillLocations( translationUnit ); 308 parse( builtins, ast::Linkage::BuiltinCFA ); 309 } // if 310 } // if 311 312 parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug ); 313 314 transUnit = buildUnit(); 315 316 DUMP( astp, std::move( transUnit ) ); 317 321 318 Stats::Time::StopBlock(); 322 319 … … 325 322 ast::pass_visitor_stats.max = Stats::Counters::build<Stats::Counters::MaxCounter<double>>("Max depth - New"); 326 323 } 327 auto transUnit = convert( std::move( translationUnit ) ); 328 329 forceFillCodeLocations( transUnit ); 330 331 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) ); 332 if ( exdeclp ) { 333 dump( std::move( transUnit ) ); 334 return EXIT_SUCCESS; 335 } 336 337 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) ); 338 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) ); 339 // Hoist Type Decls pulls some declarations out of contexts where 340 // locations are not tracked. Perhaps they should be, but for now 341 // the full fill solves it. 342 forceFillCodeLocations( transUnit ); 343 344 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) ); 345 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) ); 346 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) ); 347 348 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) ); 349 350 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) ); 351 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) ); 352 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) ); 353 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) ); 354 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) ); 355 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) ); 356 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) ); 357 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 358 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 359 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) ); 360 361 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) ); 362 363 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 364 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); 365 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) ); 366 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) ); 367 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) ); 368 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) ); 324 325 PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit ); 326 327 PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit ); 328 DUMP( exdeclp, std::move( transUnit ) ); 329 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit ); 330 PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit ); 331 PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit ); 332 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit ); 333 334 PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit ); 335 336 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit ); 337 PASS( "Hoist Struct", Validate::hoistStruct, transUnit ); 338 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit ); 339 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit ); 340 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit ); 341 PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit ); 342 PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit ); 343 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit ); 344 PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit ); 345 PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit ); 346 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit ); 347 348 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit ); 349 350 PASS( "Implement Actors", Concurrency::implementActors, transUnit ); 351 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit ); 352 PASS( "Implement Mutex", Concurrency::implementMutex, transUnit ); 353 PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit ); 354 PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit ); 355 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit ); 356 PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit ); 357 PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit ); 369 358 370 359 if ( symtabp ) { … … 377 366 } // if 378 367 379 if ( validp ) { 380 dump( std::move( transUnit ) ); 381 return EXIT_SUCCESS; 382 } // if 383 384 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) ); 385 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) ); 386 PASS( "Fix Names", CodeGen::fixNames( transUnit ) ); 387 PASS( "Gen Init", InitTweak::genInit( transUnit ) ); 388 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) ); 368 DUMP( validp, std::move( transUnit ) ); 369 370 PASS( "Translate Throws", ControlStruct::translateThrows, transUnit ); 371 PASS( "Fix Labels", ControlStruct::fixLabels, transUnit ); 372 PASS( "Fix Names", CodeGen::fixNames, transUnit ); 373 PASS( "Gen Init", InitTweak::genInit, transUnit ); 374 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit ); 389 375 390 376 if ( libcfap ) { … … 398 384 } // if 399 385 400 if ( bresolvep ) { 401 dump( std::move( transUnit ) ); 402 return EXIT_SUCCESS; 403 } // if 386 DUMP( bresolvep, std::move( transUnit ) ); 404 387 405 388 if ( resolvprotop ) { … … 408 391 } // if 409 392 410 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 411 if ( exprp ) { 412 dump( std::move( transUnit ) ); 413 return EXIT_SUCCESS; 414 } // if 415 416 forceFillCodeLocations( transUnit ); 417 418 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary())); 393 PASS( "Resolve", ResolvExpr::resolve, transUnit ); 394 DUMP( exprp, std::move( transUnit ) ); 395 396 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 419 397 420 398 // fix ObjectDecl - replaces ConstructorInit nodes 421 if ( ctorinitp ) { 422 dump( std::move( transUnit ) ); 423 return EXIT_SUCCESS; 424 } // if 399 DUMP( ctorinitp, std::move( transUnit ) ); 425 400 426 401 // Currently not working due to unresolved issues with UniqueExpr 427 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr ( transUnit )); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused428 429 PASS( "Translate Tries", ControlStruct::translateTries ( transUnit ));430 PASS( "Gen Waitfor", Concurrency::generateWaitFor ( transUnit ));402 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr, transUnit ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 403 404 PASS( "Translate Tries", ControlStruct::translateTries, transUnit ); 405 PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit ); 431 406 432 407 // Needs to happen before tuple types are expanded. 433 PASS( "Convert Specializations", GenPoly::convertSpecializations( transUnit ) ); 434 435 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 436 437 if ( tuplep ) { 438 dump( std::move( transUnit ) ); 439 return EXIT_SUCCESS; 440 } // if 408 PASS( "Convert Specializations", GenPoly::convertSpecializations, transUnit ); 409 410 PASS( "Expand Tuples", Tuples::expandTuples, transUnit ); 411 DUMP( tuplep, std::move( transUnit ) ); 441 412 442 413 // Must come after Translate Tries. 443 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) ); 444 445 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) ); 446 if ( genericsp ) { 447 dump( std::move( transUnit ) ); 448 return EXIT_SUCCESS; 449 } // if 450 451 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) ); 414 PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit ); 415 416 PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit ); 417 DUMP( genericsp, std::move( transUnit ) ); 418 419 PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit ); 452 420 453 421 translationUnit = convert( std::move( transUnit ) ); 454 422 455 if ( bboxp ) { 456 dump( translationUnit ); 457 return EXIT_SUCCESS; 458 } // if 459 PASS( "Box", GenPoly::box( translationUnit ) ); 460 461 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) ); 423 DUMP( bboxp, translationUnit ); 424 PASS( "Box", GenPoly::box, translationUnit ); 425 426 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit ); 462 427 463 428 // Code has been lowered to C, now we can start generation. 464 429 465 if ( bcodegenp ) { 466 dump( translationUnit ); 467 return EXIT_SUCCESS; 468 } // if 430 DUMP( bcodegenp, translationUnit ); 469 431 470 432 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 473 435 474 436 CodeTools::fillLocations( translationUnit ); 475 PASS( "Code Gen", CodeGen::generate ( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ));437 PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ); 476 438 477 439 CodeGen::FixMain::fix( translationUnit, *output, … … 483 445 if ( errorp ) { 484 446 cerr << "---AST at error:---" << endl; 485 dump( translationUnit, cerr ); 447 // We check which section the errors came from without looking at 448 // transUnit because std::move means it could look like anything. 449 if ( !translationUnit.empty() ) { 450 dump( translationUnit, cerr ); 451 } else { 452 dump( std::move( transUnit ), cerr ); 453 } 486 454 cerr << endl << "---End of AST, begin error message:---\n" << endl; 487 455 } // if 488 456 e.print(); 489 if ( output != &cout ) {490 delete output;491 } // if492 return EXIT_FAILURE;493 } catch ( UnimplementedError & e ) {494 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;495 if ( output != &cout ) {496 delete output;497 } // if498 return EXIT_FAILURE;499 } catch ( CompilerError & e ) {500 cerr << "Compiler Error: " << e.get_what() << endl;501 cerr << "(please report bugs to [REDACTED])" << endl;502 457 if ( output != &cout ) { 503 458 delete output; … … 528 483 529 484 530 static const char optstring[] = ":c:gh lLmNnpdP:S:twW:D:";485 static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:"; 531 486 532 487 enum { PreludeDir = 128 }; … … 535 490 { "gdb", no_argument, nullptr, 'g' }, 536 491 { "help", no_argument, nullptr, 'h' }, 492 { "invariant", no_argument, nullptr, 'i' }, 537 493 { "libcfa", no_argument, nullptr, 'l' }, 538 494 { "linemarks", no_argument, nullptr, 'L' }, 539 { "no-main", no_argument, 0, 'm' },495 { "no-main", no_argument, nullptr, 'm' }, 540 496 { "no-linemarks", no_argument, nullptr, 'N' }, 541 497 { "no-prelude", no_argument, nullptr, 'n' }, … … 556 512 "wait for gdb to attach", // -g 557 513 "print translator help message", // -h 514 "invariant checking during AST passes", // -i 558 515 "generate libcfa.c", // -l 559 516 "generate line marks", // -L … … 587 544 { "rproto", resolvprotop, true, "resolver-proto instance" }, 588 545 { "rsteps", resolvep, true, "print resolver steps" }, 589 { "tree", parsep, true, "print parse tree" },590 546 // code dumps 591 547 { "ast", astp, true, "print AST after parsing" }, … … 650 606 usage( argv ); // no return 651 607 break; 608 case 'i': // invariant checking 609 invariant = true; 610 break; 652 611 case 'l': // generate libcfa.c 653 612 libcfap = true; … … 748 707 } // parse_cmdline 749 708 750 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit ) {751 extern int yyparse( void );752 extern FILE * yyin;753 extern int yylineno;754 755 ::linkage = linkage; // set globals756 yyin = input;757 yylineno = 1;758 int parseStatus = yyparse();759 760 fclose( input );761 if ( shouldExit || parseStatus != 0 ) {762 exit( parseStatus );763 } // if764 } // parse765 766 709 static bool notPrelude( Declaration * decl ) { 767 710 return ! LinkageSpec::isBuiltin( decl->get_linkage() ); -
tests/.expect/PRNG.x64.txt
r34b4268 r24d6572 1 1 2 PRNG() PRNG(5) PRNG(0,5) 3 861 3 0 4 10137507171299805328 1 2 5 12205946788447993741 4 0 6 16222929371023265189 2 5 7 11921944259646500358 1 1 8 9511863719043198063 2 0 9 18170109536749574203 0 1 10 15896208456307578543 0 3 11 4171113079117645375 1 4 12 5535309872453329531 1 1 13 13293369315461644140 2 2 14 855811942427900360 1 1 15 9125507373316195824 1 5 16 6942856496042419510 1 5 17 16774706561877323900 2 4 18 17765436951300330249 4 0 19 3766082030894719812 1 2 20 15818141700523398820 3 5 21 1244962761353699441 0 5 22 4506898200126256218 1 2 2 CFA xoshiro256pp 3 4 PRNG() PRNG(5) PRNG(0,5) 5 13944458589275087071 3 2 6 129977468648444256 0 4 7 2357727400298891021 2 2 8 8855179187835660146 3 3 9 9957620185645882382 4 1 10 13396406983727409795 0 5 11 3342782395220265920 0 5 12 1707651271867677937 1 0 13 16402561450140881681 0 1 14 17838519215740313729 4 2 15 7425936020594490136 4 0 16 4174865704721714670 3 5 17 16055269689200152092 0 2 18 15091270195803594018 1 5 19 11807315541476180798 1 1 20 10697186588988060306 4 1 21 14665526411527044929 3 2 22 11289342279096164771 2 5 23 16126980828050300615 1 4 24 7821578301767524260 4 1 23 25 seed 1009 24 26 25 27 Sequential 26 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%28 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 27 29 28 30 Concurrent 29 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%30 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%31 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%32 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%31 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 32 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 33 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 34 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 33 35 34 prng() prng(5)prng(0,5)35 861 3 036 10137507171299805328 1 2 37 12205946788447993741 4 0 38 16222929371023265189 2 5 39 11921944259646500358 1140 9511863719043198063 2 0 41 18170109536749574203 0 1 42 15896208456307578543 0 3 43 4171113079117645375 1 4 44 5535309872453329531 1 1 45 13293369315461644140 2 2 46 855811942427900360 1 1 47 9125507373316195824 1 5 48 6942856496042419510 1549 16774706561877323900 2 4 50 17765436951300330249 4 0 51 3766082030894719812 1252 15818141700523398820 3553 1244962761353699441 0 5 54 4506898200126256218 1 2 36 prng() prng(5) prng(0,5) 37 13944458589275087071 3 2 38 129977468648444256 0 4 39 2357727400298891021 2 2 40 8855179187835660146 3 3 41 9957620185645882382 4 1 42 13396406983727409795 0 5 43 3342782395220265920 0 5 44 1707651271867677937 1 0 45 16402561450140881681 0 1 46 17838519215740313729 4 2 47 7425936020594490136 4 0 48 4174865704721714670 3 5 49 16055269689200152092 0 2 50 15091270195803594018 1 5 51 11807315541476180798 1 1 52 10697186588988060306 4 1 53 14665526411527044929 3 2 54 11289342279096164771 2 5 55 16126980828050300615 1 4 56 7821578301767524260 4 1 55 57 seed 1009 56 58 57 59 Sequential 58 trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%60 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 59 61 60 62 Concurrent 61 trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%62 trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%63 trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%64 trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%63 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 64 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 65 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 66 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 65 67 66 prng(t) prng(t,5)prng(t,0,5)67 861 3 068 10137507171299805328 1 2 69 12205946788447993741 4 0 70 16222929371023265189 2 5 71 11921944259646500358 1172 9511863719043198063 2 0 73 18170109536749574203 0 1 74 15896208456307578543 0 3 75 4171113079117645375 1 4 76 5535309872453329531 1 1 77 13293369315461644140 2 2 78 855811942427900360 1 1 79 9125507373316195824 1 5 80 6942856496042419510 1581 16774706561877323900 2 4 82 17765436951300330249 4 0 83 3766082030894719812 1284 15818141700523398820 3585 1244962761353699441 0 5 86 4506898200126256218 1 2 68 prng(t) prng(t,5) prng(t,0,5) 69 13944458589275087071 3 2 70 129977468648444256 0 4 71 2357727400298891021 2 2 72 8855179187835660146 3 3 73 9957620185645882382 4 1 74 13396406983727409795 0 5 75 3342782395220265920 0 5 76 1707651271867677937 1 0 77 16402561450140881681 0 1 78 17838519215740313729 4 2 79 7425936020594490136 4 0 80 4174865704721714670 3 5 81 16055269689200152092 0 2 82 15091270195803594018 1 5 83 11807315541476180798 1 1 84 10697186588988060306 4 1 85 14665526411527044929 3 2 86 11289342279096164771 2 5 87 16126980828050300615 1 4 88 7821578301767524260 4 1 87 89 seed 1009 88 90 89 91 Sequential 90 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%92 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 91 93 92 94 Concurrent 93 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%94 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%95 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%96 trials 100000000 buckets 100000 min 875 max 11 38 avg 1000.0 std 31.8rstd 3.2%95 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 96 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 97 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 98 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% -
tests/.expect/PRNG.x86.txt
r34b4268 r24d6572 1 1 2 PRNG() PRNG(5) PRNG(0,5) 3 8333105 1 2 4 1989339636 4 5 5 266970699 3 2 6 1928130121 3 4 7 1351003938 4 5 8 1624164922 4 3 9 363429604 1 2 10 3355083174 1 1 11 214422584 1 1 12 2266729947 1 2 13 3649702519 2 4 14 2250875012 2 4 15 4184653025 1 3 16 2640851227 2 5 17 206468178 2 3 18 2600873108 1 3 19 3007574582 3 3 20 394476790 0 2 21 1312145388 1 5 22 2989081290 2 4 2 CFA xoshiro128pp 3 4 PRNG() PRNG(5) PRNG(0,5) 5 2884683541 0 0 6 3465286746 2 4 7 3268922916 0 1 8 2396374907 3 0 9 2135076892 4 1 10 944377718 3 1 11 2204845346 3 3 12 3736609533 0 4 13 4063231336 0 2 14 1075394776 0 2 15 712844808 4 0 16 4246343110 3 1 17 3793873837 2 1 18 3690340337 1 4 19 319207944 1 4 20 1815791072 3 5 21 2581617261 1 5 22 3873329448 1 3 23 832631329 4 0 24 651551615 3 5 23 25 seed 1009 24 26 25 27 Sequential 26 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%28 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 27 29 28 30 Concurrent 29 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%30 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%31 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%32 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%31 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 32 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 33 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 34 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 33 35 34 prng() prng(5)prng(0,5)35 8333105 1 236 1989339636 4 537 266970699 3 238 1928130121 3 439 1351003938 4 540 1624164922 4 341 363429604 1 242 3355083174 1 143 214422584 1 144 2266729947 1245 3649702519 2 446 2250875012 2 447 4184653025 1 348 2640851227 2 549 206468178 2 350 2600873108 1 351 3007574582 3 352 394476790 0 253 1312145388 1 554 2989081290 2 436 prng() prng(5) prng(0,5) 37 2884683541 0 0 38 3465286746 2 4 39 3268922916 0 1 40 2396374907 3 0 41 2135076892 4 1 42 944377718 3 1 43 2204845346 3 3 44 3736609533 0 4 45 4063231336 0 2 46 1075394776 0 2 47 712844808 4 0 48 4246343110 3 1 49 3793873837 2 1 50 3690340337 1 4 51 319207944 1 4 52 1815791072 3 5 53 2581617261 1 5 54 3873329448 1 3 55 832631329 4 0 56 651551615 3 5 55 57 seed 1009 56 58 57 59 Sequential 58 trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%60 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 59 61 60 62 Concurrent 61 trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%62 trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%63 trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%64 trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%63 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 64 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 65 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 66 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 65 67 66 prng(t) prng(t,5)prng(t,0,5)67 8333105 1 268 1989339636 4 569 266970699 3 270 1928130121 3 471 1351003938 4 572 1624164922 4 373 363429604 1 274 3355083174 1 175 214422584 1 176 2266729947 1277 3649702519 2 478 2250875012 2 479 4184653025 1 380 2640851227 2 581 206468178 2 382 2600873108 1 383 3007574582 3 384 394476790 0 285 1312145388 1 586 2989081290 2 468 prng(t) prng(t,5) prng(t,0,5) 69 2884683541 0 0 70 3465286746 2 4 71 3268922916 0 1 72 2396374907 3 0 73 2135076892 4 1 74 944377718 3 1 75 2204845346 3 3 76 3736609533 0 4 77 4063231336 0 2 78 1075394776 0 2 79 712844808 4 0 80 4246343110 3 1 81 3793873837 2 1 82 3690340337 1 4 83 319207944 1 4 84 1815791072 3 5 85 2581617261 1 5 86 3873329448 1 3 87 832631329 4 0 88 651551615 3 5 87 89 seed 1009 88 90 89 91 Sequential 90 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%92 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 91 93 92 94 Concurrent 93 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%94 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%95 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%96 trials 100000000 buckets 100000 min 8 73 max 1140 avg 1000.0 std 31.3 rstd 3.1%95 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 96 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 97 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 98 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% -
tests/.expect/array.txt
r34b4268 r24d6572 1 array.cfa: 52:25: warning: Compiled1 array.cfa:119:25: warning: Preprocessor started -
tests/.expect/attributes.arm64.txt
r34b4268 r24d6572 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st ruct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1; 29 29 struct __attribute__ ((unused)) Agn1; 30 30 struct __attribute__ ((unused)) Agn2 { … … 1351 1351 signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0)); 1352 1352 signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)()); 1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)( signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/attributes.x64.txt
r34b4268 r24d6572 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st ruct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1; 29 29 struct __attribute__ ((unused)) Agn1; 30 30 struct __attribute__ ((unused)) Agn2 { … … 1351 1351 signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0)); 1352 1352 signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)()); 1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)( signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/attributes.x86.txt
r34b4268 r24d6572 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st ruct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1; 29 29 struct __attribute__ ((unused)) Agn1; 30 30 struct __attribute__ ((unused)) Agn2 { … … 1351 1351 signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0)); 1352 1352 signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)()); 1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)( signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/declarationSpecifier.arm64.txt
r34b4268 r24d6572 51 51 52 52 } 53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1; 144 144 struct __anonymous3 { 145 145 signed int _X1ii_1; … … 322 322 } 323 323 static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1; 324 struct __anonymous7 {325 signed int _X1ii_1;326 };327 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);328 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);329 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);330 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);331 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);332 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){333 {334 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);335 }336 337 }338 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){339 {340 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);341 }342 343 }344 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){345 {346 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);347 }348 349 }350 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){351 struct __anonymous7 _X4_retS12__anonymous7_1;352 {353 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));354 }355 356 {357 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));358 }359 360 return _X4_retS12__anonymous7_1;361 }362 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){363 {364 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);365 }366 367 }368 static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;369 324 volatile const signed short int _X3x20KVs_1; 370 325 static volatile const signed short int _X3x21KVs_1; … … 375 330 static volatile const signed short int _X3x26KVs_1; 376 331 static volatile const signed short int _X3x27KVs_1; 332 struct __anonymous7 { 333 signed short int _X1is_1; 334 }; 335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1); 340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 341 { 342 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */); 343 } 344 345 } 346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 347 { 348 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */); 349 } 350 351 } 352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 353 { 354 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */); 355 } 356 357 } 358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 359 struct __anonymous7 _X4_retS12__anonymous7_1; 360 { 361 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1)); 362 } 363 364 { 365 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1))); 366 } 367 368 return _X4_retS12__anonymous7_1; 369 } 370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){ 371 { 372 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */); 373 } 374 375 } 376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1; 377 377 struct __anonymous8 { 378 378 signed short int _X1is_1; … … 419 419 420 420 } 421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 2KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 3KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1; 647 struct __anonymous14 { 648 signed short int _X1is_1; 649 }; 650 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 651 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 652 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 653 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 654 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1); 655 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 656 { 657 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */); 658 } 659 660 } 661 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 662 { 663 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */); 664 } 665 666 } 667 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 668 { 669 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */); 670 } 671 672 } 673 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 674 struct __anonymous14 _X4_retS13__anonymous14_1; 675 { 676 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1)); 677 } 678 679 { 680 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 681 } 682 683 return _X4_retS13__anonymous14_1; 684 } 685 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */); 688 } 689 690 } 691 static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1; 692 struct __anonymous15 { 693 signed short int _X1is_1; 694 }; 695 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 696 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 697 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 698 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 699 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1); 700 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 701 { 702 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */); 703 } 704 705 } 706 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 707 { 708 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */); 709 } 710 711 } 712 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 713 { 714 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */); 715 } 716 717 } 718 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 719 struct __anonymous15 _X4_retS13__anonymous15_1; 720 { 721 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1)); 722 } 723 724 { 725 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 726 } 727 728 return _X4_retS13__anonymous15_1; 729 } 730 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */); 733 } 734 735 } 736 static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1; 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 737 647 _Thread_local signed int _X3x37i_1; 738 648 __thread signed int _X3x38i_1; … … 753 663 static inline volatile const signed short int _X3f27Fs___1(); 754 664 static inline volatile const signed short int _X3f28Fs___1(); 665 struct __anonymous14 { 666 signed int _X1ii_1; 667 }; 668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1); 673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 674 { 675 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */); 676 } 677 678 } 679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 680 { 681 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */); 682 } 683 684 } 685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */); 688 } 689 690 } 691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 692 struct __anonymous14 _X4_retS13__anonymous14_1; 693 { 694 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1)); 695 } 696 697 { 698 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 699 } 700 701 return _X4_retS13__anonymous14_1; 702 } 703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){ 704 { 705 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */); 706 } 707 708 } 709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1(); 710 struct __anonymous15 { 711 signed int _X1ii_1; 712 }; 713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1); 718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 719 { 720 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */); 721 } 722 723 } 724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 725 { 726 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */); 727 } 728 729 } 730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */); 733 } 734 735 } 736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 737 struct __anonymous15 _X4_retS13__anonymous15_1; 738 { 739 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1)); 740 } 741 742 { 743 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 744 } 745 746 return _X4_retS13__anonymous15_1; 747 } 748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){ 749 { 750 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */); 751 } 752 753 } 754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1(); 755 755 struct __anonymous16 { 756 756 signed int _X1ii_1; … … 797 797 798 798 } 799 static inline volatile const struct __anonymous16 _X3f3 1FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 2FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 3FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 4FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 5FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1(); 1025 struct __anonymous22 { 1026 signed int _X1ii_1; 1027 }; 1028 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1029 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1030 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1031 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1032 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1); 1033 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1034 { 1035 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */); 1036 } 1037 1038 } 1039 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1040 { 1041 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */); 1042 } 1043 1044 } 1045 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1046 { 1047 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */); 1048 } 1049 1050 } 1051 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1052 struct __anonymous22 _X4_retS13__anonymous22_1; 1053 { 1054 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1)); 1055 } 1056 1057 { 1058 ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1))); 1059 } 1060 1061 return _X4_retS13__anonymous22_1; 1062 } 1063 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){ 1064 { 1065 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */); 1066 } 1067 1068 } 1069 static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1(); 1070 struct __anonymous23 { 1071 signed int _X1ii_1; 1072 }; 1073 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1074 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1075 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1076 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1077 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1); 1078 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1079 { 1080 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */); 1081 } 1082 1083 } 1084 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1085 { 1086 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */); 1087 } 1088 1089 } 1090 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1091 { 1092 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */); 1093 } 1094 1095 } 1096 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1097 struct __anonymous23 _X4_retS13__anonymous23_1; 1098 { 1099 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1)); 1100 } 1101 1102 { 1103 ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1))); 1104 } 1105 1106 return _X4_retS13__anonymous23_1; 1107 } 1108 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){ 1109 { 1110 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */); 1111 } 1112 1113 } 1114 static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1(); 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 1115 1025 static inline volatile const signed short int _X3f41Fs___1(); 1116 1026 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/declarationSpecifier.x64.txt
r34b4268 r24d6572 51 51 52 52 } 53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1; 144 144 struct __anonymous3 { 145 145 signed int _X1ii_1; … … 322 322 } 323 323 static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1; 324 struct __anonymous7 {325 signed int _X1ii_1;326 };327 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);328 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);329 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);330 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);331 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);332 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){333 {334 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);335 }336 337 }338 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){339 {340 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);341 }342 343 }344 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){345 {346 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);347 }348 349 }350 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){351 struct __anonymous7 _X4_retS12__anonymous7_1;352 {353 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));354 }355 356 {357 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));358 }359 360 return _X4_retS12__anonymous7_1;361 }362 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){363 {364 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);365 }366 367 }368 static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;369 324 volatile const signed short int _X3x20KVs_1; 370 325 static volatile const signed short int _X3x21KVs_1; … … 375 330 static volatile const signed short int _X3x26KVs_1; 376 331 static volatile const signed short int _X3x27KVs_1; 332 struct __anonymous7 { 333 signed short int _X1is_1; 334 }; 335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1); 340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 341 { 342 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */); 343 } 344 345 } 346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 347 { 348 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */); 349 } 350 351 } 352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 353 { 354 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */); 355 } 356 357 } 358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 359 struct __anonymous7 _X4_retS12__anonymous7_1; 360 { 361 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1)); 362 } 363 364 { 365 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1))); 366 } 367 368 return _X4_retS12__anonymous7_1; 369 } 370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){ 371 { 372 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */); 373 } 374 375 } 376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1; 377 377 struct __anonymous8 { 378 378 signed short int _X1is_1; … … 419 419 420 420 } 421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 2KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 3KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1; 647 struct __anonymous14 { 648 signed short int _X1is_1; 649 }; 650 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 651 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 652 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 653 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 654 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1); 655 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 656 { 657 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */); 658 } 659 660 } 661 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 662 { 663 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */); 664 } 665 666 } 667 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 668 { 669 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */); 670 } 671 672 } 673 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 674 struct __anonymous14 _X4_retS13__anonymous14_1; 675 { 676 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1)); 677 } 678 679 { 680 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 681 } 682 683 return _X4_retS13__anonymous14_1; 684 } 685 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */); 688 } 689 690 } 691 static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1; 692 struct __anonymous15 { 693 signed short int _X1is_1; 694 }; 695 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 696 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 697 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 698 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 699 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1); 700 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 701 { 702 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */); 703 } 704 705 } 706 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 707 { 708 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */); 709 } 710 711 } 712 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 713 { 714 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */); 715 } 716 717 } 718 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 719 struct __anonymous15 _X4_retS13__anonymous15_1; 720 { 721 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1)); 722 } 723 724 { 725 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 726 } 727 728 return _X4_retS13__anonymous15_1; 729 } 730 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */); 733 } 734 735 } 736 static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1; 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 737 647 _Thread_local signed int _X3x37i_1; 738 648 __thread signed int _X3x38i_1; … … 753 663 static inline volatile const signed short int _X3f27Fs___1(); 754 664 static inline volatile const signed short int _X3f28Fs___1(); 665 struct __anonymous14 { 666 signed int _X1ii_1; 667 }; 668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1); 673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 674 { 675 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */); 676 } 677 678 } 679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 680 { 681 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */); 682 } 683 684 } 685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */); 688 } 689 690 } 691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 692 struct __anonymous14 _X4_retS13__anonymous14_1; 693 { 694 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1)); 695 } 696 697 { 698 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 699 } 700 701 return _X4_retS13__anonymous14_1; 702 } 703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){ 704 { 705 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */); 706 } 707 708 } 709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1(); 710 struct __anonymous15 { 711 signed int _X1ii_1; 712 }; 713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1); 718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 719 { 720 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */); 721 } 722 723 } 724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 725 { 726 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */); 727 } 728 729 } 730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */); 733 } 734 735 } 736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 737 struct __anonymous15 _X4_retS13__anonymous15_1; 738 { 739 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1)); 740 } 741 742 { 743 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 744 } 745 746 return _X4_retS13__anonymous15_1; 747 } 748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){ 749 { 750 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */); 751 } 752 753 } 754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1(); 755 755 struct __anonymous16 { 756 756 signed int _X1ii_1; … … 797 797 798 798 } 799 static inline volatile const struct __anonymous16 _X3f3 1FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 2FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 3FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 4FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 5FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1(); 1025 struct __anonymous22 { 1026 signed int _X1ii_1; 1027 }; 1028 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1029 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1030 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1031 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1032 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1); 1033 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1034 { 1035 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */); 1036 } 1037 1038 } 1039 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1040 { 1041 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */); 1042 } 1043 1044 } 1045 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1046 { 1047 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */); 1048 } 1049 1050 } 1051 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1052 struct __anonymous22 _X4_retS13__anonymous22_1; 1053 { 1054 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1)); 1055 } 1056 1057 { 1058 ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1))); 1059 } 1060 1061 return _X4_retS13__anonymous22_1; 1062 } 1063 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){ 1064 { 1065 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */); 1066 } 1067 1068 } 1069 static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1(); 1070 struct __anonymous23 { 1071 signed int _X1ii_1; 1072 }; 1073 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1074 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1075 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1076 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1077 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1); 1078 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1079 { 1080 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */); 1081 } 1082 1083 } 1084 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1085 { 1086 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */); 1087 } 1088 1089 } 1090 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1091 { 1092 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */); 1093 } 1094 1095 } 1096 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1097 struct __anonymous23 _X4_retS13__anonymous23_1; 1098 { 1099 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1)); 1100 } 1101 1102 { 1103 ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1))); 1104 } 1105 1106 return _X4_retS13__anonymous23_1; 1107 } 1108 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){ 1109 { 1110 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */); 1111 } 1112 1113 } 1114 static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1(); 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 1115 1025 static inline volatile const signed short int _X3f41Fs___1(); 1116 1026 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/declarationSpecifier.x86.txt
r34b4268 r24d6572 51 51 52 52 } 53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1; 144 144 struct __anonymous3 { 145 145 signed int _X1ii_1; … … 322 322 } 323 323 static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1; 324 struct __anonymous7 {325 signed int _X1ii_1;326 };327 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);328 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);329 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);330 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);331 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);332 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){333 {334 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);335 }336 337 }338 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){339 {340 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);341 }342 343 }344 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){345 {346 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);347 }348 349 }350 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){351 struct __anonymous7 _X4_retS12__anonymous7_1;352 {353 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));354 }355 356 {357 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));358 }359 360 return _X4_retS12__anonymous7_1;361 }362 static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){363 {364 ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);365 }366 367 }368 static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;369 324 volatile const signed short int _X3x20KVs_1; 370 325 static volatile const signed short int _X3x21KVs_1; … … 375 330 static volatile const signed short int _X3x26KVs_1; 376 331 static volatile const signed short int _X3x27KVs_1; 332 struct __anonymous7 { 333 signed short int _X1is_1; 334 }; 335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1); 338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1); 339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1); 340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 341 { 342 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */); 343 } 344 345 } 346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 347 { 348 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */); 349 } 350 351 } 352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){ 353 { 354 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */); 355 } 356 357 } 358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){ 359 struct __anonymous7 _X4_retS12__anonymous7_1; 360 { 361 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1)); 362 } 363 364 { 365 ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1))); 366 } 367 368 return _X4_retS12__anonymous7_1; 369 } 370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){ 371 { 372 ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */); 373 } 374 375 } 376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1; 377 377 struct __anonymous8 { 378 378 signed short int _X1is_1; … … 419 419 420 420 } 421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 2KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 3KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1; 647 struct __anonymous14 { 648 signed short int _X1is_1; 649 }; 650 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 651 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 652 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 653 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 654 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1); 655 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 656 { 657 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */); 658 } 659 660 } 661 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 662 { 663 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */); 664 } 665 666 } 667 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 668 { 669 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */); 670 } 671 672 } 673 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 674 struct __anonymous14 _X4_retS13__anonymous14_1; 675 { 676 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1)); 677 } 678 679 { 680 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 681 } 682 683 return _X4_retS13__anonymous14_1; 684 } 685 static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */); 688 } 689 690 } 691 static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1; 692 struct __anonymous15 { 693 signed short int _X1is_1; 694 }; 695 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 696 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 697 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 698 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 699 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1); 700 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 701 { 702 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */); 703 } 704 705 } 706 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 707 { 708 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */); 709 } 710 711 } 712 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 713 { 714 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */); 715 } 716 717 } 718 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 719 struct __anonymous15 _X4_retS13__anonymous15_1; 720 { 721 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1)); 722 } 723 724 { 725 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 726 } 727 728 return _X4_retS13__anonymous15_1; 729 } 730 static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */); 733 } 734 735 } 736 static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1; 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 737 647 _Thread_local signed int _X3x37i_1; 738 648 __thread signed int _X3x38i_1; … … 753 663 static inline volatile const signed short int _X3f27Fs___1(); 754 664 static inline volatile const signed short int _X3f28Fs___1(); 665 struct __anonymous14 { 666 signed int _X1ii_1; 667 }; 668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1); 671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1); 672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1); 673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 674 { 675 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */); 676 } 677 678 } 679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 680 { 681 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */); 682 } 683 684 } 685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){ 686 { 687 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */); 688 } 689 690 } 691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){ 692 struct __anonymous14 _X4_retS13__anonymous14_1; 693 { 694 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1)); 695 } 696 697 { 698 ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1))); 699 } 700 701 return _X4_retS13__anonymous14_1; 702 } 703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){ 704 { 705 ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */); 706 } 707 708 } 709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1(); 710 struct __anonymous15 { 711 signed int _X1ii_1; 712 }; 713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1); 716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1); 717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1); 718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 719 { 720 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */); 721 } 722 723 } 724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 725 { 726 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */); 727 } 728 729 } 730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){ 731 { 732 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */); 733 } 734 735 } 736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){ 737 struct __anonymous15 _X4_retS13__anonymous15_1; 738 { 739 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1)); 740 } 741 742 { 743 ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1))); 744 } 745 746 return _X4_retS13__anonymous15_1; 747 } 748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){ 749 { 750 ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */); 751 } 752 753 } 754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1(); 755 755 struct __anonymous16 { 756 756 signed int _X1ii_1; … … 797 797 798 798 } 799 static inline volatile const struct __anonymous16 _X3f3 1FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 2FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 3FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 4FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 5FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1(); 1025 struct __anonymous22 { 1026 signed int _X1ii_1; 1027 }; 1028 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1029 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1030 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1); 1031 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1); 1032 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1); 1033 static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1034 { 1035 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */); 1036 } 1037 1038 } 1039 static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1040 { 1041 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */); 1042 } 1043 1044 } 1045 static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){ 1046 { 1047 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */); 1048 } 1049 1050 } 1051 static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){ 1052 struct __anonymous22 _X4_retS13__anonymous22_1; 1053 { 1054 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1)); 1055 } 1056 1057 { 1058 ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1))); 1059 } 1060 1061 return _X4_retS13__anonymous22_1; 1062 } 1063 static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){ 1064 { 1065 ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */); 1066 } 1067 1068 } 1069 static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1(); 1070 struct __anonymous23 { 1071 signed int _X1ii_1; 1072 }; 1073 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1074 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1075 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1); 1076 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1); 1077 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1); 1078 static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1079 { 1080 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */); 1081 } 1082 1083 } 1084 static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1085 { 1086 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */); 1087 } 1088 1089 } 1090 static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){ 1091 { 1092 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */); 1093 } 1094 1095 } 1096 static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){ 1097 struct __anonymous23 _X4_retS13__anonymous23_1; 1098 { 1099 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1)); 1100 } 1101 1102 { 1103 ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1))); 1104 } 1105 1106 return _X4_retS13__anonymous23_1; 1107 } 1108 static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){ 1109 { 1110 ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */); 1111 } 1112 1113 } 1114 static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1(); 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 1115 1025 static inline volatile const signed short int _X3f41Fs___1(); 1116 1026 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/forall.txt
r34b4268 r24d6572 1 forall.cfa:244:25: warning: Compiled 1 1 2 f 3 97 4 f 5 g 6 f 7 f 8 g 9 fT 10 fT 11 fT 12 fTU 13 fTU 14 fTU 15 1 2 16 2 1 17 1, 2 18 @ 0 2 0 4 6.4 6.4 6.4 6.4+3.i 4 19 3. 3. 20 45 21 12 3 -
tests/.expect/nested_function.x64.txt
r34b4268 r24d6572 1 total 801 total 145 -
tests/.expect/nested_function.x86.txt
r34b4268 r24d6572 1 total 551 total 245 -
tests/Makefile.am
r34b4268 r24d6572 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : S at Jun 5 14:49:25 202114 ## Update Count : 9213 ## Last Modified On : Sun May 28 08:15:43 2023 14 ## Update Count : 196 15 15 ############################################################################### 16 16 … … 22 22 DEFAULT_INCLUDES = -I${abs_srcdir} 23 23 24 debug=yes 25 installed=no 26 archiveerrors= 27 28 DEBUG_FLAGS=-debug -g -O0 29 30 quick_test=avl_test operators numericConstants expression enum array typeof cast raii/dtor-early-exit raii/init_once attributes meta/dumpable 31 32 concurrent= 33 timeouts= 24 debug ?= yes 25 installed ?= no 26 ARCH = ${if ${arch},"--arch=${arch}"} 27 arch_support = "x86/x64/arm" 28 TIMEOUT = ${if ${timeout},"--timeout=${timeout}"} 29 GLOBAL_TIMEOUT = ${if ${global-timeout},"--global-timeout=${global-timeout}"} 30 ARCHIVE_ERRORS = ${if ${archive-errors},"--archive-errors=${archive-errors}"} 31 32 DEBUG_FLAGS = -debug -g -O0 33 34 quick_test = avl_test operators numericConstants expression enum array typeof cast raii/dtor-early-exit raii/init_once attributes meta/dumpable 34 35 35 36 TEST_PY = python3 ${builddir}/test.py … … 37 38 # applies to both programs 38 39 # since automake doesn't have support for CFA we have to 39 AM_CFLAGS = $ (if $(test), 2> $(test), )\40 -fdebug-prefix-map=$ (abspath ${abs_srcdir})= \40 AM_CFLAGS = ${if ${test}, 2> ${test}, } \ 41 -fdebug-prefix-map=${abspath ${abs_srcdir}}= \ 41 42 -fdebug-prefix-map=/tmp= \ 42 43 -fno-diagnostics-show-caret \ … … 51 52 52 53 # get the desired cfa to test 53 TARGET_CFA = $ (if $(filter $(installed),yes), @CFACC_INSTALL@, @CFACC@)54 TARGET_CFA = ${if ${filter ${installed},yes}, @CFACC_INSTALL@, @CFACC@} 54 55 55 56 # adjust CC to current flags 56 CC = LC_ALL=C $ (if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS} ,$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})57 CFACC = $ (CC)57 CC = LC_ALL=C ${if ${DISTCC_CFA_PATH},distcc ${DISTCC_CFA_PATH} ${ARCH_FLAGS} ,${TARGET_CFA} ${DEBUG_FLAGS} ${ARCH_FLAGS}} 58 CFACC = ${CC} 58 59 59 60 # get local binary for depedencies … … 61 62 62 63 # adjusted CC but without the actual distcc call 63 CFACCLOCAL = $ (if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS} ,$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})64 CFACCLINK = $ (CFACCLOCAL) -quiet $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'))65 66 PRETTY_PATH =mkdir -p $(dir $(abspath ${@}))&& cd ${srcdir} &&67 68 .PHONY :list .validate .test_makeflags69 .INTERMEDIATE : .validate .validate.cfa .test_makeflags64 CFACCLOCAL = ${if ${DISTCC_CFA_PATH},${DISTCC_CFA_PATH} ${ARCH_FLAGS} ,${TARGET_CFA} ${DEBUG_FLAGS} ${ARCH_FLAGS}} 65 CFACCLINK = ${CFACCLOCAL} -quiet ${if ${test}, 2> ${test}, } ${${shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'}} 66 67 PRETTY_PATH = mkdir -p ${dir ${abspath ${@}}} && cd ${srcdir} && 68 69 .PHONY : concurrency list .validate .test_makeflags 70 .INTERMEDIATE : .validate .validate.cfa .test_makeflags 70 71 EXTRA_PROGRAMS = avl_test linkonce linking/mangling/anon .dummy_hack # build but do not install 71 72 EXTRA_DIST = test.py \ … … 78 79 avltree/avl-private.h \ 79 80 avltree/avl.h \ 80 concurrent/clib_tls.c \81 concurrent/clib.c \82 81 configs/.in/parseconfig-all.txt \ 83 82 configs/.in/parseconfig-errors.txt \ … … 88 87 io/.in/many_read.data \ 89 88 meta/fork+exec.hfa \ 90 unified_locking/mutex_test.hfa 89 concurrency/clib_tls.c \ 90 concurrency/clib.c \ 91 concurrency/unified_locking/mutex_test.hfa \ 92 concurrency/channels/parallel_harness.hfa 91 93 92 94 dist-hook: … … 94 96 for file in `${TEST_PY} --list-dist`; do \ 95 97 if test -f ${srcdir}/$${file}; then \ 96 $ (MKDIR_P)$$(dirname ${distdir}/$${file}); \98 ${MKDIR_P} $$(dirname ${distdir}/$${file}); \ 97 99 cp -df ${srcdir}/$${file} ${distdir}/$${file}; \ 98 100 fi; \ … … 106 108 107 109 #---------------------------------------------------------------------------------------------------------------- 108 all-local : 109 @+${TEST_PY} --debug=${debug} --install=${installed} --archive-errors=${archiveerrors} ${concurrent} ${timeouts} ${quick_test} 110 111 all-tests : 112 @+${TEST_PY} --debug=${debug} --install=${installed} --archive-errors=${archiveerrors} ${concurrent} ${timeouts} --all # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 110 111 # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 112 all-local : # This name is important to automake and implies the default build target. 113 @+${TEST_PY} --debug=${debug} --install=${installed} --invariant ${ARCHIVE_ERRORS} ${TIMEOUT} ${GLOBAL_TIMEOUT} ${ARCH} --all 114 115 tests : all-local # synonym 116 117 install : all-local # synonym, PAB only 118 119 quick : 120 @+${TEST_PY} --debug=${debug} --install=${installed} ${ARCHIVE_ERRORS} ${ARCH} ${quick_test} 121 122 concurrency : 123 @+${TEST_PY} --debug=${debug} --install=${installed} ${ARCHIVE_ERRORS} ${TIMEOUT} ${GLOBAL_TIMEOUT} ${ARCH} -Iconcurrency 124 125 list : 126 @+${TEST_PY} --list 127 128 help : 129 @echo "user targets:" 130 @echo " Run the complete test suite." 131 @echo " $$ make (null) / tests [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [timeout=seconds] [global-timeout=seconds] [arch=${arch_support}]" 132 @echo "" 133 @echo " Run the short (quick) test suite." 134 @echo " $$ make quick [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [arch=${arch_support}]" 135 @echo "" 136 @echo " Run the concurrency test suite." 137 @echo " $$ make concurrency [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [timeout=seconds] [global-timeout=seconds] [arch=${arch_support}]" 138 @echo "" 139 @echo " List all tests in the test suite." 140 @echo " $$ make list" 113 141 114 142 mostlyclean-local : … … 122 150 find ${builddir} -path '*.Po' -delete 123 151 124 list :125 @+${TEST_PY} --list ${concurrent}126 127 152 .test_makeflags: 128 153 @echo "${MAKEFLAGS}" 129 154 130 155 .validate: .validate.cfa 131 $ (CFACOMPILE).validate.cfa -fsyntax-only -Wall -Wextra -Werror156 ${CFACOMPILE} .validate.cfa -fsyntax-only -Wall -Wextra -Werror 132 157 133 158 .validate.cfa: … … 141 166 @echo "int bar() { return 0; }" > ${@} 142 167 143 concurrency :144 @+${TEST_PY} --debug=${debug} --install=${installed} -Iconcurrent145 146 168 #---------------------------------------------------------------------------------------------------------------- 147 169 148 170 # Use for all tests, make sure the path are correct and all flags are added 149 CFACOMPILETEST=$ (PRETTY_PATH) $(CFACOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) $($(shell echo "${@}_FLAGSCFA" | sed 's/-\|\//_/g'))171 CFACOMPILETEST=${PRETTY_PATH} ${CFACOMPILE} ${shell realpath --relative-to=${srcdir} ${<}} ${${shell echo "${@}_FLAGSCFA" | sed 's/-\|\//_/g'}} 150 172 151 173 #---------------------------------------------------------------------------------------------------------------- … … 154 176 # split into two steps to support compiling remotely using distcc 155 177 # don't use distcc to do the linking because distcc doesn't do linking 156 % : %.cfa $ (CFACCBIN)157 $ (CFACOMPILETEST) -c -o $(abspath ${@}).o -DIN_DIR="$(abspath $(dir ${<}))/.in/"158 $ (CFACCLINK) ${@}.o -o $(abspath ${@})159 rm $ (abspath ${@}).o178 % : %.cfa ${CFACCBIN} 179 ${CFACOMPILETEST} -c -o ${abspath ${@}}.o -DIN_DIR="${abspath ${dir ${<}}}/.in/" 180 ${CFACCLINK} ${@}.o -o ${abspath ${@}} 181 rm ${abspath ${@}}.o 160 182 161 183 # implicit rule for c++ test 162 184 # convient for testing the testsuite itself but not actuall used 163 185 % : %.cpp 164 $ (PRETTY_PATH) $(CXXCOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})186 ${PRETTY_PATH} ${CXXCOMPILE} ${shell realpath --relative-to=${srcdir} ${<}} -o ${abspath ${@}} 165 187 166 188 #------------------------------------------------------------------------------ … … 173 195 # Generated code 174 196 GENERATED_CODE = declarationSpecifier gccExtensions extension attributes functions KRfunctions 175 $ (GENERATED_CODE): % : %.cfa $(CFACCBIN)176 $ (CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@})197 ${GENERATED_CODE} : % : %.cfa ${CFACCBIN} 198 ${CFACOMPILETEST} -CFA -XCFA -p -c -fsyntax-only -o ${abspath ${@}} 177 199 178 200 #------------------------------------------------------------------------------ … … 180 202 #------------------------------------------------------------------------------ 181 203 # tests that just validate syntax and compiler output should be compared to stderr 182 CFACOMPILE_SYNTAX = $ (CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})183 184 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall\185 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment 186 $ (SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)187 $ (CFACOMPILE_SYNTAX)188 $ (if $(test), cp $(test) $(abspath ${@}), )204 CFACOMPILE_SYNTAX = ${CFACOMPILETEST} -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o ${abspath ${@}} 205 206 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator \ 207 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment concurrency/waitfor/parse 208 ${SYNTAX_ONLY_CODE} : % : %.cfa ${CFACCBIN} 209 ${CFACOMPILE_SYNTAX} 210 ${if ${test}, cp ${test} ${abspath ${@}}, } 189 211 190 212 # expected failures 191 213 # use custom target since they require a custom define *and* have a name that doesn't match the file 192 alloc-ERROR : alloc.cfa $(CFACCBIN) 193 $(CFACOMPILE_SYNTAX) -DERR1 194 -cp $(test) $(abspath ${@}) 195 196 init1-ERROR : init1.cfa $(CFACCBIN) 197 $(CFACOMPILE_SYNTAX) -DERR1 198 -cp $(test) $(abspath ${@}) 199 200 typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN) 201 $(CFACOMPILE_SYNTAX) -DERR1 202 -cp $(test) $(abspath ${@}) 203 204 nested-types-ERR1 : nested-types.cfa $(CFACCBIN) 205 $(CFACOMPILE_SYNTAX) -DERR1 206 -cp $(test) $(abspath ${@}) 207 208 nested-types-ERR2 : nested-types.cfa $(CFACCBIN) 209 $(CFACOMPILE_SYNTAX) -DERR2 210 -cp $(test) $(abspath ${@}) 211 212 raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN) 213 $(CFACOMPILE_SYNTAX) -DERR1 214 -cp $(test) $(abspath ${@}) 215 216 raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN) 217 $(CFACOMPILE_SYNTAX) -DERR1 218 -cp $(test) $(abspath ${@}) 219 220 raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN) 221 $(CFACOMPILE_SYNTAX) -DERR1 222 -cp $(test) $(abspath ${@}) 223 224 raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN) 225 $(CFACOMPILE_SYNTAX) -DERR2 226 -cp $(test) $(abspath ${@}) 214 215 array-ERR1 : array.cfa ${CFACCBIN} 216 ${CFACOMPILE_SYNTAX} -DERR1 217 -cp ${test} ${abspath ${@}} 218 219 array-ERR2 : array.cfa ${CFACCBIN} 220 ${CFACOMPILE_SYNTAX} -DERR2 221 -cp ${test} ${abspath ${@}} 222 223 array-ERR3 : array.cfa ${CFACCBIN} 224 ${CFACOMPILE_SYNTAX} -DERR3 225 -cp ${test} ${abspath ${@}} 226 227 alloc-ERROR : alloc.cfa ${CFACCBIN} 228 ${CFACOMPILE_SYNTAX} -DERR1 229 -cp ${test} ${abspath ${@}} 230 231 init1-ERROR : init1.cfa ${CFACCBIN} 232 ${CFACOMPILE_SYNTAX} -DERR1 233 -cp ${test} ${abspath ${@}} 234 235 typedefRedef-ERR1 : typedefRedef.cfa ${CFACCBIN} 236 ${CFACOMPILE_SYNTAX} -DERR1 237 -cp ${test} ${abspath ${@}} 238 239 nested-types-ERR1 : nested-types.cfa ${CFACCBIN} 240 ${CFACOMPILE_SYNTAX} -DERR1 241 -cp ${test} ${abspath ${@}} 242 243 nested-types-ERR2 : nested-types.cfa ${CFACCBIN} 244 ${CFACOMPILE_SYNTAX} -DERR2 245 -cp ${test} ${abspath ${@}} 246 247 raii/memberCtors-ERR1 : raii/memberCtors.cfa ${CFACCBIN} 248 ${CFACOMPILE_SYNTAX} -DERR1 249 -cp ${test} ${abspath ${@}} 250 251 raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa ${CFACCBIN} 252 ${CFACOMPILE_SYNTAX} -DERR1 253 -cp ${test} ${abspath ${@}} 254 255 raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa ${CFACCBIN} 256 ${CFACOMPILE_SYNTAX} -DERR1 257 -cp ${test} ${abspath ${@}} 258 259 raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa ${CFACCBIN} 260 ${CFACOMPILE_SYNTAX} -DERR2 261 -cp ${test} ${abspath ${@}} 227 262 228 263 # Exception Tests 229 264 # Test with libcfathread; it changes how storage works. 230 265 231 exceptions/%-threads : exceptions/%.cfa $ (CFACCBIN)232 $ (CFACOMPILETEST) -include exceptions/with-threads.hfa -c -o $(abspath ${@}).o233 $ (CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})266 exceptions/%-threads : exceptions/%.cfa ${CFACCBIN} 267 ${CFACOMPILETEST} -include exceptions/with-threads.hfa -c -o ${abspath ${@}}.o 268 ${CFACCLOCAL} ${${shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'}} ${abspath ${@}}.o -o ${abspath ${@}} 234 269 235 270 # Linking tests 236 271 # Meta tests to make sure we see linking errors (can't compile with -O2 since it may multiply number of calls) 237 linking/linkerror : linking/linkerror.cfa $ (CFACCBIN)238 $ (CFACOMPILETEST) -O0 -c -o $(abspath ${@}).o239 $ (CFACCLINK) -O0 ${@}.o -o $(abspath ${@})240 rm $ (abspath ${@}).o272 linking/linkerror : linking/linkerror.cfa ${CFACCBIN} 273 ${CFACOMPILETEST} -O0 -c -o ${abspath ${@}}.o 274 ${CFACCLINK} -O0 ${@}.o -o ${abspath ${@}} 275 rm ${abspath ${@}}.o 241 276 242 277 #------------------------------------------------------------------------------ -
tests/PRNG.cfa
r34b4268 r24d6572 1 // -*- Mode: C -*- 2 // 1 // 3 2 // Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo 4 // 5 // PRNG.c -- 6 // 3 // 4 // PRNG.c -- high-perforamnce pseudo-random numbers 5 // 6 // The contents of this file are covered under the licence agreement in the 7 // file "LICENCE" distributed with Cforall. 8 // 7 9 // Author : Peter A. Buhr 8 10 // Created On : Wed Dec 29 09:38:12 2021 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : T ue Nov 22 22:51:12 202211 // Update Count : 38112 // Last Modified On : Thu May 25 15:39:52 2023 13 // Update Count : 422 12 14 // 13 15 … … 15 17 #include <stdlib.hfa> // PRNG 16 18 #include <clock.hfa> 17 #include <thread.hfa>18 19 #include <limits.hfa> // MAX 19 20 #include <math.hfa> // sqrt 20 21 #include <malloc.h> // malloc_stats 21 22 #include <locale.h> // setlocale 23 #include <thread.hfa> 22 24 #include <mutex_stmt.hfa> 23 25 24 #ifdef __x86_64__ // 64-bit architecture 26 #define xstr(s) str(s) 27 #define str(s) #s 28 29 #if defined( __x86_64__ ) || defined( __aarch64__ ) // 64-bit architecture 25 30 #define PRNG PRNG64 26 31 #else // 32-bit architecture 27 32 #define PRNG PRNG32 28 33 #endif // __x86_64__ 34 35 //#define TIME 29 36 30 37 #ifdef TIME // use -O2 -nodebug … … 38 45 #endif // TIME 39 46 40 void avgstd( unsigned int buckets[] ) {41 unsigned int min = MAX, max = 0;47 static void avgstd( size_t trials, size_t buckets[] ) { 48 size_t min = MAX, max = 0; 42 49 double sum = 0.0, diff; 43 50 for ( i; BUCKETS ) { … … 54 61 } // for 55 62 double std = sqrt( sum / BUCKETS ); 56 mutex( sout ) sout | "trials" | TRIALS| "buckets" | BUCKETS63 mutex( sout ) sout | "trials" | trials | "buckets" | BUCKETS 57 64 | "min" | min | "max" | max 58 65 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%"; … … 60 67 61 68 62 unsigned int seed = 1009;69 size_t seed = 1009; 63 70 64 71 thread T1 {}; 65 72 void main( T1 & ) { 66 unsigned int * buckets = calloc( BUCKETS );// too big for task stack67 for ( TRIALS / 100 ) {73 size_t * buckets = calloc( BUCKETS ); // too big for task stack 74 for ( TRIALS / 50 ) { 68 75 buckets[rand() % BUCKETS] += 1; // concurrent 69 76 } // for 70 avgstd( buckets );77 avgstd( TRIALS / 50, buckets ); 71 78 free( buckets ); 72 79 } // main … … 76 83 PRNG prng; 77 84 if ( seed != 0 ) set_seed( prng, seed ); 78 unsigned int * buckets = calloc( BUCKETS );// too big for task stack85 size_t * buckets = calloc( BUCKETS ); // too big for task stack 79 86 for ( TRIALS ) { 80 87 buckets[prng( prng ) % BUCKETS] += 1; // concurrent 81 88 } // for 82 avgstd( buckets );89 avgstd( TRIALS, buckets ); 83 90 free( buckets ); 84 91 } // main … … 86 93 thread T3 {}; 87 94 void main( T3 & th ) { 88 unsigned int * buckets = calloc( BUCKETS );// too big for task stack89 for ( TRIALS ) {95 size_t * buckets = calloc( BUCKETS ); // too big for task stack 96 for ( TRIALS / 5 ) { 90 97 buckets[prng() % BUCKETS] += 1; // concurrent 91 98 } // for 92 avgstd( buckets );99 avgstd( TRIALS / 5, buckets ); 93 100 free( buckets ); 94 101 } // main … … 96 103 thread T4 {}; 97 104 void main( T4 & th ) { 98 unsigned int * buckets = calloc( BUCKETS );// too big for task stack105 size_t * buckets = calloc( BUCKETS ); // too big for task stack 99 106 for ( TRIALS ) { 100 buckets[prng( th ) % BUCKETS] += 1; // concurrent101 } // for 102 avgstd( buckets );107 buckets[prng( th ) % BUCKETS] += 1; // concurrent 108 } // for 109 avgstd( TRIALS, buckets ); 103 110 free( buckets ); 104 111 } // main … … 108 115 static void dummy( thread$ & th ) __attribute__(( noinline )); 109 116 static void dummy( thread$ & th ) { 110 unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack111 for ( unsigned int i = 0; i < TRIALS; i += 1 ) {117 size_t * buckets = (size_t *)calloc( BUCKETS, sizeof(size_t) ); // too big for task stack 118 for ( size_t i = 0; i < TRIALS; i += 1 ) { 112 119 buckets[prng( th ) % BUCKETS] += 1; // sequential 113 120 } // for 114 avgstd( buckets );121 avgstd( TRIALS, buckets ); 115 122 free( buckets ); 116 123 } // dummy 117 124 125 118 126 int main() { 119 // causes leaked storage message 120 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // print digit separator 127 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // causes leaked storage message 128 129 // only works on the current pthread thread 130 // locale_t loc = newlocale( LC_NUMERIC_MASK, getenv( "LANG" ), (locale_t)0p ); 131 // if ( loc == (locale_t)0p ) abort( "newlocale" ); 132 // uselocale( loc ); 121 133 122 134 enum { TASKS = 4 }; 123 135 Time start; 136 124 137 #ifdef TIME // too slow for test and generates non-repeatable results 125 138 #if 1 126 unsigned int rseed; 139 sout | "glib rand" | nl | nl; 140 141 size_t rseed; 127 142 if ( seed != 0 ) rseed = seed; 128 143 else rseed = rdtscl(); … … 130 145 131 146 sout | sepDisable; 132 sout | wd(13, "rand()" ) | wd(10, "rand(5)") | wd(13, "rand(0,5)" );133 for ( 20 ) { 134 sout | wd( 13, rand()) | nonl;135 sout | wd(1 0, rand() % 5) | nonl;136 sout | wd(1 3, rand() % (5 - 0 + 1) + 0);147 sout | nl | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" ); 148 for ( 20 ) { 149 sout | wd(26, rand()) | nonl; 150 sout | wd(12, rand() % 5) | nonl; 151 sout | wd(12, rand() % (5 - 0 + 1) + 0); 137 152 } // for 138 153 sout | sepEnable; … … 142 157 STARTTIME; 143 158 { 144 unsigned int * buckets = calloc( BUCKETS );// too big for task stack145 for ( i; TRIALS / 10) {159 size_t * buckets = calloc( BUCKETS ); // too big for task stack 160 for ( i; TRIALS / 5 ) { 146 161 buckets[rand() % BUCKETS] += 1; // sequential 147 162 } // for 148 avgstd( buckets );163 avgstd( TRIALS / 5, buckets ); 149 164 free( buckets ); 150 165 } 151 ENDTIME( " x 10" );166 ENDTIME( " x 5 " ); 152 167 153 168 sout | nl | "Concurrent"; … … 159 174 } // wait for threads to complete 160 175 } 161 ENDTIME( " x 100 " );176 ENDTIME( " x 50 " ); 162 177 #endif // 0 163 178 #endif // TIME 179 180 sout | nl | "CFA " xstr(PRNG_NAME); 181 164 182 #if 1 165 183 PRNG prng; … … 168 186 169 187 sout | sepDisable; 170 sout | nl | wd( 13, "PRNG()" ) | wd(10, "PRNG(5)") | wd(13, "PRNG(0,5)" );171 for ( 20 ) { 172 sout | wd( 13, prng( prng )) | nonl; // cascading => side-effect functions called in arbitary order173 sout | wd(1 0, prng( prng, 5 )) | nonl;174 sout | wd(1 3, prng( prng, 0, 5 ));188 sout | nl | wd(26, "PRNG()" ) | wd(12, "PRNG(5)") | wd(12, "PRNG(0,5)" ); 189 for ( 20 ) { 190 sout | wd(26, prng( prng )) | nonl; // cascading => side-effect functions called in arbitary order 191 sout | wd(12, prng( prng, 5 )) | nonl; 192 sout | wd(12, prng( prng, 0, 5 )); 175 193 } // for 176 194 sout | sepEnable; … … 180 198 STARTTIME; 181 199 { 182 unsigned int * buckets = calloc( BUCKETS );// too big for task stack200 size_t * buckets = calloc( BUCKETS ); // too big for task stack 183 201 for ( TRIALS ) { 184 202 buckets[prng( prng ) % BUCKETS] += 1; // sequential 185 203 } // for 186 avgstd( buckets );204 avgstd( TRIALS, buckets ); 187 205 free( buckets ); 188 206 } … … 203 221 204 222 sout | sepDisable; 205 sout | nl | wd( 13, "prng()" ) | wd(10, "prng(5)") | wd(13, "prng(0,5)" );206 for ( 20 ) { 207 sout | wd( 13, prng()) | nonl; // cascading => side-effect functions called in arbitary order208 sout | wd(1 0, prng( 5 )) | nonl;209 sout | wd(1 3, prng( 0, 5 ));223 sout | nl | wd(26, "prng()" ) | wd(12, "prng(5)") | wd(12, "prng(0,5)" ); 224 for ( 20 ) { 225 sout | wd(26, prng()) | nonl; // cascading => side-effect functions called in arbitary order 226 sout | wd(12, prng( 5 )) | nonl; 227 sout | wd(12, prng( 0, 5 )); 210 228 } // for 211 229 sout | sepEnable; … … 215 233 STARTTIME; 216 234 { 217 unsigned int * buckets = calloc( BUCKETS );// too big for task stack218 for ( TRIALS ) {235 size_t * buckets = calloc( BUCKETS ); // too big for task stack 236 for ( TRIALS / 5 ) { 219 237 buckets[prng() % BUCKETS] += 1; 220 238 } // for 221 avgstd( buckets );239 avgstd( TRIALS / 5, buckets ); 222 240 free( buckets ); 223 241 } 224 ENDTIME( );242 ENDTIME( " x 5 " ); 225 243 226 244 sout | nl | "Concurrent"; … … 232 250 } // wait for threads to complete 233 251 } 234 ENDTIME( );252 ENDTIME( " x 5 " ); 235 253 #endif // 0 236 254 #if 1 … … 239 257 240 258 sout | sepDisable; 241 sout | nl | wd( 13, "prng(t)" ) | wd(10, "prng(t,5)") | wd(13, "prng(t,0,5)" );242 for ( 20 ) { 243 sout | wd( 13, prng( th )) | nonl; // cascading => side-effect functions called in arbitary order244 sout | wd(1 0, prng( th, 5 )) | nonl;245 sout | wd(1 3, prng( th, 0, 5 ));259 sout | nl | wd(26, "prng(t)" ) | wd(12, "prng(t,5)") | wd(12, "prng(t,0,5)" ); 260 for ( 20 ) { 261 sout | wd(26, prng( th )) | nonl; // cascading => side-effect functions called in arbitary order 262 sout | wd(12, prng( th, 5 )) | nonl; 263 sout | wd(12, prng( th, 0, 5 )); 246 264 } // for 247 265 sout | sepEnable; … … 266 284 #endif // 0 267 285 // malloc_stats(); 286 // freelocale( loc ); 268 287 } // main 269 288 -
tests/array.cfa
r34b4268 r24d6572 15 15 // 16 16 17 int a1[0]; 18 // int a2[*];19 // double a4[3.0];17 // Tests syntax. Comments explain semantics. Test does not show semantics. 18 // Mostly illustrates facts about C (with which CFA is being tested to agree). 19 // Is a test oracle under `gcc -x c`. 20 20 21 int m1[0][3]; 22 //int m2[*][*]; 23 int m4[3][3]; 21 #ifdef ERR1 22 #define E1(...) __VA_ARGS__ 23 #else 24 #define E1(...) 25 #endif 24 26 25 typedef int T; 27 #ifdef ERR2 28 #define E2(...) __VA_ARGS__ 29 #else 30 #define E2(...) 31 #endif 26 32 27 int fred() { 28 // int a1[]; 29 // int a2[*]; 30 int a4[3]; 31 int T[3]; 32 } 33 #ifdef ERR3 34 #define E3(...) __VA_ARGS__ 35 #else 36 #define E3(...) 37 #endif 33 38 34 int mary( int T[3], 35 int p1[const 3], 36 int p2[static 3], 37 int p3[static const 3] 38 ) { 39 } 39 int a1[0]; 40 E1( int a2[*]; ) 41 #ifndef __cforall 42 E1( double a4[3.0]; ) // BUG 275: CFA accepts but should reject 43 #endif 40 44 41 int (*tom())[3] { 42 } 45 int m1[0][3]; 46 E1( int m2[*][*]; ) 47 int m4[3][3]; 43 48 44 int (*(jane)())( int T[3], 45 int p1[const 3], 46 int p2[static 3], 47 int p3[static const 3] 48 ) { 49 } 49 typedef int T; 50 51 int fred(int n) { 52 E1( int a1[]; ) 53 E1( int a2[*]; ) 54 int a4[3]; 55 int T[3]; 56 int a5[n]; 57 } 58 59 int mary( int T[3], // same as: int *T 60 int p1[const 3], // same as: int const *p1 61 int p2[static 3], // same as T, but length >=3 checked 62 int p3[static const 3] // both above: 3 is static, p3 is const 63 ) { 64 } 65 66 // function taking (), returning pointer to array of ints 67 int (*tom())[3] { 68 } 69 70 // function taking (), returning pointer to function of same type as mary 71 int (*(jane)())( int T[3], 72 int p1[const 3], 73 int p2[static 3], 74 int p3[static const 3] 75 ) { 76 } 77 78 // functions returning same exotic pointers, in CFA's non-onion syntax 79 #ifdef __cforall 80 [ * [3] int ] toms_twin(...) { 81 } 82 [ * [int]( [3] int T, 83 [const 3] int p1, 84 [static 3] int p2, 85 [static const 3] int p3 86 ) 87 ] janes_twin(...) { 88 } 89 #endif 90 91 // GCC 11+ gives a false warning (-Wvla-parameter) on the valid (C11 ARM p134-135) combination: 92 // declare with type int[*], define with type int[n]. 93 // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=100420 suggests the internal representation of 94 // of a[*] is the same as a[0]. 95 // https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wno-vla-parameter explains 96 // the purpose of -Wvla-parameter is to report conflicts between int[] and int[n], which would 97 // understandably also include those between int[42] and int[n]. 98 // https://stackoverflow.com/questions/17371645/why-use-an-asterisk-instead-of-an-integer-for-a-vla-array-parameter-of-a-f 99 // explains the declare-*, define-n pattern. 100 101 // To work around the false warning, and keep to this test's purpose of exercising CFA's 102 // handling of exotic C array syntax, what would ideally be demonstrated as a declaration of 103 // fm1, followed by its definition, is instead split into fm1x and fm1y. And similarly for 104 // fm5. 105 106 int fm1x( int, int, int[][*] ); 107 int fm1y( int r, int c, int m[][c] ) {} 108 int fm2( int r, int c, int (*m)[c] ) {} // same as fm1 109 E2( int fm3( int r, int c, int m[][static c] ) {} ) // that's not static 110 E3( int fm4( int r, int c, int m[][] ); ) // m's immediate element type is incomplete 111 int fm5x( int, int, int[*][*] ); // same as fm1 decl 112 #ifndef __cforall 113 int fm5y( int r, int c, int m[r][c] ) {} // BUG 276: CFA chokes but should accept 114 // C: same as fm1 defn 115 #endif 116 50 117 51 118 int main() { 52 #pragma GCC warning " Compiled"// force non-empty .expect file, NO TABS!!!119 #pragma GCC warning "Preprocessor started" // force non-empty .expect file, NO TABS!!! 53 120 } 54 121 -
tests/attributes.cfa
r34b4268 r24d6572 10 10 // Created On : Mon Feb 6 16:07:02 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 15 13:53:31 202113 // Update Count : 3 812 // Last Modified On : Thu Feb 23 20:33:07 2023 13 // Update Count : 39 14 14 // 15 15 … … 22 22 23 23 // aggregate_name 24 st ruct __attribute__(( unused )) {} Dummy;24 static struct __attribute__(( unused )) {} Dummy; 25 25 struct __attribute__(( unused )) Agn1; 26 26 struct __attribute__(( unused )) Agn2 {}; -
tests/avltree/avl.h
r34b4268 r24d6572 9 9 // #include <lib.h> 10 10 11 trait Comparable(T) { 11 forall(T) 12 trait Comparable { 12 13 int ?<?(T, T); 13 14 }; -
tests/collections/vector-demo.cfa
r34b4268 r24d6572 143 143 assert( v`capacity > 5 && v`length == 5 ); 144 144 145 v[2] = -0.1 ; // v is [0.0, 98.6, -0.1, 0.2, 0.3]; iter at -0.1, where only the new memory had that change145 v[2] = -0.1f; // v is [0.0, 98.6, -0.1, 0.2, 0.3]; iter at -0.1, where only the new memory had that change 146 146 147 147 float val3 = iter`val; -
tests/declarationSpecifier.cfa
r34b4268 r24d6572 10 10 // Created On : Wed Aug 17 08:21:04 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Apr 30 18:20:36 201913 // Update Count : 412 // Last Modified On : Thu Feb 23 20:53:31 2023 13 // Update Count : 8 14 14 // 15 15 … … 25 25 short int volatile static const x8; 26 26 27 const volatile struct { int i; } x10; 28 const struct { int i; } volatile x11; 29 struct { int i; } const volatile x12; 30 static const volatile struct { int i; } x13; 31 const static struct { int i; } volatile x14; 32 struct { int i; } static const volatile x15; 33 struct { int i; } const static volatile x16; 34 struct { int i; } const volatile static x17; 27 static const volatile struct { int i; } x10; 28 static const struct { int i; } volatile x11; 29 static struct { int i; } const volatile x12; 30 const static struct { int i; } volatile x13; 31 struct { int i; } static const volatile x14; 32 struct { int i; } const static volatile x15; 33 struct { int i; } const volatile static x16; 35 34 36 35 const Int volatile x20; … … 43 42 Int volatile static const x27; 44 43 45 const volatile struct { Int i; } x29; 46 const struct { Int i; } volatile x30; 47 struct { Int i; } const volatile x31; 48 static const volatile struct { Int i; } x32; 49 const static struct { Int i; } volatile x33; 50 struct { Int i; } static const volatile x34; 51 struct { Int i; } const static volatile x35; 52 struct { Int i; } const volatile static x36; 44 static const volatile struct { Int i; } x29; 45 static const struct { Int i; } volatile x30; 46 static struct { Int i; } const volatile x31; 47 const static struct { Int i; } volatile x32; 48 struct { Int i; } static const volatile x33; 49 struct { Int i; } const static volatile x34; 50 struct { Int i; } const volatile static x35; 53 51 54 52 _Thread_local int x37; -
tests/enum_tests/.expect/typedIntEnum.txt
r34b4268 r24d6572 1 0 2 1 3 1000 4 1001 5 2000 6 2001 7 2002 1 0=0 2 1=1 3 1000=1000 4 1001=1001 5 2000=2000 6 2001=2001 7 2002=2002 -
tests/enum_tests/pointerEnum.cfa
r34b4268 r24d6572 11 11 int main() { 12 12 E * v = First; 13 sout | "v: " | e.x;13 // sout | "v: " | e.x; 14 14 } -
tests/enum_tests/typedIntEnum.cfa
r34b4268 r24d6572 12 12 13 13 int main() { 14 printf(" %d\n", zero);15 printf(" %d\n", one);16 printf(" %d\n", thousand);17 printf(" %d\n", thousand_one);18 printf(" %d\n", two_thousand);19 printf(" %d\n", two_thousand_one);20 printf(" %d\n", two_thousand_two);14 printf("0=%d\n", zero); 15 printf("1=%d\n", one); 16 printf("1000=%d\n", thousand); 17 printf("1001=%d\n", thousand_one); 18 printf("2000=%d\n", two_thousand); 19 printf("2001=%d\n", two_thousand_one); 20 printf("2002=%d\n", two_thousand_two); 21 21 return 0; 22 22 } -
tests/errors/.expect/declaration.txt
r34b4268 r24d6572 1 errors/declaration.cfa:16:1 error: duplicate static in declaration of x1: static const volatile short int1 errors/declaration.cfa:16:1 error: duplicate static storage class(es) in declaration of x1: static const volatile short int 2 2 3 errors/declaration.cfa:17:1 error: conflicting extern & static in declaration of x2: extern const volatile short int3 errors/declaration.cfa:17:1 error: conflicting extern & static storage classes in declaration of x2: extern const volatile short int 4 4 5 errors/declaration.cfa:18:1 error: conflicting extern & auto , conflicting extern & static, conflicting extern & static, duplicate externin declaration of x3: extern const volatile short int5 errors/declaration.cfa:18:1 error: conflicting extern & auto storage classes, conflicting extern & static storage classes, conflicting extern & static storage classes, duplicate extern storage class(es) in declaration of x3: extern const volatile short int 6 6 7 errors/declaration.cfa:19:1 error: duplicate static in declaration of x4: static const volatile instance of const volatile struct __anonymous07 errors/declaration.cfa:19:1 error: duplicate static storage class(es) in declaration of x4: static const volatile instance of const volatile struct __anonymous0 8 8 with members 9 9 i: int … … 11 11 12 12 13 errors/declaration.cfa:20:1 error: duplicate const , duplicate static, duplicate volatilein declaration of x5: static const volatile instance of const volatile struct __anonymous113 errors/declaration.cfa:20:1 error: duplicate const qualifier(s), duplicate static storage class(es), duplicate volatile qualifier(s) in declaration of x5: static const volatile instance of const volatile struct __anonymous1 14 14 with members 15 15 i: int … … 17 17 18 18 19 errors/declaration.cfa:22:1 error: duplicate static in declaration of x6: static const volatile Int19 errors/declaration.cfa:22:1 error: duplicate static storage class(es) in declaration of x6: static const volatile Int 20 20 21 errors/declaration.cfa:24:1 error: duplicate const in declaration of f01: static inline function21 errors/declaration.cfa:24:1 error: duplicate const qualifier(s) in declaration of f01: static inline function 22 22 with no parameters 23 23 returning const volatile int 24 24 25 25 26 errors/declaration.cfa:25:1 error: duplicate volatile in declaration of f02: static inline function26 errors/declaration.cfa:25:1 error: duplicate volatile qualifier(s) in declaration of f02: static inline function 27 27 with no parameters 28 28 returning const volatile int 29 29 30 30 31 errors/declaration.cfa:26:1 error: duplicate const in declaration of f03: static inline function31 errors/declaration.cfa:26:1 error: duplicate const qualifier(s) in declaration of f03: static inline function 32 32 with no parameters 33 33 returning const volatile int 34 34 35 35 36 errors/declaration.cfa:27:1 error: duplicate volatile in declaration of f04: static inline function36 errors/declaration.cfa:27:1 error: duplicate volatile qualifier(s) in declaration of f04: static inline function 37 37 with no parameters 38 38 returning const volatile int 39 39 40 40 41 errors/declaration.cfa:28:1 error: duplicate const in declaration of f05: static inline function41 errors/declaration.cfa:28:1 error: duplicate const qualifier(s) in declaration of f05: static inline function 42 42 with no parameters 43 43 returning const volatile int 44 44 45 45 46 errors/declaration.cfa:29:1 error: duplicate volatile in declaration of f06: static inline function46 errors/declaration.cfa:29:1 error: duplicate volatile qualifier(s) in declaration of f06: static inline function 47 47 with no parameters 48 48 returning const volatile int 49 49 50 50 51 errors/declaration.cfa:30:1 error: duplicate const in declaration of f07: static inline function51 errors/declaration.cfa:30:1 error: duplicate const qualifier(s) in declaration of f07: static inline function 52 52 with no parameters 53 53 returning const volatile int 54 54 55 55 56 errors/declaration.cfa:31:1 error: duplicate const , duplicate volatilein declaration of f08: static inline function56 errors/declaration.cfa:31:1 error: duplicate const volatile qualifier(s) in declaration of f08: static inline function 57 57 with no parameters 58 58 returning const volatile int 59 59 60 60 61 errors/declaration.cfa:33:1 error: duplicate const , duplicate volatilein declaration of f09: static inline function61 errors/declaration.cfa:33:1 error: duplicate const volatile qualifier(s) in declaration of f09: static inline function 62 62 with no parameters 63 63 returning const volatile int 64 64 65 65 66 errors/declaration.cfa:34:1 error: duplicate const , duplicate _Atomic, duplicate _Atomic, duplicate const, duplicate restrict, duplicate volatilein declaration of f09: static inline function66 errors/declaration.cfa:34:1 error: duplicate const qualifier(s), duplicate _Atomic qualifier(s), duplicate _Atomic qualifier(s), duplicate const restrict volatile qualifier(s) in declaration of f09: static inline function 67 67 with no parameters 68 68 returning const restrict volatile _Atomic int -
tests/forall.cfa
r34b4268 r24d6572 10 10 // Created On : Wed May 9 08:48:15 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 5 10:06:08 2021 13 // Update Count : 36 14 // 12 // Last Modified On : Thu Feb 23 20:29:59 2023 13 // Update Count : 91 14 // 15 16 #include <fstream.hfa> 15 17 16 18 void g1() { 17 forall( T ) T f( T ) {}; 18 void f( int ) {}; 19 void h( void (*p)(void) ) {}; 20 21 int x; 22 void (*y)(void); 23 char z; 24 float w; 19 forall( T ) T f( T p ) { sout | 'f'; return p; }; 20 void f( int p ) { sout | p; }; 21 void g( void ) { sout | 'g'; }; 22 void h( void (*p)(void) ) { p(); }; 23 24 int x = 1; 25 void (*y)(void) = g; 26 char z = 'a'; 27 float w = 3.5; 25 28 26 29 f( x ); … … 28 31 f( z ); 29 32 f( w ); 33 h( y ); 34 f( y ); 30 35 h( f( y ) ); 31 36 } 32 37 33 38 void g2() { 34 forall( T ) void f( T, T ) { }35 forall( T, U ) void f( T, U ) { }39 forall( T ) void f( T, T ) { sout | "fT"; } 40 forall( T, U ) void f( T, U ) { sout | "fTU"; } 36 41 37 42 int x; 38 43 float y; 39 int *z; 40 float *w; 41 44 int * z; 45 float * w; 46 47 f( x, x ); 48 f( y, y ); 49 f( w, w ); 42 50 f( x, y ); 43 51 f( z, w ); … … 50 58 51 59 forall( T ) 52 void swap( T left, T right ) { 53 T temp = left; 54 left = right; 55 right = temp; 56 } 57 58 trait sumable( T ) { 60 void swap( T & left, T & right ) { // by reference 61 T temp = left; 62 left = right; 63 right = temp; 64 } 65 66 forall( T ) 67 [ T, T ] swap( T i, T j ) { // by value 68 return [ j, i ]; 69 } 70 71 forall( T ) trait sumable { 59 72 void ?{}( T &, zero_t ); // 0 literal constructor 60 73 T ?+?( T, T ); // assortment of additions … … 64 77 }; // sumable 65 78 66 forall( T | sumable( T ) ) // use trait79 forall( T | sumable( T ) ) // use trait 67 80 T sum( size_t size, T a[] ) { 68 81 T total = 0; // initialize by 0 constructor … … 72 85 } // sum 73 86 74 forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &, T ); } )87 forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &, T ); } ) 75 88 T twice( T t ) { 76 89 return t + t; … … 82 95 } 83 96 84 intfred() {85 int x = 1, y = 2, a[10] ;97 void fred() { 98 int x = 1, y = 2, a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 86 99 float f; 87 100 101 sout | x | y; 88 102 swap( x, y ); 89 twice( x ); 103 sout | x | y | nl | swap( x, y ); 104 // [ x, y ] = swap( y, x ); 105 sout | twice( ' ' ) | ' ' | twice( 0hh ) | twice( 1h ) | twice( 0n ) | twice( 2 ) 106 | twice( 3.2f ) | twice( 3.2 ) | twice( 3.2d ) | twice( 3.2+1.5i ) | twice( x ); 90 107 f = min( 4.0, 3.0 ); 91 sum( 10, a ); 108 sout | f | min( 4.0, 3.0 ); 109 sout | sum( 10, a ); 92 110 } 93 111 … … 177 195 178 196 forall( T ) struct S { T t; } (int) x, y, z; 179 forall( T ) struct { T t; } (int) a, b, c;197 static forall( T ) struct { T t; } (int) a, b, c; 180 198 181 199 forall( T ) static forall( S ) { … … 186 204 187 205 forall( T ) { 188 extern "C" {206 // extern "C" { 189 207 struct SS { T t; }; 190 T foo( T ) {}191 }208 T foo( T p ) { return p; } 209 // } 192 210 } 193 211 … … 195 213 W(int,int) w; 196 214 197 intjane() {215 void jane() { 198 216 // int j = bar( 3, 4 ); 199 217 int k = baz( 3, 4, 5 ); 200 218 int i = foo( 3 ); 219 sout | k | i; 201 220 } 202 221 … … 211 230 T t; 212 231 T t2 = t; 232 sout | &tr | tp; 213 233 } 214 234 … … 242 262 243 263 int main( void ) { 244 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 264 g1(); 265 g2(); 266 fred(); 267 jane(); 245 268 } 246 269 -
tests/function-operator.cfa
r34b4268 r24d6572 10 10 // Created On : Fri Aug 25 15:21:11 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 11 18:27:45 201913 // Update Count : 1 012 // Last Modified On : Sat Feb 25 07:26:10 2023 13 // Update Count : 12 14 14 // 15 15 … … 22 22 23 23 // STL-like Algorithms 24 trait Assignable(T &, U &) { T ?=?(T &, U); }; 25 trait Copyable(T &) { void ?{}(T &, T); }; 26 trait Destructable(T &) { void ^?{}(T &); }; 24 forall(T &, U &) 25 trait Assignable { T ?=?(T &, U); }; 26 forall(T &) 27 trait Copyable { void ?{}(T &, T); }; 28 forall(T &) 29 trait Destructable { void ^?{}(T &); }; 27 30 28 31 trait Iterator(iter & | sized(iter) | Copyable(iter) | Destructable(iter), T) { -
tests/include/includes.cfa
r34b4268 r24d6572 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun May 22 08:27:20 202213 // Update Count : 77912 // Last Modified On : Wed Feb 22 10:16:58 2023 13 // Update Count : 811 14 14 // 15 15 … … 72 72 #include <gshadow.h> 73 73 #include <iconv.h> 74 #include <ifaddrs.h> 74 //#include <ifaddrs.h> // causes warning messages that break the build 75 75 #include <inttypes.h> 76 76 #include <langinfo.h> … … 97 97 #include <ncurses_dll.h> // may not be installed, comes with ncurses 98 98 #endif 99 #include <netdb.h>99 //#include <netdb.h> 100 100 #include <nl_types.h> 101 101 #include <nss.h> … … 111 111 #include <pwd.h> 112 112 #include <regex.h> 113 #include <resolv.h>113 //#include <resolv.h> 114 114 #include <re_comp.h> 115 115 #include <sched.h> … … 170 170 #endif // __CFA__ 171 171 172 int main( int argc, char const * argv[]) {172 int main() { 173 173 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 174 174 } -
tests/io/comp_basic.cfa
r34b4268 r24d6572 26 26 #include <unistd.h> 27 27 28 st ruct {28 static struct { 29 29 barrier & bar; 30 30 int pipe[2]; 31 32 31 } globals; 33 32 -
tests/io/comp_fair.cfa
r34b4268 r24d6572 26 26 #include <unistd.h> 27 27 28 st ruct {28 static struct { 29 29 barrier & bar; 30 30 int pipe[2]; 31 32 31 } globals; 33 32 -
tests/linking/mangling/header.hfa
r34b4268 r24d6572 8 8 extern name_but_a_typedefed_t a_typedefed_global; 9 9 10 extern struct /* anonymous */ { 11 int some_int; 12 int some_other_int; 13 } a_global_with_no_type; 10 // Must be extern C to prevent name mangling. 11 extern "C" { 12 extern struct /* anonymous */ { 13 int some_int; 14 int some_other_int; 15 } a_global_with_no_type; 16 } -
tests/linking/mangling/lib.cfa
r34b4268 r24d6572 3 3 name_but_a_typedefed_t a_typedefed_global; 4 4 5 struct { 6 int some_int; 7 int some_other_int; 8 } a_global_with_no_type; 5 // Must be extern C to prevent name mangling. 6 extern "C" { 7 // This declaration is necessary to create an instance of a_global_with_no_type. 8 // typeof is a trick to get a_global_with_no_type's type because its type is anonymous. 9 // Otherwise C generates conflicting types for a_global_with_no_type in .h and .c 10 // because C uses name equivalence and the two anonymous types cannot have the same name. 11 typeof(a_global_with_no_type) a_global_with_no_type; 12 } -
tests/linking/mangling/main.cfa
r34b4268 r24d6572 1 1 #include <fstream.hfa> 2 2 3 st ruct { int a; } test; //purposefully before the include3 static struct { int a; } test; // purposefully before the include to force anonymous name numbering 4 4 5 5 #include "header.hfa" … … 13 13 14 14 sout | "Done!"; 15 16 return 0;17 15 } -
tests/pybin/settings.py
r34b4268 r24d6572 126 126 global archive 127 127 global install 128 global invariant 128 129 129 130 global continue_ … … 140 141 all_install = [Install(o) for o in list(dict.fromkeys(options.install))] 141 142 archive = os.path.abspath(os.path.join(original_path, options.archive_errors)) if options.archive_errors else None 143 invariant = options.invariant 142 144 continue_ = options.continue_ 143 145 dry_run = options.dry_run # must be called before tools.config_hash() -
tests/quotedKeyword.cfa
r34b4268 r24d6572 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 7 19:07:07 202013 // Update Count : 2 512 // Last Modified On : Thu Feb 23 20:31:05 2023 13 // Update Count : 26 14 14 // 15 15 16 16 #include <fstream.hfa> 17 17 18 st ruct {18 static struct { 19 19 int ``otype; 20 20 int ``struct; -
tests/sum.cfa
r34b4268 r24d6572 11 11 // Created On : Wed May 27 17:56:53 2015 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Thu Aug 5 21:27:25 202114 // Update Count : 34 613 // Last Modified On : Fri Feb 24 22:52:12 2023 14 // Update Count : 347 15 15 // 16 16 … … 18 18 #include <stdlib.hfa> 19 19 20 trait sumable( T ) { 20 forall( T ) 21 trait sumable { 21 22 void ?{}( T &, zero_t ); // 0 literal constructor 22 23 void ?{}( T &, one_t ); // 1 literal constructor -
tests/test.py
r34b4268 r24d6572 114 114 parser.add_argument('--install', help='Run all tests based on installed binaries or tree binaries', type=comma_separated(yes_no), default='no') 115 115 parser.add_argument('--continue', help='When multiple specifications are passed (debug/install/arch), sets whether or not to continue if the last specification failed', type=yes_no, default='yes', dest='continue_') 116 parser.add_argument('--invariant', help='Tell the compiler to check invariants while running.', action='store_true') 116 117 parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180) 117 118 parser.add_argument('--global-timeout', help='Maximum cumulative duration in seconds after the ALL tests are considered to have timed out', type=int, default=7200) … … 172 173 test.prepare() 173 174 175 # extra flags for cfa to pass through make. 176 cfa_flags = 'CFAFLAGS=--invariant' if settings.invariant else None 177 174 178 # ---------- 175 179 # MAKE … … 177 181 # build, skipping to next test on error 178 182 with Timed() as comp_dur: 179 make_ret, _, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file)183 make_ret, _, _ = make(test.target(), flags=cfa_flags, output_file=subprocess.DEVNULL, error=out_file, error_file=err_file) 180 184 181 185 # ----------
Note:
See TracChangeset
for help on using the changeset viewer.