Changes in / [b110bcc:2ed94a9]
- Files:
-
- 5 added
- 227 deleted
- 179 edited
-
Jenkins/Promote (modified) (2 diffs)
-
doc/LaTeXmacros/common.sty (modified) (7 diffs)
-
doc/LaTeXmacros/common.tex (modified) (5 diffs)
-
doc/bibliography/pl.bib (modified) (54 diffs)
-
doc/theses/colby_parsons_MMAth/.gitignore (deleted)
-
doc/theses/colby_parsons_MMAth/Makefile (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/AkkaExecutor.scala (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Executor/build.sbt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/AkkaMatrix.scala (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Matrix/build.sbt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/AkkaRepeat.scala (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/Repeat/build.sbt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/AkkaSendDynamic.scala (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendDynamic/build.sbt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/AkkaSendStatic.scala (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/akka/SendStatic/build.sbt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFExecutor.cpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFMatrix.cpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFRepeat.cpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFSendDynamic.cpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/CAFSendStatic.cpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/caf/caf-application.conf (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/balance.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/bench.hfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/dynamic.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/executor.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/matrix.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/repeat.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/cfa/static.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasusSendDynamic (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasusSendStatic (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_ALL.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_CFA.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_SEND.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pykeSendDynamic (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pykeSendStatic (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_ALL.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_CFA.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_SEND.txt (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/genPlots (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/plotData.py (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/GoExecutor.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Executor/go.sum (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/INSTALL (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/GoMatrix.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Matrix/go.sum (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/GoRepeat.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/Repeat/go.sum (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/GoSendDynamic.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendDynamic/go.sum (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/GoSendStatic.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/proto/SendStatic/go.sum (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/run (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Executor.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Matrix.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++Repeat.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++SendDynamic.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/ucpp/uC++SendStatic.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/barrier.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/churn.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/contend.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/daisy_chain.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/hot_potato.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/ping_pong.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/cfa/pub_sub.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/barrier/barrier.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/barrier/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/churn/churn.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/churn/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/contend/contend.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/contend/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/daisy_chain/daisy_chain.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/daisy_chain/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/hot_potato/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/hot_potato/hot_potato.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/ping_pong/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/ping_pong/ping_pong.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/pub_sub/go.mod (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/go/pub_sub/pub_sub.go (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/plotData.py (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/run (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/bench.h (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/baseline.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/order.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cfa/rand.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/baseline.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/cppLock.hpp (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/order.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/cpp/rand.cc (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/plotData.py (deleted)
-
doc/theses/colby_parsons_MMAth/benchmarks/mutex_stmt/run (deleted)
-
doc/theses/colby_parsons_MMAth/code/basic_actor_example.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/code/swap_queues.cfa (deleted)
-
doc/theses/colby_parsons_MMAth/data/nasusExecutorMem (deleted)
-
doc/theses/colby_parsons_MMAth/data/nasusSendDynamic (deleted)
-
doc/theses/colby_parsons_MMAth/data/nasusSendStatic (deleted)
-
doc/theses/colby_parsons_MMAth/data/pykeExecutorMem (deleted)
-
doc/theses/colby_parsons_MMAth/data/pykeSendDynamic (deleted)
-
doc/theses/colby_parsons_MMAth/data/pykeSendStatic (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/M_to_one_swap.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/acyclic_swap.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/chain_swap.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/cyclic_swap.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/gulp.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/inverted_actor.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/diagrams/standard_actor.tikz (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFABalance-Multi.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFABalance-One.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFAExecutor.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFAMatrix.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusCFARepeat.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusExecutor.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusMatrix.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasusRepeat.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_2.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_4.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Aggregate_Lock_8.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/nasus_Channel_Contention.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFABalance-Multi.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFABalance-One.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFAExecutor.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFAMatrix.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeCFARepeat.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeExecutor.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeMatrix.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pykeRepeat.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_2.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_4.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Aggregate_Lock_8.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/figures/pyke_Channel_Contention.pgf (deleted)
-
doc/theses/colby_parsons_MMAth/glossary.tex (deleted)
-
doc/theses/colby_parsons_MMAth/local.bib (deleted)
-
doc/theses/colby_parsons_MMAth/style/cfa-format.tex (deleted)
-
doc/theses/colby_parsons_MMAth/style/style.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/CFA_concurrency.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/CFA_intro.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/actors.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/channels.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/frontpgs.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/intro.tex (deleted)
-
doc/theses/colby_parsons_MMAth/text/mutex_stmt.tex (deleted)
-
doc/theses/colby_parsons_MMAth/thesis.tex (deleted)
-
doc/theses/colby_parsons_MMAth/version (deleted)
-
doc/theses/colby_parsons_MMAth/version.sh (deleted)
-
doc/theses/mike_brooks_MMath/Makefile (modified) (5 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/.gitignore (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/Makefile (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/driver.c (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.queue-insfirst.txt (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.queue-inslast.txt (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.stack-insfirst.txt (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/expect.stack-inslast.txt (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-cfa-cfa.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-cpp-stlref.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-lq-list.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-lq-tailq.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/fx-upp-upp.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.c (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-allhead.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-inselem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-remelem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-allhead.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-inselem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-remelem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-allhead.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-inselem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-remelem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-allhead.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-inselem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-remelem.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/proglang.h (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-baseline.csv (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-sizing.csv (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/tailq-bug.c (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/test-correctness-regenerate-expected.sh (deleted)
-
doc/theses/mike_brooks_MMath/benchmarks/list/test-correctness.sh (deleted)
-
doc/theses/mike_brooks_MMath/list.tex (deleted)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-attach.pdf (deleted)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-attach.vsdx (deleted)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-direct.pdf (deleted)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-direct.vsdx (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-features-intro.run.cfa (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-features-multidir.run.cfa (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction-byref.run.cpp (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction-emplaced.run.cpp (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-attach-reduction.hpp (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-intrusive.run.c (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-multi-static.run.c (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-wrapped-byref.run.cpp (deleted)
-
doc/theses/mike_brooks_MMath/programs/lst-issues-wrapped-emplaced.run.cpp (deleted)
-
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) (5 diffs)
-
libcfa/src/Makefile.am (modified) (1 diff)
-
libcfa/src/algorithms/range_iterator.hfa (modified) (1 diff)
-
libcfa/src/bitmanip.hfa (modified) (1 diff)
-
libcfa/src/bits/random.hfa (modified) (18 diffs)
-
libcfa/src/concurrency/actor.hfa (modified) (17 diffs)
-
libcfa/src/concurrency/channel.hfa (modified) (4 diffs)
-
libcfa/src/concurrency/clib/cfathread.cfa (modified) (6 diffs)
-
libcfa/src/concurrency/clib/cfathread.h (modified) (3 diffs)
-
libcfa/src/concurrency/coroutine.cfa (modified) (1 diff)
-
libcfa/src/concurrency/future.hfa (modified) (1 diff)
-
libcfa/src/concurrency/invoke.h (modified) (1 diff)
-
libcfa/src/concurrency/io.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/io/call.cfa.in (modified) (11 diffs)
-
libcfa/src/concurrency/io/setup.cfa (modified) (1 diff)
-
libcfa/src/concurrency/iofwd.hfa (modified) (5 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/cluster.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/kernel/cluster.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/private.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/locks.cfa (modified) (1 diff)
-
libcfa/src/concurrency/locks.hfa (modified) (10 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (1 diff)
-
libcfa/src/concurrency/mutex.cfa (modified) (1 diff)
-
libcfa/src/concurrency/mutex_stmt.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/preemption.cfa (modified) (1 diff)
-
libcfa/src/concurrency/pthread.cfa (modified) (37 diffs)
-
libcfa/src/concurrency/ready_queue.cfa (modified) (1 diff)
-
libcfa/src/concurrency/select.hfa (modified) (1 diff)
-
libcfa/src/concurrency/thread.cfa (modified) (1 diff)
-
libcfa/src/containers/array.hfa (modified) (1 diff)
-
libcfa/src/containers/list.hfa (modified) (1 diff)
-
libcfa/src/containers/vector2.hfa (modified) (1 diff)
-
libcfa/src/interpose.cfa (modified) (5 diffs)
-
libcfa/src/interpose_thread.cfa (modified) (3 diffs)
-
libcfa/src/iostream.cfa (modified) (2 diffs)
-
libcfa/src/limits.cfa (modified) (1 diff)
-
libcfa/src/stdlib.cfa (modified) (2 diffs)
-
libcfa/src/vec/vec.hfa (modified) (1 diff)
-
libcfa/src/virtual_dtor.hfa (deleted)
-
src/AST/Attribute.hpp (modified) (1 diff)
-
src/AST/Convert.cpp (modified) (4 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.hpp (modified) (4 diffs)
-
src/AST/Fwd.hpp (modified) (2 diffs)
-
src/AST/Init.hpp (modified) (1 diff)
-
src/AST/Inspect.cpp (modified) (2 diffs)
-
src/AST/Inspect.hpp (modified) (2 diffs)
-
src/AST/ParseNode.hpp (modified) (1 diff)
-
src/AST/Pass.impl.hpp (modified) (2 diffs)
-
src/AST/Pass.proto.hpp (modified) (1 diff)
-
src/AST/Print.cpp (modified) (11 diffs)
-
src/AST/Print.hpp (modified) (2 diffs)
-
src/AST/Stmt.hpp (modified) (6 diffs)
-
src/AST/SymbolTable.cpp (modified) (5 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/porting.md (modified) (3 diffs)
-
src/CodeGen/CodeGenerator.cc (modified) (1 diff)
-
src/Common/CodeLocationTools.cpp (modified) (2 diffs)
-
src/Common/CompilerError.h (added)
-
src/Common/Debug.h (added)
-
src/Common/DeclStats.cpp (modified) (1 diff)
-
src/Common/Eval.cc (modified) (2 diffs)
-
src/Common/Eval.h (deleted)
-
src/Common/Iterate.hpp (deleted)
-
src/Common/ResolvProtoDump.cpp (modified) (2 diffs)
-
src/Common/SemanticError.h (modified) (2 diffs)
-
src/Common/ToString.hpp (deleted)
-
src/Common/UnimplementedError.h (added)
-
src/Common/module.mk (modified) (3 diffs)
-
src/Common/utility.h (modified) (7 diffs)
-
src/CompilationState.cc (modified) (2 diffs)
-
src/CompilationState.h (modified) (2 diffs)
-
src/Concurrency/Actors.cpp (modified) (16 diffs)
-
src/Concurrency/Actors.hpp (modified) (1 diff)
-
src/Concurrency/KeywordsNew.cpp (modified) (1 diff)
-
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) (3 diffs)
-
src/GenPoly/FindFunction.cc (modified) (3 diffs)
-
src/GenPoly/FindFunction.h (modified) (2 diffs)
-
src/GenPoly/GenPoly.cc (modified) (4 diffs)
-
src/GenPoly/GenPoly.h (modified) (1 diff)
-
src/GenPoly/Lvalue.cc (modified) (1 diff)
-
src/GenPoly/LvalueNew.cpp (modified) (1 diff)
-
src/InitTweak/FixInit.cc (modified) (2 diffs)
-
src/InitTweak/FixInitNew.cpp (modified) (13 diffs)
-
src/InitTweak/GenInit.cc (modified) (2 diffs)
-
src/Parser/DeclarationNode.cc (modified) (45 diffs)
-
src/Parser/DeclarationNode.h (deleted)
-
src/Parser/ExpressionNode.cc (modified) (19 diffs)
-
src/Parser/ExpressionNode.h (deleted)
-
src/Parser/InitializerNode.cc (modified) (4 diffs)
-
src/Parser/InitializerNode.h (deleted)
-
src/Parser/ParseNode.h (modified) (5 diffs)
-
src/Parser/ParserTypes.h (modified) (1 diff)
-
src/Parser/RunParser.cpp (modified) (3 diffs)
-
src/Parser/RunParser.hpp (modified) (3 diffs)
-
src/Parser/StatementNode.cc (modified) (8 diffs)
-
src/Parser/StatementNode.h (deleted)
-
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) (4 diffs)
-
src/Parser/module.mk (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (133 diffs)
-
src/Parser/parserutility.cc (modified) (3 diffs)
-
src/Parser/parserutility.h (modified) (1 diff)
-
src/ResolvExpr/Candidate.cpp (modified) (2 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (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/ResolveAssertions.cc (modified) (1 diff)
-
src/ResolvExpr/Resolver.cc (modified) (1 diff)
-
src/ResolvExpr/Resolver.h (modified) (1 diff)
-
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 (deleted)
-
src/SymTab/GenImplicitCall.hpp (deleted)
-
src/SymTab/Mangler.cc (modified) (1 diff)
-
src/SymTab/Validate.cc (modified) (1 diff)
-
src/SymTab/ValidateType.cc (modified) (1 diff)
-
src/SymTab/module.mk (modified) (1 diff)
-
src/SynTree/AggregateDecl.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/Validate/Autogen.cpp (modified) (3 diffs)
-
src/Validate/FixQualifiedTypes.cpp (modified) (1 diff)
-
src/Validate/ForallPointerDecay.cpp (modified) (1 diff)
-
src/Validate/HandleAttributes.cc (modified) (1 diff)
-
src/Validate/HoistStruct.cpp (modified) (1 diff)
-
src/Virtual/VirtualDtor.cpp (deleted)
-
src/Virtual/VirtualDtor.hpp (deleted)
-
src/Virtual/module.mk (modified) (1 diff)
-
src/include/cassert (modified) (1 diff)
-
src/main.cc (modified) (17 diffs)
-
tests/.expect/PRNG.x64.txt (modified) (1 diff)
-
tests/.expect/PRNG.x86.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/nested_function.x64.txt (modified) (1 diff)
-
tests/.expect/nested_function.x86.txt (modified) (1 diff)
-
tests/Makefile.am (modified) (2 diffs)
-
tests/PRNG.cfa (modified) (16 diffs)
-
tests/attributes.cfa (modified) (2 diffs)
-
tests/avltree/avl.h (modified) (1 diff)
-
tests/concurrent/actors/.expect/inherit.txt (deleted)
-
tests/concurrent/actors/.expect/poison.txt (deleted)
-
tests/concurrent/actors/.expect/types.txt (modified) (1 diff)
-
tests/concurrent/actors/dynamic.cfa (modified) (4 diffs)
-
tests/concurrent/actors/executor.cfa (modified) (5 diffs)
-
tests/concurrent/actors/inherit.cfa (deleted)
-
tests/concurrent/actors/matrix.cfa (modified) (3 diffs)
-
tests/concurrent/actors/pingpong.cfa (modified) (4 diffs)
-
tests/concurrent/actors/poison.cfa (deleted)
-
tests/concurrent/actors/static.cfa (modified) (4 diffs)
-
tests/concurrent/actors/types.cfa (modified) (7 diffs)
-
tests/concurrent/channels/.expect/churn.txt (deleted)
-
tests/concurrent/channels/.expect/contend.txt (deleted)
-
tests/concurrent/channels/.expect/daisy_chain.txt (deleted)
-
tests/concurrent/channels/.expect/hot_potato.txt (deleted)
-
tests/concurrent/channels/.expect/ping_pong.txt (deleted)
-
tests/concurrent/channels/.expect/pub_sub.txt (deleted)
-
tests/concurrent/channels/barrier.cfa (deleted)
-
tests/concurrent/channels/churn.cfa (deleted)
-
tests/concurrent/channels/contend.cfa (deleted)
-
tests/concurrent/channels/daisy_chain.cfa (deleted)
-
tests/concurrent/channels/hot_potato.cfa (deleted)
-
tests/concurrent/channels/parallel_harness.hfa (modified) (4 diffs)
-
tests/concurrent/channels/ping_pong.cfa (deleted)
-
tests/concurrent/channels/pub_sub.cfa (deleted)
-
tests/concurrent/pthread/.expect/bounded_buffer.x64.txt (modified) (1 diff)
-
tests/concurrent/pthread/.expect/bounded_buffer.x86.txt (modified) (1 diff)
-
tests/concurrent/signal/disjoint.cfa (modified) (1 diff)
-
tests/concurrent/waitfor/parse.cfa (modified) (2 diffs)
-
tests/concurrent/waitfor/parse2.cfa (added)
-
tests/declarationSpecifier.cfa (modified) (3 diffs)
-
tests/errors/.expect/declaration.txt (modified) (3 diffs)
-
tests/forall.cfa (modified) (2 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 (deleted)
-
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/zombies/prolog.c (added)
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/Promote
rb110bcc r2ed94a9 36 36 dir (BuildDir) { 37 37 sh 'rm -rf *' 38 sshagent (credentials: ['git _key_mar27']) {38 sshagent (credentials: ['github_key_jun1']) { 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 _key_mar27']) {71 sshagent (credentials: ['github_key_jun1']) { 72 72 sh "git push origin master" 73 73 } -
doc/LaTeXmacros/common.sty
rb110bcc r2ed94a9 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 4 12:03:19 202314 %% Update Count : 5 8513 %% Last Modified On : Sat Apr 2 17:35:23 2022 14 %% Update Count : 570 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \setlist[itemize,1]{label=\textbullet}% local 31 31 %\renewcommand{\labelitemi}{{\raisebox{0.25ex}{\footnotesize$\bullet$}}} 32 \setlist[enumerate]{ topsep=0.5ex,parsep=0.25ex,itemsep=0.25ex,listparindent=\parindent}% global32 \setlist[enumerate]{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}{\ relsize{2}$^\sharp$}\xspace} % C# symbolic name51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\Large$^\sharp$}\xspace} % C# symbolic name 52 52 53 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 54 55 \usepackage[scaled=0.85]{helvet} % descent Helvetica font and scale to times size 56 \usepackage[T1]{fontenc} 55 \usepackage{pslatex} % reduce size of san serif font 57 56 \usepackage{relsize} % must be after change to small or selects old size 58 57 \usepackage{rotating} … … 196 195 \newcommand{\viz}{\VIZ\CheckPeriod} 197 196 198 \newcommand{\VS}{\abbrevFont{vs}}199 \newcommand{\vs}{\VS\CheckPeriod}200 201 197 \newenvironment{cquote}{% 202 198 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}% … … 248 244 \renewcommand{\reftextpagerange}[2]{\unskip, pp.~\pageref{#1}--\pageref{#2}} 249 245 \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}}251 246 \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}}253 247 254 248 \let\Oldthebibliography\thebibliography … … 266 260 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 267 261 \newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}} 268 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}}269 262 270 263 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly … … 287 280 columns=fullflexible, 288 281 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font 289 stringstyle=\ small\tt,% use typewriter font282 stringstyle=\tt, % use typewriter font 290 283 tabsize=5, % N space tabbing 291 284 xleftmargin=\parindentlnth, % indent code to paragraph indentation -
doc/LaTeXmacros/common.tex
rb110bcc r2ed94a9 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 4 12:03:18 202314 %% Update Count : 5 6713 %% Last Modified On : Tue Apr 26 16:02:48 2022 14 %% Update Count : 558 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}{\ relsize{2}$^\sharp$}\xspace} % C# symbolic name51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\Large$^\sharp$}\xspace} % C# symbolic name 52 52 53 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 54 55 \usepackage[scaled=0.85]{helvet} % descent Helvetica font and scale to times size 56 \usepackage[T1]{fontenc} 55 \usepackage{pslatex} % reduce size of san serif font 57 56 \usepackage{relsize} % must be after change to small or selects old size 58 57 \usepackage{rotating} … … 197 196 \newcommand{\viz}{\VIZ\CheckPeriod} 198 197 199 \newcommand{\VS}{\abbrevFont{vs}}200 \newcommand{\vs}{\VS\CheckPeriod}201 198 \makeatother 202 199 … … 269 266 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 270 267 \newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}} 271 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}}272 268 273 269 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly … … 291 287 columns=fullflexible, 292 288 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font 293 stringstyle=\ small\tt,% use typewriter font289 stringstyle=\tt, % use typewriter font 294 290 tabsize=5, % N space tabbing 295 291 xleftmargin=\parindentlnth, % indent code to paragraph indentation -
doc/bibliography/pl.bib
rb110bcc r2ed94a9 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 organization= {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation},149 booktitle = {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation}, 150 150 series = {PLDI'16}, 151 151 year = {2016}, … … 196 196 }, 197 197 comment = {Mentions Thoth in reference to delegation} 198 }199 200 @misc{ActorBenchmarks,201 keywords = {Actors, microbenchmarks, uC++. CAF, AkkaC, AkkaT, ProtoActor},202 contributer = {pabuhr@plg},203 key = {ActorBenchmarks},204 title = {Actor Benchmarks},205 author = {Peter A. Buhr and Colby A. Parsons},206 howpublished= {\href{https://github.com/pabuhr/ActorExperiments}{https://\-github.com/\-pabuhr/\-ActorExperiments}},207 year = 2022,208 198 } 209 199 … … 255 245 } 256 246 257 @manual{Ada95,258 keywords = {Ada},259 contributer = {pabuhr@plg},260 title = {{A}da Reference Manual},261 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},262 organization= {Intermetrics, Inc.},263 month = dec,264 year = 1995,265 note = {Language and Standards Libraries}266 }267 268 @manual{Ada12,269 keywords = {ISO/IEC Ada},270 contributer = {pabuhr@plg},271 author = {Ada12},272 title = {Programming languages -- {Ada} ISO/IEC 8652:2012},273 edition = {3rd},274 organization= {International Standard Organization},275 address = {Geneva, Switzerland},276 year = 2012,277 note = {\href{https://www.iso.org/standard/61507.html}{https://\-www.iso.org/\-standard/\-61507.html}},278 }279 280 @manual{Ada95:annotated,281 keywords = {Ada},282 contributer = {pabuhr@plg},283 title = {Annotated {A}da Reference Manual},284 edition = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},285 organization= {Intermetrics, Inc.},286 month = dec,287 year = 1995,288 note = {Language and Standards Libraries}289 }290 291 247 @article{dim:ada, 292 248 keywords = {Dimensional Analysis, Ada}, … … 300 256 number = 2, 301 257 pages = {189-203}, 302 }303 304 @article{Agrawal08,305 keywords = {Adaptive scheduling, adversary, instantaneous parallelism, job scheduling, multiprocessing, multiprogramming, parallel computation, parallelism feedback, processor allocation, randomized algorithm, space sharing, span, thread scheduling, trim analysis, two-level scheduling, work, work-stealing},306 author = {Agrawal, Kunal and Leiserson, Charles E. and He, Yuxiong and Hsu, Wen Jing},307 title = {Adaptive Work-stealing with Parallelism Feedback},308 journal = {ACM Trans. Comput. Syst.},309 issue_date = {September 2008},310 volume = {26},311 number = {3},312 month = sep,313 year = {2008},314 pages = {7:1-7:32},315 publisher = {ACM},316 address = {New York, NY, USA},317 258 } 318 259 … … 436 377 year = 2016, 437 378 note = {\href{http://doc.akka.io/docs/akka/2.4/AkkaScala.pdf}{http://\-doc.akka.io/\-docs/\-akka/\-2.4/\-AkkaScala.pdf}}, 438 }439 440 @misc{AkkaFuture,441 contributer = {pabuhr@plg},442 key = {AkkaFuture},443 title = {Akka Futures},444 author = {{Lightbend}},445 howpublished= {\href{https://doc.akka.io/docs/akka/2.5/futures.html}{https://\-doc.akka.io/\-docs/\-akka/\-2.5/\-futures.html}},446 year = 2022,447 379 } 448 380 … … 616 548 } 617 549 618 @inproceedings{Mitzenmacher98,619 author = {Mitzenmacher, Michael},620 title = {Analyses of Load Stealing Models Based on Differential Equations},621 organization= {Proceedings of the Tenth Annual ACM Symposium on Parallel Algorithms and Architectures},622 series = {SPAA '98},623 year = {1998},624 isbn = {0-89791-989-0},625 location = {Puerto Vallarta, Mexico},626 pages = {212-221},627 publisher = {ACM},628 address = {New York, NY, USA},629 }630 631 @inproceedings{Squillante91,632 author = {Squillante, Mark S. and Nelson, Randolph D.},633 title = {Analysis of Task Migration in Shared-memory Multiprocessor Scheduling},634 organization= {Proceedings of the 1991 ACM SIGMETRICS Conference on Measurement and Modeling of Computer Systems},635 series = {SIGMETRICS '91},636 year = {1991},637 isbn = {0-89791-392-2},638 location = {San Diego, California, USA},639 pages = {143-155},640 publisher = {ACM},641 address = {New York, NY, USA},642 }643 644 550 @article{Sinha00, 645 551 author = {Saurabh Sinha and Mary Jean Harrold}, … … 656 562 author = {Martin P. Robillard and Gail C. Murphy}, 657 563 title = {Analyzing Exception Flow in {J}ava Programs}, 658 organization= {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly564 booktitle = {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly 659 565 with the 7th ACM SIGSOFT International Symposium on Foundations of Software Engineering}, 660 566 year = 1999, … … 698 604 author = {Henry Qin and Qian Li and Jacqueline Speiser and Peter Kraft and John Ousterhout}, 699 605 title = {Arachne: Core-Aware Thread Management}, 700 organization= {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)},606 booktitle = {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)}, 701 607 year = {2018}, 702 608 address = {Carlsbad, CA}, … … 755 661 author = {Jaewoong Chung and Luke Yen and Stephan Diestelhorst and Martin Pohlack and Michael Hohmuth and David Christie and Dan Grossman}, 756 662 title = {ASF: AMD64 Extension for Lock-Free Data Structures and Transactional Memory}, 757 organization= {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture},663 booktitle = {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture}, 758 664 series = {MICRO '43}, 759 665 year = 2010, … … 776 682 } 777 683 778 @misc{AsyncAwait,779 contributer = {pabuhr@plg},780 key = {AsyncAwait},781 title = {Async Await},782 author = {{WikipediA}},783 howpublished= {\href{https://en.wikipedia.org/wiki/Async/await}{https://\-en.wikipedia.org/\-wiki/\-Async/\-await}},784 year = 2022,785 }786 787 684 @inproceedings{Krischer08, 788 685 keywords = {exception handling, asynchronous, blocked tasks}, … … 790 687 author = {Roy Krischer and Peter A. Buhr}, 791 688 title = {Asynchronous Exception Propagation in Blocked Tasks}, 792 organization= {4th International Workshop on Exception Handling (WEH.08)},689 booktitle = {4th International Workshop on Exception Handling (WEH.08)}, 793 690 optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)}, 794 691 address = {Atlanta, U.S.A}, … … 799 696 800 697 @article{Joung00, 801 keywords = {group mutual exclusion, congenial talking philosophers, resource allocation, shared-memory algorithms},802 698 author = {Joung, Yuh-Jzer}, 803 699 title = {Asynchronous group mutual exclusion}, … … 863 759 publisher = {ACM}, 864 760 address = {New York, NY, USA}, 865 }866 867 @techreport{Neill09,868 author = {Daniel Neill and Adam Wierman},869 title = {On the Benefits of Work Stealing in Shared-Memory Multiprocessors},870 institution = {Carnegie Mellon University},871 address = {California Institute of Technology, Pasadena, CA, USA},872 note = {\href{http://www.cs.cmu.edu/~acw/15740/paper.pdf}{http://\-www.cs.cmu.edu/\-$\sim$acw/\-15740/\-paper.pdf}, Accessed May 2014},873 year = 2009,874 761 } 875 762 … … 1029 916 } 1030 917 1031 @inproceedings{Ding12,1032 keywords = {fairness, multicore, time sharing, work stealing},1033 author = {Ding, Xiaoning and Wang, Kaibo and Gibbons, Phillip B. and Zhang, Xiaodong},1034 title = {BWS: Balanced Work Stealing for Time-sharing Multicores},1035 organization= {Proceedings of the 7th ACM European Conference on Computer Systems},1036 series = {EuroSys '12},1037 year = {2012},1038 location = {Bern, Switzerland},1039 pages = {365-378},1040 publisher = {ACM},1041 address = {New York, NY, USA},1042 }1043 1044 918 % C 1045 919 … … 1114 988 year = 2015, 1115 989 note = {\href{https://www.iso.org/standard/64031.html}{https://\-www.iso.org/\-standard/\-64031.html}}, 1116 }1117 1118 @inproceedings{CAF,1119 keywords = {performance measurement, actor model, c++, message-oriented middleware, distributed debugging},1120 author = {Charousset, Dominik and Hiesgen, Raphael and Schmidt, Thomas C.},1121 title = {{CAF} - the {C}++ Actor Framework for Scalable and Resource-Efficient Applications},1122 publisher = {ACM},1123 address = {New York, NY, USA},1124 organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},1125 pages = {15-28},1126 numpages = {14},1127 location = {Portland, Oregon, USA},1128 series = {AGERE'14},1129 year = {2014},1130 990 } 1131 991 … … 1312 1172 @techreport{Prokopec11, 1313 1173 keywords = {ctrie, concurrent map}, 1314 contributer = {a3moss@uwaterloo.ca},1174 contributer = {a3moss@uwaterloo.ca}, 1315 1175 title = {Cache-aware lock-free concurrent hash tries}, 1316 1176 author = {Prokopec, Aleksandar and Bagwell, Phil and Odersky, Martin}, … … 1636 1496 author = {Emery D. Berger and Benjamin G. Zorn and Kathryn S. McKinley}, 1637 1497 title = {Composing High-Performance Memory Allocators}, 1638 organization= {{SIGPLAN} Conference on Programming Language Design and Implementation},1498 booktitle = {{SIGPLAN} Conference on Programming Language Design and Implementation}, 1639 1499 pages = {114-124}, 1640 1500 year = 2001, … … 2136 1996 address = {Eindhoven, Neth.}, 2137 1997 year = 1965, 2138 optnote = {Reprinted in \cite{Genuys68} pp. 43--112.}, 2139 note = {\url{https://pure.tue.nl/ws/files/4279816/344354178746665.pdf}}, 1998 note = {Reprinted in \cite{Genuys68} pp. 43--112.} 2140 1999 } 2141 2000 … … 2144 2003 author = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.}, 2145 2004 title = {Cooperative Task Management Without Manual Stack Management}, 2146 organization= {Proc. of the General Track USENIX Tech. Conf.},2005 booktitle = {Proc. of the General Track USENIX Tech. Conf.}, 2147 2006 series = {ATEC '02}, 2148 2007 year = {2002}, … … 2252 2111 year = 2016, 2253 2112 note = {\href{http://dlang.org/spec/spec.html}{http://\-dlang.org/\-spec/\-spec.html}}, 2254 }2255 2256 @article{Acar02,2257 author = {Acar, Umut A. and Blelloch, Guy E. and Blumofe, Robert D.},2258 title = {The Data Locality of Work Stealing},2259 journal = {Theory of Computing Systems},2260 volume = {35},2261 number = {3},2262 year = {2002},2263 publisher = {Springer-Verlag},2264 pages = {321-347},2265 2113 } 2266 2114 … … 2522 2370 editor = {R. E. A. Mason}, 2523 2371 organization= {IFIP}, 2524 publisher = {North-Holland},2525 summary = {2372 publisher = {North-Holland}, 2373 summary = { 2526 2374 Packages group related declarations or subprograms, and encapsulate 2527 2375 data types. Separate interfaces and bodies promotes information … … 2750 2598 address = {Waterview Corporate Center, 20 Waterview Boulevard, Parsippany, NJ 07054}, 2751 2599 year = {1993} 2752 }2753 2754 @inproceedings{Chen14,2755 keywords = {Core allocation, Multi-programmed, Work-stealing},2756 author = {Chen, Quan and Zheng, Long and Guo, Minyi},2757 title = {DWS: Demand-aware Work-Stealing in Multi-programmed Multi-core Architectures},2758 organization= {Proceedings of Programming Models and Applications on Multicores and Manycores},2759 series = {PMAM'14},2760 year = {2007},2761 location = {Orlando, FL, USA},2762 pages = {131:131-131:139},2763 articleno = {131},2764 numpages = {9},2765 publisher = {ACM},2766 address = {New York, NY, USA},2767 2600 } 2768 2601 … … 2798 2631 year = 2003, 2799 2632 pages = {29-35}, 2800 }2801 2802 @inproceedings{Hamidzadeh96,2803 keywords = {processor scheduling, resource allocation, shared memory systems, average memory referencing delay},2804 author = {Hamidzadeh, B. and Lilja, D.J.},2805 booktitle = {Distributed Computing Systems, 1996., Proceedings of the 16th International Conference on},2806 title = {Dynamic scheduling strategies for shared-memory multiprocessors},2807 year = {1996},2808 month = {May},2809 pages = {208-215},2810 }2811 2812 @article{Hendler06,2813 keywords = {Concurrent programming; Load balancing; Work stealing; Lock-free; Data structures},2814 author = {Hendler, Danny and Lev, Yossi and Moir, Mark and Shavit, Nir},2815 title = {A dynamic-sized nonblocking work stealing deque},2816 journal = {Distributed Computing},2817 volume = {18},2818 number = {3},2819 year = {2006},2820 publisher = {Springer-Verlag},2821 pages = {189-207},2822 2633 } 2823 2634 … … 2923 2734 } 2924 2735 2925 @inproceedings{Blelloch04,2926 keywords = {chip multiprocessors, multithreaded architectures, scheduling algorithms, shared cache},2927 author = {Blelloch, Guy E. and Gibbons, Phillip B.},2928 title = {Effectively Sharing a Cache Among Threads},2929 organization= {Proceedings of the Sixteenth Annual ACM Symposium on Parallelism in Algorithms and Architectures},2930 series = {SPAA '04},2931 year = {2004},2932 location = {Barcelona, Spain},2933 pages = {235-244},2934 publisher = {ACM},2935 address = {New York, NY, USA},2936 }2937 2938 2736 @techreport{Habermann80, 2939 2737 keywords = {Ada, threads}, … … 3010 2808 title = {Encapsulation and Inheritance in Object-Oriented Programming Languages}, 3011 2809 journal = sigplan, 3012 volume = {21}, 3013 number = {11}, 2810 volume = {21}, number = {11}, 3014 2811 pages = {38-45}, 3015 month = nov, 3016 year = 1986, 2812 month = nov, year = 1986, 3017 2813 comment = { 3018 2814 Client, child interfaces should be distinct. Child interface … … 3070 2866 } 3071 2867 3072 @inproceedings{Ribic14,3073 keywords = {dvfs, energy efficiency, language runtimes, thread management, work stealing},3074 author = {Ribic, Haris and Liu, Yu David},3075 title = {Energy-efficient Work-stealing Language Runtimes},3076 organization= {Proceedings of the 19th International Conference on Architectural Support for Programming Languages and Operating Systems},3077 series = {ASPLOS '14},3078 year = {2014},3079 location = {Salt Lake City, Utah, USA},3080 pages = {513-528},3081 publisher = {ACM},3082 address = {New York, NY, USA},3083 }3084 3085 2868 @manual{EPT, 3086 2869 keywords = {concurrency, light-weight threads}, … … 3120 2903 publisher = {North Oxford Academic}, 3121 2904 year = 1985 3122 }3123 3124 @article{Torrellas95,3125 author = {J. Torrellas and A. Tucker and A. Gupta},3126 title = {Evaluating the Performance of Cache-Affinity Scheduling in Shared-Memory Multiprocessors},3127 journal = {Journal of Parallel and Distributed Computing},3128 volume = {24},3129 number = {2},3130 pages = {139-151},3131 year = {1995},3132 2905 } 3133 2906 … … 3841 3614 author = {Robert Griesemer and Rob Pike and Ken Thompson}, 3842 3615 title = {{Go} Programming Language}, 3843 address = {Mountain View, CA, USA},3844 3616 organization= {Google}, 3845 3617 year = 2009, … … 3953 3725 @article{Michael04a, 3954 3726 keywords = {Lock-free, synchronization, concurrent programming, memory management, multiprogramming, dynamic data structures}, 3955 contributer = {pabuhr@plg},3956 3727 author = {Maged M. Michael}, 3957 3728 title = {Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects}, … … 3964 3735 publisher = {IEEE Press}, 3965 3736 address = {Piscataway, NJ, USA}, 3966 }3967 3968 @inproceedings{Johansson02,3969 keywords = {concurrent languages, erlang, garbage collection, message passing, runtime systems},3970 contributer = {pabuhr@plg},3971 author = {Erik Johansson and Konstantinos Sagonas and Jesper Wilhelmsson},3972 title = {Heap Architectures for Concurrent Languages Using Message Passing},3973 year = {2002},3974 isbn = {1581135394},3975 publisher = {ACM},3976 address = {New York, NY, USA},3977 organization= {Proceedings of the 3rd International Symposium on Memory Management},3978 pages = {88-99},3979 location = {Berlin, Germany},3980 3737 } 3981 3738 … … 4160 3917 year = {1994}, 4161 3918 pages = {64-69}, 4162 }4163 4164 @inproceedings{Halstead84,4165 author = {Halstead,Jr., Robert H.},4166 title = {Implementation of Multilisp: Lisp on a Multiprocessor},4167 organization= {Proceedings of the 1984 ACM Symposium on LISP and Functional Programming},4168 series = {LFP '84},4169 year = {1984},4170 location = {Austin, Texas, USA},4171 pages = {9-17},4172 publisher = {ACM},4173 address = {New York, NY, USA},4174 3919 } 4175 3920 … … 4950 4695 contributer = {pabuhr@plg}, 4951 4696 author = {Lua}, 4952 title = {Lua 5.4 Reference Manual}, 4953 organization= {Pontifical Catholic University}, 4954 address = {\href{https://www.lua.org/manual/5.4}{https://\-www.lua.org/\-manual/\-5.4}}, 4955 year = 2020, 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, 4956 4700 } 4957 4701 … … 5533 5277 Programming Language}, 5534 5278 year = 1980, 5535 month = dec, 5536 pages = {139-145}, 5279 month = dec, pages = {139-145}, 5537 5280 note = {SIGPLAN Notices, v. 15, n. 11}, 5538 5281 abstract = { … … 5655 5398 year = 2005, 5656 5399 pages = {146-196}, 5657 publisher = {ACM},5658 address = {New York, NY, USA},5659 }5660 5661 @inproceedings{Hendler02,5662 author = {Hendler, Danny and Shavit, Nir},5663 title = {Non-blocking Steal-half Work Queues},5664 organization= {Proceedings of the Twenty-first Annual Symposium on Principles of Distributed Computing},5665 series = {PODC '02},5666 year = {2002},5667 location = {Monterey, California},5668 pages = {280-289},5669 5400 publisher = {ACM}, 5670 5401 address = {New York, NY, USA}, … … 5915 5646 } 5916 5647 5917 @misc{OpenTelemetry,5918 contributer = {pabuhr@plg},5919 key = {OpenTelemetry},5920 title = {OpenTelemetry},5921 author = {{Asynkron AB}},5922 howpublished= {\href{https://proto.actor/docs/tracing}{https://\-proto.actor/\-docs/\-tracing}},5923 year = 2022,5924 }5925 5926 5648 @inproceedings{Krebbers14, 5927 5649 keywords = {c formalization}, … … 6161 5883 } 6162 5884 6163 @article{Nigro21,6164 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},6165 contributer = {pabuhr@plg},6166 author = {Libero Nigro},6167 title = {Parallel Theatre: An actor framework in {Java} for high performance computing},6168 journal = {Simulation Modelling Practice and Theory},6169 volume = {106},6170 number = {102189},6171 year = {2021},6172 }6173 6174 5885 @incollection{Stroustrup96, 6175 5886 keywords = {concurrency, C++}, … … 6206 5917 journal = ieeese, 6207 5918 year = 1984, 6208 month = sep, 6209 volume = "SE-10", 6210 number = 5, 6211 pages = {528-543}, 5919 month = sep, volume = "SE-10", number = 5, pages = {528-543}, 6212 5920 abstract = { 6213 5921 Parameterized programming is a powerful technique for the reliable … … 6241 5949 booktitle = {USENIX {C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Conference}, 6242 5950 organization= {USENIX Association}, 6243 year = 1988, 6244 pages = {1-18}, 5951 year = 1988, pages = {1-18} 6245 5952 } 6246 5953 … … 6330 6037 } 6331 6038 6332 @incollection{Kazempour08,6333 keywords = {multicore processors; cache affinity; performance evaluation; scheduling},6334 author = {Kazempour, Vahid and Fedorova, Alexandra and Alagheband, Pouya},6335 title = {Performance Implications of Cache Affinity on Multicore Processors},6336 organization= {Euro-Par 2008 -- Parallel Processing},6337 series = {Lecture Notes in Computer Science},6338 editor = {Luque, Emilio and Margalef, Tomas and Benitez, Domingo},6339 year = {2008},6340 volume = {5168},6341 pages = {151-161},6342 publisher = {Springer Berlin Heidelberg},6343 }6344 6345 @article{Anderson89,6346 keywords = {data structures, multiprocessing systems, operating systems (computers), performance evaluation, critical resource waiting},6347 author = {Anderson, T.E. and Lazowska, E.D. and Levy, H.M.},6348 journal = {Computers, IEEE Transactions on},6349 title = {The Performance Implications of Thread Management Alternatives for Shared-Memory Multiprocessors},6350 year = {1989},6351 month = {Dec},6352 volume = {38},6353 number = {12},6354 pages = {1631-1644},6355 }6356 6357 6039 @article{Anderson90, 6358 6040 keywords = {spin locks, back off, performance}, … … 6366 6048 number = 1, 6367 6049 pages = {6-16}, 6368 }6369 6370 @article{Blumofe98,6371 author = {Blumofe, Robert D. and Papadopoulos, Dionisios},6372 title = {The Performance of Work Stealing in Multiprogrammed Environments (Extended Abstract)},6373 journal = {SIGMETRICS Perform. Eval. Rev.},6374 volume = {26},6375 number = {1},6376 month = jun,6377 year = {1998},6378 issn = {0163-5999},6379 pages = {266-267},6380 publisher = {ACM},6381 address = {New York, NY, USA},6382 6050 } 6383 6051 … … 7092 6760 } 7093 6761 7094 @inproceedings{Bacon03, 7095 keywords = {utilization, real-time scheduling, read barrier, defragmentation}, 7096 contributer = {pabuhr@plg}, 7097 author = {David F. Bacon and Perry Cheng and V. T. Rajan}, 7098 title = {A Real-Time Garbage Collector with Low Overhead and Consistent Utilization}, 7099 year = {2003}, 7100 organization= {Proceedings of the 30th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, 7101 publisher = {ACM}, 7102 address = {New York, NY, USA}, 7103 pages = {285-298}, 7104 location = {New Orleans, Louisiana, USA}, 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} 7105 6794 } 7106 6795 … … 7238 6927 journal = sigplan, 7239 6928 year = 1991, 7240 month = oct, 7241 volume = 26, 7242 number = 10, 7243 pages = {29-43}, 6929 month = oct, volume = 26, number = 10, pages = {29-43}, 7244 6930 abstract = { 7245 6931 {\tt lcc} is a new retargetable compiler for ANSI C. Versions for … … 7331 7017 publisher = {ACM}, 7332 7018 address = {New York, NY, USA}, 7333 organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},7019 booktitle = {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control}, 7334 7020 pages = {67-80}, 7335 7021 numpages = {14}, … … 7363 7049 } 7364 7050 7365 @article{Nickolls08,7366 author = {Nickolls, John and Buck, Ian and Garland, Michael and Skadron, Kevin},7367 title = {Scalable Parallel Programming with CUDA},7368 journal = {Queue},7369 volume = {6},7370 number = {2},7371 month = mar,7372 year = 2008,7373 pages = {40-53},7374 publisher = {ACM},7375 address = {New York, NY, USA},7376 }7377 7378 7051 @article{Anderson92, 7379 7052 keywords = {light-weight tasks}, … … 7389 7062 } 7390 7063 7391 @article{Blumofe99,7392 keywords = {critical-path length, multiprocessor, multithreading, randomized algorithm, thread scheduling, work stealing},7393 author = {Blumofe, Robert D. and Leiserson, Charles E.},7394 title = {Scheduling Multithreaded Computations by Work Stealing},7395 journal = {Journal of the ACM},7396 volume = {46},7397 number = {5},7398 month = sep,7399 year = {1999},7400 pages = {720-748},7401 publisher = {ACM},7402 address = {New York, NY, USA},7403 }7404 7405 @inproceedings{Acar13,7406 keywords = {dynamic load balancing, nested parallelism, work stealing},7407 author = {Acar, Umut A. and Chargueraud, Arthur and Rainey, Mike},7408 title = {Scheduling Parallel Programs by Work Stealing with Private Deques},7409 organization= {Proceedings of the 18th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming},7410 series = {PPoPP '13},7411 year = {2013},7412 location = {Shenzhen, China},7413 pages = {219-228},7414 publisher = {ACM},7415 address = {New York, NY, USA},7416 }7417 7418 @inproceedings{Chen07,7419 keywords = {chip multiprocessors, constructive cache sharing, parallel depth first, scheduling algorithms, thread granularity, work stealing, working set profiling},7420 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},7421 title = {Scheduling Threads for Constructive Cache Sharing on CMPs},7422 organization= {Proceedings of the Nineteenth Annual ACM Symposium on Parallel Algorithms and Architectures},7423 series = {SPAA '07},7424 year = {2007},7425 location = {San Diego, California, USA},7426 pages = {105-115},7427 numpages = {11},7428 publisher = {ACM},7429 address = {New York, NY, USA},7430 }7431 7432 7064 @manual{SELF, 7433 7065 keywords = {programming language, obect-oriented, polymorphism}, … … 7451 7083 publisher = {Springer}, 7452 7084 note = {Lecture Notes in Computer Science v. 173}, 7453 }7454 7455 @inproceedings{Kahn74,7456 keywords = {programming language, obect-oriented, polymorphism},7457 contributer = {pabuhr@plg},7458 title = {The Semantics of a Simple Language for Parallel Programming},7459 author = {Gilles Kahn},7460 booktitle = {IFIP Congress},7461 year = 1974,7462 7085 } 7463 7086 … … 7527 7150 publisher = {Morgan \& Claypool}, 7528 7151 year = 2013, 7529 }7530 7531 @inproceedings{Leissa14,7532 title = {{S}ierra: a {SIMD} extension for {C}++},7533 author = {Lei{\ss}a, Roland and Haffner, Immanuel and Hack, Sebastian},7534 booktitle = {Proceedings of the 2014 Workshop on Workshop on programming models for SIMD/Vector processing},7535 pages = {17-24},7536 year = {2014},7537 organization= {ACM}7538 7152 } 7539 7153 … … 8219 7833 } 8220 7834 8221 @article{Arora01,8222 author = {Arora, N. S. and Blumofe, R. D. and Plaxton, C. G.},8223 title = {Thread Scheduling for Multiprogrammed Multiprocessors},8224 journal = {Theory of Computing Systems},8225 year = {2001},8226 volume = {34},8227 number = {2},8228 pages = {115-144},8229 publisher = {Springer-Verlag},8230 }8231 8232 7835 @article{Boehm05, 8233 7836 keywords = {concurrency, C++}, … … 8457 8060 } 8458 8061 8459 @misc{AkkaBecome,8460 contributer = {pabuhr@plg},8461 key = {AkkaBecome},8462 title = {Typed Actors},8463 author = {{Lightbend}},8464 howpublished= {\href{https://doc.akka.io/docs/akka/2.5/typed-actors.html}{https://\-doc.akka.io/\-docs/\-akka/\-2.5/\-typed-actors.html}},8465 year = 2022,8466 }8467 8468 8062 @article{concatenation, 8469 8063 keywords = {record concatenation, isa}, … … 8530 8124 author = {Paul R. Wilson}, 8531 8125 title = {Uniprocessor Garbage Collection Techniques}, 8532 organization= {Proceedings of the International Workshop on Memory Management},8126 booktitle = {Proceedings of the International Workshop on Memory Management}, 8533 8127 location = {St. Malo, France}, 8534 8128 publisher = {Springer}, … … 8543 8137 author = {Carl Hewitt and Peter Bishop and Richard Steiger}, 8544 8138 title = {A Universal Modular {ACTOR} Formalism for Artificial Intelligence}, 8545 organization= {Proceedings of the 3rd International Joint Conference on Artificial Intelligence},8139 booktitle = {Proceedings of the 3rd International Joint Conference on Artificial Intelligence}, 8546 8140 address = {Standford, California, U.S.A.}, 8547 8141 pages = {235-245}, 8548 location = {Stanford, USA},8549 series = {IJCAI'73},8550 8142 month = aug, 8551 8143 year = 1973, … … 8579 8171 @article{Karsten20, 8580 8172 author = {Karsten, Martin and Barghi, Saman}, 8581 title = { User-level Threading: Have Your Cake and Eat It Too},8173 title = {{User-level Threading: Have Your Cake and Eat It Too}}, 8582 8174 year = {2020}, 8583 8175 issue_date = {March 2020}, … … 8604 8196 } 8605 8197 8606 @article{Squillante93,8607 keywords = {buffer storage, performance evaluation, queueing theory, scheduling, shared memory systems, processor-cache affinity},8608 author = {Squillante, M.S. and Lazowska, E.D.},8609 title = {Using Processor-Cache Affinity Information in Shared-Memory Multiprocessor Scheduling},8610 journal = {Parallel and Distributed Systems, IEEE Transactions on},8611 year = {1993},8612 month = {Feb},8613 volume = {4},8614 number = {2},8615 pages = {131-143},8616 }8617 8618 8198 @article{delegation, 8619 8199 keywords = {delegation, inheritance, actors}, … … 8765 8345 year = 2003, 8766 8346 pages = {19-24}, 8767 }8768 8769 @inproceedings{Saman18,8770 keywords = {actors, scheduling, NUMA, locality},8771 contributer = {pabuhr@plg},8772 author = {Saman Barghi and Martin Karsten},8773 organization= {2018 IEEE International Parallel and Distributed Processing Symposium (IPDPS)},8774 title = {Work-Stealing, Locality-Aware Actor Scheduling},8775 year = {2018},8776 address = {Vancouver, BC, Canada},8777 pages = {484-494},8778 }8779 8780 @article{Wimmer13,8781 keywords = {priorities, scheduler hints, strategies, work-stealing},8782 author = {Wimmer, Martin and Cederman, Daniel and Tr\"{a}ff, Jesper Larsson and Tsigas, Philippas},8783 title = {Work-stealing with Configurable Scheduling Strategies},8784 journal = {SIGPLAN Not.},8785 issue_date = {August 2013},8786 volume = {48},8787 number = {8},8788 month = feb,8789 year = {2013},8790 issn = {0362-1340},8791 pages = {315-316},8792 publisher = {ACM},8793 address = {New York, NY, USA},8794 8347 } 8795 8348 -
doc/theses/mike_brooks_MMath/Makefile
rb110bcc r2ed94a9 8 8 PicSRC = ${notdir ${wildcard ${Pictures}/*.png}} 9 9 DemoSRC = ${notdir ${wildcard ${Programs}/*-demo.cfa}} 10 PgmSRC = ${notdir ${wildcard ${Programs}/*}} 11 RunPgmSRC = ${notdir ${wildcard ${Programs}/*.run.*}} 10 PgmSRC = ${notdir ${wildcard ${Programs}/*.cfa}} 12 11 BibSRC = ${wildcard *.bib} 13 12 … … 15 14 BibLIB = .:../../bibliography # common citation repository 16 15 17 #MAKEFLAGS = --no-print-directory # --silent16 MAKEFLAGS = --no-print-directory # --silent 18 17 VPATH = ${Build} ${Pictures} ${Programs} # extra search path for file names used in document 19 18 … … 21 20 BASE = ${basename ${DOCUMENT}} # remove suffix 22 21 23 DemoTex = ${DemoSRC:%.cfa=${Build}/%.tex}24 RunPgmExe = ${addprefix ${Build}/,${basename ${basename ${RunPgmSRC}}}}25 RunPgmOut = ${RunPgmExe:%=%.out}26 27 22 # Commands 28 23 29 24 LaTeX = TEXINPUTS=${TeXLIB} && export TEXINPUTS && pdflatex -halt-on-error -output-directory=${Build} 30 25 BibTeX = BIBINPUTS=${BibLIB} && export BIBINPUTS && bibtex 31 CFA = cfa -O0 -g 32 CC = gcc -O0 -g 33 CXX = g++-11 --std=c++20 -O0 -g 26 CFA = cfa 34 27 35 28 # Rules and Recipes 36 29 37 .PHONY : all fragments_ran clean # not file names 38 .PRECIOUS : ${Build}/% ${Build}/%-demo # don't delete intermediates 30 .PHONY : all clean # not file names 39 31 .ONESHELL : 40 32 41 all : fragments_ran ${DOCUMENT} 42 43 fragments_ran : $(RunPgmOut) 33 all : ${DOCUMENT} 44 34 45 35 clean : … … 48 38 # File Dependencies 49 39 50 %.pdf : ${TeXSRC} ${Demo Tex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build}40 %.pdf : ${TeXSRC} ${DemoSRC:%.cfa=%.tex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build} 51 41 ${LaTeX} ${BASE} 52 42 ${BibTeX} ${Build}/${BASE} … … 62 52 63 53 %-demo.tex: %-demo | ${Build} 64 $ < >$@54 ${Build}/$< > ${Build}/$@ 65 55 66 ${Build}/%-demo: ${Programs}/%-demo.cfa | ${Build} 67 ${CFA} $< -o $ @56 %-demo: %-demo.cfa 57 ${CFA} $< -o ${Build}/$@ 68 58 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
rb110bcc r2ed94a9 65 65 bibsource = {dblp computer science bibliography, https://dblp.org} 66 66 } 67 68 % --------------------------------------------------69 % Linked-list prior work70 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.html84 % 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
rb110bcc r2ed94a9 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}63 62 \usepackage[T1]{fontenc} % Latin-1 => 256-bit characters, => | not dash, <> not Spanish question marks 64 63 … … 88 87 \usepackage{comment} % Removes large sections of the document. 89 88 \usepackage{tabularx} 90 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig} 91 \renewcommand\thesubfigure{(\alph{subfigure})} 89 \usepackage{subfigure} 92 90 93 91 \usepackage{algorithm} … … 117 115 citecolor=blue, % color of links to bibliography 118 116 filecolor=magenta, % color of file links 119 urlcolor=blue, % color of external links 120 breaklinks=true 117 urlcolor=blue % color of external links 121 118 } 122 119 \ifthenelse{\boolean{PrintVersion}}{ % for improved print quality, change some hyperref options … … 132 129 % although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and 133 130 % installation instructions there. 134 135 % Customizing tabularx136 \newcolumntype{Y}{>{\centering\arraybackslash}X}137 131 138 132 % Setting up the page margins... … … 181 175 \CFAStyle % CFA code-style 182 176 \lstset{language=CFA} % default language 183 \lstset{basicstyle=\linespread{0.9}\ sf} % CFA typewriter font177 \lstset{basicstyle=\linespread{0.9}\tt} % CFA typewriter font 184 178 \lstset{inputpath={programs}} 185 179 \newcommand{\PAB}[1]{{\color{red}PAB: #1}} 186 187 \newcommand{\uCpp}{$\mu$\CC}188 180 189 181 %====================================================================== … … 209 201 %---------------------------------------------------------------------- 210 202 \begin{sloppypar} 203 211 204 \input{intro} 212 205 \input{background} 213 \input{list}214 206 \input{array} 215 207 \input{string} -
driver/cfa.cc
rb110bcc r2ed94a9 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 21:16:00 202313 // Update Count : 4 7612 // Last Modified On : Wed Jul 14 21:55:12 2021 13 // Update Count : 467 14 14 // 15 15 … … 44 44 static int flags = 0; 45 45 46 // This allocation 'leaks' memory from the program to the execution47 // environment, as putenv does not manage the storage of the string used48 // as an environment variable. This leak is necessary to ensure the49 // underlying C string is allocated long enough.50 46 if ( putenv( (char *)( *new string( string( __CFA_FLAGPREFIX__ + to_string( flags++ ) + "__=" ) + arg ) ).c_str() ) ) { 51 47 cerr << argv[0] << " error, cannot set environment variable." << endl; … … 202 198 } // if 203 199 } else if ( arg == "-CFA" ) { 204 CFA_flag = true; // strip -CFA flag200 CFA_flag = true; // strip the -CFA flag 205 201 link = false; 206 202 args[nargs++] = "-fsyntax-only"; // stop after stage 2 207 203 } else if ( arg == "-debug" ) { 208 debug = true; // strip debug flag204 debug = true; // strip the debug flag 209 205 } else if ( arg == "-nodebug" ) { 210 debug = false; // strip nodebug flag206 debug = false; // strip the nodebug flag 211 207 } else if ( arg == "-quiet" ) { 212 quiet = true; // strip quiet flag208 quiet = true; // strip the quiet flag 213 209 } else if ( arg == "-noquiet" ) { 214 quiet = false; // strip noquiet flag 215 } else if ( arg == "-invariant" ) { 216 Putenv( argv, "-" + arg ); 217 } else if ( arg == "--invariant" ) { 218 Putenv( argv, arg ); 210 quiet = false; // strip the noquiet flag 219 211 } else if ( arg == "-no-include-stdhdr" ) { 220 noincstd_flag = true; // strip no-include-stdhdr flag212 noincstd_flag = true; // strip the no-include-stdhdr flag 221 213 } else if ( arg == "-nolib" ) { 222 nolib = true; // strip nolib flag214 nolib = true; // strip the nolib flag 223 215 } else if ( arg == "-help" ) { 224 help = true; // strip help flag216 help = true; // strip the help flag 225 217 } else if ( arg == "-nohelp" ) { 226 help = false; // strip nohelp flag218 help = false; // strip the nohelp flag 227 219 } else if ( arg == "-cfalib") { 228 220 compiling_libs = true; … … 282 274 } // if 283 275 } else if ( prefix( arg, "-B" ) ) { 284 bprefix = arg.substr(2); // strip -B flag276 bprefix = arg.substr(2); // strip the -B flag 285 277 } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) { 286 278 args[nargs++] = argv[i]; // pass flag along … … 452 444 453 445 args[nargs++] = "-fexceptions"; // add exception flags (unconditionally) 454 args[nargs++] = "-D_GNU_SOURCE"; // force gnu libraries455 446 456 447 // add flags based on the type of compile -
libcfa/src/Makefile.am
rb110bcc r2ed94a9 48 48 math.hfa \ 49 49 time_t.hfa \ 50 virtual_dtor.hfa \51 50 bits/algorithm.hfa \ 52 51 bits/align.hfa \ -
libcfa/src/algorithms/range_iterator.hfa
rb110bcc r2ed94a9 9 9 // Author : Thierry Delisle 10 10 // Created On : Tue Nov 30 13:06:22 2021 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Mar 13 23:10:35 202313 // Update Count : 111 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 14 // 15 16 #pragma once17 15 18 16 generator RangeIter { -
libcfa/src/bitmanip.hfa
rb110bcc r2ed94a9 11 11 // Created On : Sat Mar 14 18:12:27 2020 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Mon Jan 9 09:02:43 202314 // Update Count : 14 413 // Last Modified On : Sat Oct 8 08:28:15 2022 14 // Update Count : 142 15 15 // 16 16 17 17 #pragma once 18 19 #include "bits/debug.hfa" // verify20 18 21 19 // Reference: Bit Twiddling Hacks: http://graphics.stanford.edu/%7Eseander/bithacks.html#CountBitsSetNaive -
libcfa/src/bits/random.hfa
rb110bcc r2ed94a9 10 10 // Created On : Fri Jan 14 07:18:11 2022 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 20 21:45:24 202313 // Update Count : 1 8612 // Last Modified On : Thu Dec 22 20:54:22 2022 13 // Update Count : 178 14 14 // 15 15 … … 28 28 #define XOSHIRO256PP 29 29 //#define KISS_64 30 // #define SPLITMIX_6431 30 32 31 // 32-bit generators 33 32 //#define XORSHIFT_6_21_7 34 33 #define XOSHIRO128PP 35 // #define SPLITMIX_3236 34 #else // 32-bit architecture 37 35 // 64-bit generators 38 36 //#define XORSHIFT_13_7_17 39 37 #define XOSHIRO256PP 40 // #define SPLITMIX_6441 38 42 39 // 32-bit generators 43 40 //#define XORSHIFT_6_21_7 44 41 #define XOSHIRO128PP 45 // #define SPLITMIX_3246 42 #endif // __x86_64__ 47 43 48 44 // Define C/CFA PRNG name and random-state. 45 46 // SKULLDUGGERY: typedefs name struct and typedef with the same name to deal with CFA typedef numbering problem. 49 47 50 48 #ifdef XOSHIRO256PP 51 49 #define PRNG_NAME_64 xoshiro256pp 52 50 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 53 typedef struct { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;51 typedef struct PRNG_STATE_64_T { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T; 54 52 #endif // XOSHIRO256PP 55 53 … … 57 55 #define PRNG_NAME_32 xoshiro128pp 58 56 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 59 typedef struct { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;57 typedef struct PRNG_STATE_32_T { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T; 60 58 #endif // XOSHIRO128PP 61 59 … … 85 83 #endif // XORSHIFT_12_25_27 86 84 87 #ifdef SPLITMIX_6488 #define PRNG_NAME_64 splitmix6489 #define PRNG_STATE_64_T uint64_t90 #endif // SPLITMIX3291 92 #ifdef SPLITMIX_3293 #define PRNG_NAME_32 splitmix3294 #define PRNG_STATE_32_T uint32_t95 #endif // SPLITMIX3296 97 85 #ifdef KISS_64 98 86 #define PRNG_NAME_64 kiss_64 99 87 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 100 typedef struct { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;88 typedef struct PRNG_STATE_64_T { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T; 101 89 #endif // KISS_^64 102 90 … … 104 92 #define PRNG_NAME_32 xorwow 105 93 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 106 typedef struct { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;94 typedef struct PRNG_STATE_32_T { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T; 107 95 #endif // XOSHIRO128PP 108 96 … … 131 119 #ifdef __cforall // don't include in C code (invoke.h) 132 120 133 // https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64134 //135 // Splitmix64 is not recommended for demanding random number requirements, but is often used to calculate initial states136 // 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 } // splitmix64145 146 static inline void splitmix64_set_seed( uint64_t & state , uint64_t seed ) {147 state = seed;148 splitmix64( state ); // prime149 } // splitmix64_set_seed150 151 // https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32152 //153 // Splitmix32 is not recommended for demanding random number requirements, but is often used to calculate initial states154 // 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 } // splitmix32163 164 static inline void splitmix32_set_seed( uint32_t & state, uint64_t seed ) {165 state = seed;166 splitmix32( state ); // prime167 } // splitmix32_set_seed168 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 } // lehmer64176 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 ); // prime180 } // lehmer64_set_seed181 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 } // wyhash64193 194 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) {195 state = splitmix64( seed ); // prime196 } // wyhash64_set_seed197 #endif // __SIZEOF_INT128__198 199 121 // https://prng.di.unimi.it/xoshiro256starstar.c 200 122 // … … 208 130 209 131 #ifndef XOSHIRO256PP 210 typedef struct { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;132 typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t; 211 133 #endif // ! XOSHIRO256PP 212 134 … … 229 151 230 152 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 }; 153 state = (xoshiro256pp_t){ seed, seed, seed, seed }; 154 xoshiro256pp( state ); 237 155 } // xoshiro256pp_set_seed 238 156 … … 247 165 248 166 #ifndef XOSHIRO128PP 249 typedef struct { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;167 typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t; 250 168 #endif // ! XOSHIRO128PP 251 169 … … 268 186 269 187 static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) { 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 }; 188 state = (xoshiro128pp_t){ seed, seed, seed, seed }; 189 xoshiro128pp( state ); // prime 276 190 } // xoshiro128pp_set_seed 191 192 #ifdef __SIZEOF_INT128__ 193 //-------------------------------------------------- 194 static inline uint64_t lehmer64( __uint128_t & state ) { 195 __uint128_t ret = state; 196 state *= 0x_da94_2042_e4dd_58b5; 197 return ret >> 64; 198 } // lehmer64 199 200 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) { 201 // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed. 202 state = seed; 203 lehmer64( state ); // prime 204 } // lehmer64_set_seed 205 206 //-------------------------------------------------- 207 static inline uint64_t wyhash64( uint64_t & state ) { 208 uint64_t ret = state; 209 state += 0x_60be_e2be_e120_fc15; 210 __uint128_t tmp; 211 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d; 212 uint64_t m1 = (tmp >> 64) ^ tmp; 213 tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9; 214 uint64_t m2 = (tmp >> 64) ^ tmp; 215 return m2; 216 } // wyhash64 217 218 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) { 219 state = seed; 220 wyhash64( state ); // prime 221 } // wyhash64_set_seed 222 #endif // __SIZEOF_INT128__ 277 223 278 224 //-------------------------------------------------- … … 286 232 287 233 static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) { 288 state = splitmix64( seed ); // prime 234 state = seed; 235 xorshift_13_7_17( state ); // prime 289 236 } // xorshift_13_7_17_set_seed 290 237 … … 303 250 304 251 static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) { 305 state = splitmix32( seed ); // prime 252 state = seed; 253 xorshift_6_21_7( state ); // prime 306 254 } // xorshift_6_21_7_set_seed 307 255 … … 317 265 318 266 static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) { 319 state = splitmix64( seed ); // prime 267 state = seed; 268 xorshift_12_25_27( state ); // prime 320 269 } // xorshift_12_25_27_set_seed 321 270 … … 323 272 // The state must be seeded with a nonzero value. 324 273 #ifndef KISS_64 325 typedef struct { uint64_t z, w, jsr, jcong; } kiss_64_t;274 typedef struct kiss_64_t { uint64_t z, w, jsr, jcong; } kiss_64_t; 326 275 #endif // ! KISS_64 327 276 … … 338 287 339 288 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 289 z = 1; w = 1; jsr = 4; jcong = seed; 290 kiss_64( rs ); // prime 341 291 } // kiss_64_set_seed 342 292 … … 344 294 // The state array must be initialized to non-zero in the first four words. 345 295 #ifndef XORWOW 346 typedef struct { uint32_t a, b, c, d, counter; } xorwow_t;296 typedef struct xorwow_t { uint32_t a, b, c, d, counter; } xorwow_t; 347 297 #endif // ! XORWOW 348 298 … … 366 316 367 317 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 }; 318 rs = (xorwow_t){ seed, seed, seed, seed, 0 }; 319 xorwow( rs ); // prime 374 320 } // xorwow_set_seed 375 321 … … 377 323 // Used in __tls_rand_fwd 378 324 #define M (1_l64u << 48_l64u) 379 #define A (25 _214_903_917_l64u)380 #define AI (18 _446_708_753_438_544_741_l64u)325 #define A (25214903917_l64u) 326 #define AI (18446708753438544741_l64u) 381 327 #define C (11_l64u) 382 328 #define D (16_l64u) -
libcfa/src/concurrency/actor.hfa
rb110bcc r2ed94a9 3 3 #include <locks.hfa> 4 4 #include <limits.hfa> 5 #include <list.hfa> 5 6 #include <kernel.hfa> 6 #include <iofwd.hfa>7 #include <virtual_dtor.hfa>8 7 9 8 #ifdef __CFA_DEBUG__ … … 21 20 // Define the default number of executor request-queues (mailboxes) written to by actors and serviced by the 22 21 // actor-executor threads. Must be greater than 0. 23 #define __DEFAULT_EXECUTOR_RQUEUES__ 422 #define __DEFAULT_EXECUTOR_RQUEUES__ 2 24 23 25 24 // Define if executor is created in a separate cluster 26 25 #define __DEFAULT_EXECUTOR_SEPCLUS__ false 27 26 28 #define __DEFAULT_EXECUTOR_BUFSIZE__ 10 29 30 #define __STEAL 0 // workstealing toggle. Disjoint from toggles above 31 32 // workstealing heuristic selection (only set one to be 1) 33 // #define RAND 0 34 #define SEARCH 1 35 36 // show stats 37 // #define ACTOR_STATS 27 // when you flip this make sure to recompile compiler and flip the appropriate flag there too in Actors.cpp 28 #define __ALLOC 0 38 29 39 30 // forward decls 40 31 struct actor; 41 32 struct message; 42 struct executor;43 33 44 34 enum Allocation { Nodelete, Delete, Destroy, Finished }; // allocation status … … 50 40 __receive_fn fn; 51 41 bool stop; 52 }; 42 inline dlink(request); 43 }; 44 P9_EMBEDDED( request, dlink(request) ) 53 45 54 46 static inline void ?{}( request & this ) { this.stop = true; } // default ctor makes a sentinel … … 66 58 } 67 59 68 // Vector-like data structure that supports O(1) queue operations with no bound on size 69 // assumes gulping behaviour (once a remove occurs, removes happen until empty beforw next insert) 60 // hybrid data structure. Copies until buffer is full and then allocates for intrusive list 70 61 struct copy_queue { 62 dlist( request ) list; 63 #if ! __ALLOC 71 64 request * buffer; 72 size_t count, buffer_size, index, utilized, last_size; 65 size_t count, buffer_size, index; 66 #endif 73 67 }; 74 68 static inline void ?{}( copy_queue & this ) {} 75 69 static inline void ?{}( copy_queue & this, size_t buf_size ) with(this) { 70 list{}; 71 #if ! __ALLOC 76 72 buffer_size = buf_size; 77 73 buffer = aalloc( buffer_size ); 78 74 count = 0; 79 utilized = 0;80 75 index = 0; 81 last_size = 0; 82 } 83 static inline void ^?{}( copy_queue & this ) with(this) { adelete(buffer); } 76 #endif 77 } 78 static inline void ^?{}( copy_queue & this ) with(this) { 79 #if ! __ALLOC 80 adelete(buffer); 81 #endif 82 } 84 83 85 84 static inline void insert( copy_queue & this, request & elem ) with(this) { 86 if ( count >= buffer_size ) { // increase arr size87 last_size = buffer_size;88 buffer _size = 2 * buffer_size;89 buffer = realloc( buffer, sizeof( request ) * buffer_size );90 /* paranoid */ verify( buffer );85 #if ! __ALLOC 86 if ( count < buffer_size ) { // fast path ( no alloc ) 87 buffer[count]{ elem }; 88 count++; 89 return; 91 90 } 92 memcpy( &buffer[count], &elem, sizeof(request) ); 93 count++; 91 request * new_elem = alloc(); 92 (*new_elem){ elem }; 93 insert_last( list, *new_elem ); 94 #else 95 insert_last( list, elem ); 96 #endif 94 97 } 95 98 96 99 // once you start removing you need to remove all elements 97 // it is not supported to call insert() before the array is fully empty 98 static inline request & remove( copy_queue & this ) with(this) { 100 // it is not supported to call insert() before the list is fully empty 101 // should_delete is an output param 102 static inline request & remove( copy_queue & this, bool & should_delete ) with(this) { 103 #if ! __ALLOC 99 104 if ( count > 0 ) { 100 105 count--; 106 should_delete = false; 101 107 size_t old_idx = index; 102 108 index = count == 0 ? 0 : index + 1; 103 109 return buffer[old_idx]; 104 110 } 105 request * ret = 0p;106 return *0p;107 } 108 109 // try to reclaim some memory if less than half of buffer is utilized 110 static inline void reclaim( copy_queue & this ) with(this) {111 if ( utilized >= last_size || buffer_size <= 4 ) { utilized = 0; return; }112 utilized = 0;113 buffer_size--;114 buffer = realloc( buffer, sizeof( request ) * buffer_size ); // try to reclaim some memory115 } 116 117 static inline bool isEmpty( copy_queue & this ) with(this) { return count == 0; } 118 111 #endif 112 should_delete = true; 113 return try_pop_front( list ); 114 } 115 116 static inline bool isEmpty( copy_queue & this ) with(this) { 117 #if ! __ALLOC 118 return count == 0 && list`isEmpty; 119 #else 120 return list`isEmpty; 121 #endif 122 } 123 124 static size_t __buffer_size = 10; // C_TODO: rework this to be passed from executor through ctors (no need for global) 119 125 struct work_queue { 120 126 __spinlock_t mutex_lock; 121 copy_queue * owned_queue; // copy queue allocated and cleaned up by this work_queue 122 copy_queue * c_queue; // current queue 123 volatile bool being_processed; // flag to prevent concurrent processing 124 #ifdef ACTOR_STATS 125 unsigned int id; 126 size_t missed; // transfers skipped due to being_processed flag being up 127 #endif 127 copy_queue owned_queue; 128 copy_queue * c_queue; // C_TODO: try putting this on the stack with ptr juggling 129 128 130 }; // work_queue 129 static inline void ?{}( work_queue & this, size_t buf_size, unsigned int i ) with(this) { 130 owned_queue = alloc(); // allocated separately to avoid false sharing 131 (*owned_queue){ buf_size }; 132 c_queue = owned_queue; 133 being_processed = false; 134 #ifdef ACTOR_STATS 135 id = i; 136 missed = 0; 137 #endif 138 } 139 140 // clean up copy_queue owned by this work_queue 141 static inline void ^?{}( work_queue & this ) with(this) { delete( owned_queue ); } 131 static inline void ?{}( work_queue & this ) with(this) { 132 // c_queue = alloc(); 133 // (*c_queue){ __buffer_size }; 134 owned_queue{ __buffer_size }; 135 c_queue = &owned_queue; 136 } 137 // static inline void ^?{}( work_queue & this ) with(this) { delete( c_queue ); } 142 138 143 139 static inline void insert( work_queue & this, request & elem ) with(this) { … … 149 145 static inline void transfer( work_queue & this, copy_queue ** transfer_to ) with(this) { 150 146 lock( mutex_lock __cfaabi_dbg_ctx2 ); 151 #ifdef __STEAL152 153 // check if queue is being processed elsewhere154 if ( unlikely( being_processed ) ) {155 #ifdef ACTOR_STATS156 missed++;157 #endif158 unlock( mutex_lock );159 return;160 }161 162 being_processed = c_queue->count != 0;163 #endif // __STEAL164 165 c_queue->utilized = c_queue->count;166 167 147 // swap copy queue ptrs 168 148 copy_queue * temp = *transfer_to; … … 172 152 } // transfer 173 153 174 // needed since some info needs to persist past worker lifetimes175 struct worker_info {176 volatile unsigned long long stamp;177 #ifdef ACTOR_STATS178 size_t stolen_from, try_steal, stolen, failed_swaps, msgs_stolen;179 unsigned long long processed;180 size_t gulps;181 #endif182 };183 static inline void ?{}( worker_info & this ) {184 #ifdef ACTOR_STATS185 this.stolen_from = 0;186 this.try_steal = 0; // attempts to steal187 this.stolen = 0; // successful steals188 this.processed = 0; // requests processed189 this.gulps = 0; // number of gulps190 this.failed_swaps = 0; // steal swap failures191 this.msgs_stolen = 0; // number of messages stolen192 #endif193 this.stamp = rdtscl();194 }195 196 // #ifdef ACTOR_STATS197 // unsigned int * stolen_arr;198 // unsigned int * replaced_queue;199 // #endif200 154 thread worker { 201 work_queue ** request_queues; 155 copy_queue owned_queue; 156 work_queue * request_queues; 202 157 copy_queue * current_queue; 203 executor * executor_;158 request & req; 204 159 unsigned int start, range; 205 int id; 206 }; 207 208 #ifdef ACTOR_STATS 209 // aggregate counters for statistics 210 size_t __total_tries = 0, __total_stolen = 0, __total_workers, __all_gulps = 0, 211 __total_failed_swaps = 0, __all_processed = 0, __num_actors_stats = 0, __all_msgs_stolen = 0; 212 #endif 213 static inline void ?{}( worker & this, cluster & clu, work_queue ** request_queues, copy_queue * current_queue, executor * executor_, 214 unsigned int start, unsigned int range, int id ) { 160 }; 161 162 static inline void ?{}( worker & this, cluster & clu, work_queue * request_queues, unsigned int start, unsigned int range ) { 215 163 ((thread &)this){ clu }; 216 this.request_queues = request_queues; // array of all queues 217 this.current_queue = current_queue; // currently gulped queue (start with empty queue to use in swap later) 218 this.executor_ = executor_; // pointer to current executor 219 this.start = start; // start of worker's subrange of request_queues 220 this.range = range; // size of worker's subrange of request_queues 221 this.id = id; // worker's id and index in array of workers 222 } 223 224 static bool no_steal = false; 164 this.request_queues = request_queues; 165 // this.current_queue = alloc(); 166 // (*this.current_queue){ __buffer_size }; 167 this.owned_queue{ __buffer_size }; 168 this.current_queue = &this.owned_queue; 169 this.start = start; 170 this.range = range; 171 } 172 // static inline void ^?{}( worker & mutex this ) with(this) { delete( current_queue ); } 173 225 174 struct executor { 226 175 cluster * cluster; // if workers execute on separate cluster 227 176 processor ** processors; // array of virtual processors adding parallelism for workers 228 work_queue * request_queues; // master array of work request queues 229 copy_queue * local_queues; // array of all worker local queues to avoid deletion race 230 work_queue ** worker_req_queues; // secondary array of work queues to allow for swapping 231 worker ** workers; // array of workers executing work requests 232 worker_info * w_infos; // array of info about each worker 177 work_queue * request_queues; // master list of work request queues 178 worker ** workers; // array of workers executing work requests 233 179 unsigned int nprocessors, nworkers, nrqueues; // number of processors/threads/request queues 234 180 bool seperate_clus; // use same or separate cluster for executor 235 181 }; // executor 236 182 237 // #ifdef ACTOR_STATS238 // __spinlock_t out_lock;239 // #endif240 static inline void ^?{}( worker & mutex this ) with(this) {241 #ifdef ACTOR_STATS242 __atomic_add_fetch(&__all_gulps, executor_->w_infos[id].gulps,__ATOMIC_SEQ_CST);243 __atomic_add_fetch(&__all_processed, executor_->w_infos[id].processed,__ATOMIC_SEQ_CST);244 __atomic_add_fetch(&__all_msgs_stolen, executor_->w_infos[id].msgs_stolen,__ATOMIC_SEQ_CST);245 __atomic_add_fetch(&__total_tries, executor_->w_infos[id].try_steal, __ATOMIC_SEQ_CST);246 __atomic_add_fetch(&__total_stolen, executor_->w_infos[id].stolen, __ATOMIC_SEQ_CST);247 __atomic_add_fetch(&__total_failed_swaps, executor_->w_infos[id].failed_swaps, __ATOMIC_SEQ_CST);248 249 // per worker steal stats (uncomment alongside the lock above this routine to print)250 // lock( out_lock __cfaabi_dbg_ctx2 );251 // printf("Worker id: %d, processed: %llu messages, attempted %lu, stole: %lu, stolen from: %lu\n", id, processed, try_steal, stolen, __atomic_add_fetch(&executor_->w_infos[id].stolen_from, 0, __ATOMIC_SEQ_CST) );252 // int count = 0;253 // int count2 = 0;254 // for ( i; range ) {255 // if ( replaced_queue[start + i] > 0 ){256 // count++;257 // // printf("%d: %u, ",i, replaced_queue[i]);258 // }259 // if (__atomic_add_fetch(&stolen_arr[start + i],0,__ATOMIC_SEQ_CST) > 0)260 // count2++;261 // }262 // printf("swapped with: %d of %u indices\n", count, executor_->nrqueues / executor_->nworkers );263 // printf("%d of %u indices were stolen\n", count2, executor_->nrqueues / executor_->nworkers );264 // unlock( out_lock );265 #endif266 }267 268 183 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus, size_t buf_size ) with(this) { 269 184 if ( nrqueues < nworkers ) abort( "nrqueues needs to be >= nworkers\n" ); 185 __buffer_size = buf_size; 270 186 this.nprocessors = nprocessors; 271 187 this.nworkers = nworkers; … … 273 189 this.seperate_clus = seperate_clus; 274 190 275 if ( nworkers == nrqueues )276 no_steal = true;277 278 #ifdef ACTOR_STATS279 // stolen_arr = aalloc( nrqueues );280 // replaced_queue = aalloc( nrqueues );281 __total_workers = nworkers;282 #endif283 284 191 if ( seperate_clus ) { 285 192 cluster = alloc(); … … 288 195 289 196 request_queues = aalloc( nrqueues ); 290 worker_req_queues = aalloc( nrqueues ); 291 for ( i; nrqueues ) { 292 request_queues[i]{ buf_size, i }; 293 worker_req_queues[i] = &request_queues[i]; 294 } 197 for ( i; nrqueues ) 198 request_queues[i]{}; 295 199 296 200 processors = aalloc( nprocessors ); … … 298 202 (*(processors[i] = alloc())){ *cluster }; 299 203 300 local_queues = aalloc( nworkers ); 301 workers = aalloc( nworkers ); 302 w_infos = aalloc( nworkers ); 204 workers = alloc( nworkers ); 303 205 unsigned int reqPerWorker = nrqueues / nworkers, extras = nrqueues % nworkers; 304 305 for ( i; nworkers ) {306 w_infos[i]{};307 local_queues[i]{ buf_size };308 }309 310 206 for ( unsigned int i = 0, start = 0, range; i < nworkers; i += 1, start += range ) { 311 207 range = reqPerWorker + ( i < extras ? 1 : 0 ); 312 (*(workers[i] = alloc())){ *cluster, worker_req_queues, &local_queues[i], &this, start, range, i};208 (*(workers[i] = alloc())){ *cluster, request_queues, start, range }; 313 209 } // for 314 210 } 315 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus ) { this{ nprocessors, nworkers, nrqueues, seperate_clus, __ DEFAULT_EXECUTOR_BUFSIZE__}; }211 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus ) { this{ nprocessors, nworkers, nrqueues, seperate_clus, __buffer_size }; } 316 212 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues ) { this{ nprocessors, nworkers, nrqueues, __DEFAULT_EXECUTOR_SEPCLUS__ }; } 317 213 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers ) { this{ nprocessors, nworkers, __DEFAULT_EXECUTOR_RQUEUES__ }; } … … 320 216 321 217 static inline void ^?{}( executor & this ) with(this) { 322 #ifdef __STEAL323 request sentinels[nrqueues];324 for ( unsigned int i = 0; i < nrqueues; i++ ) {325 insert( request_queues[i], sentinels[i] ); // force eventually termination326 } // for327 #else328 218 request sentinels[nworkers]; 329 unsigned int reqPerWorker = nrqueues / nworkers, extras = nrqueues % nworkers; 330 for ( unsigned int i = 0, step = 0, range; i < nworkers; i += 1, step += range ) { 331 range = reqPerWorker + ( i < extras ? 1 : 0 ); 219 unsigned int reqPerWorker = nrqueues / nworkers; 220 for ( unsigned int i = 0, step = 0; i < nworkers; i += 1, step += reqPerWorker ) { 332 221 insert( request_queues[step], sentinels[i] ); // force eventually termination 333 222 } // for 334 #endif335 223 336 224 for ( i; nworkers ) … … 341 229 } // for 342 230 343 #ifdef ACTOR_STATS344 size_t misses = 0;345 for ( i; nrqueues ) {346 misses += worker_req_queues[i]->missed;347 }348 // adelete( stolen_arr );349 // adelete( replaced_queue );350 #endif351 352 231 adelete( workers ); 353 adelete( w_infos );354 adelete( local_queues );355 232 adelete( request_queues ); 356 adelete( worker_req_queues );357 233 adelete( processors ); 358 234 if ( seperate_clus ) delete( cluster ); 359 360 #ifdef ACTOR_STATS // print formatted stats361 printf(" Actor System Stats:\n");362 printf("\tActors Created:\t\t\t\t%lu\n\tMessages Sent:\t\t\t\t%lu\n", __num_actors_stats, __all_processed);363 size_t avg_gulps = __all_gulps == 0 ? 0 : __all_processed / __all_gulps;364 printf("\tGulps:\t\t\t\t\t%lu\n\tAverage Gulp Size:\t\t\t%lu\n\tMissed gulps:\t\t\t\t%lu\n", __all_gulps, avg_gulps, misses);365 printf("\tSteal attempts:\t\t\t\t%lu\n\tSteals:\t\t\t\t\t%lu\n\tSteal failures (no candidates):\t\t%lu\n\tSteal failures (failed swaps):\t\t%lu\n",366 __total_tries, __total_stolen, __total_tries - __total_stolen - __total_failed_swaps, __total_failed_swaps);367 size_t avg_steal = __total_stolen == 0 ? 0 : __all_msgs_stolen / __total_stolen;368 printf("\tMessages stolen:\t\t\t%lu\n\tAverage steal size:\t\t\t%lu\n", __all_msgs_stolen, avg_steal);369 #endif370 371 235 } 372 236 373 237 // this is a static field of executor but have to forward decl for get_next_ticket 374 static size_t __next_ticket = 0; 375 376 static inline size_t __get_next_ticket( executor & this ) with(this) { 377 #ifdef __CFA_DEBUG__ 378 size_t temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues; 379 380 // reserve MAX for dead actors 381 if ( unlikely( temp == MAX ) ) temp = __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues; 382 return temp; 383 #else 384 return __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_RELAXED) % nrqueues; 385 #endif 238 static unsigned int __next_ticket = 0; 239 240 static inline unsigned int get_next_ticket( executor & this ) with(this) { 241 return __atomic_fetch_add( &__next_ticket, 1, __ATOMIC_SEQ_CST) % nrqueues; 386 242 } // tickets 387 243 388 // TODO: update globals in this file to be static fields once the static fieldsproject is done244 // C_TODO: update globals in this file to be static fields once the project is done 389 245 static executor * __actor_executor_ = 0p; 390 static bool __actor_executor_passed = false; // was an executor passed to start_actor_system391 static size_t __num_actors_ = 0;// number of actor objects in system246 static bool __actor_executor_passed = false; // was an executor passed to start_actor_system 247 static unsigned long int __num_actors_; // number of actor objects in system 392 248 static struct thread$ * __actor_executor_thd = 0p; // used to wake executor after actors finish 393 249 struct actor { 394 size_t ticket; // executor-queue handle 395 Allocation allocation_; // allocation action 396 inline virtual_dtor; 397 }; 398 399 static inline void ?{}( actor & this ) with(this) { 250 unsigned long int ticket; // executor-queue handle to provide FIFO message execution 251 Allocation allocation_; // allocation action 252 }; 253 254 static inline void ?{}( actor & this ) { 400 255 // Once an actor is allocated it must be sent a message or the actor system cannot stop. Hence, its receive 401 256 // member must be called to end it 402 verifyf( __actor_executor_, "Creating actor before calling start_actor_system() can cause undefined behaviour.\n" ); 403 allocation_ = Nodelete; 404 ticket = __get_next_ticket( *__actor_executor_ ); 405 __atomic_fetch_add( &__num_actors_, 1, __ATOMIC_RELAXED ); 406 #ifdef ACTOR_STATS 407 __atomic_fetch_add( &__num_actors_stats, 1, __ATOMIC_SEQ_CST ); 408 #endif 409 } 257 verifyf( __actor_executor_, "Creating actor before calling start_actor_system()." ); 258 this.allocation_ = Nodelete; 259 this.ticket = get_next_ticket( *__actor_executor_ ); 260 __atomic_fetch_add( &__num_actors_, 1, __ATOMIC_SEQ_CST ); 261 } 262 static inline void ^?{}( actor & this ) {} 410 263 411 264 static inline void check_actor( actor & this ) { … … 423 276 } 424 277 425 if ( unlikely( __atomic_add_fetch( &__num_actors_, -1, __ATOMIC_ RELAXED) == 0 ) ) { // all actors have terminated278 if ( unlikely( __atomic_add_fetch( &__num_actors_, -1, __ATOMIC_SEQ_CST ) == 0 ) ) { // all actors have terminated 426 279 unpark( __actor_executor_thd ); 427 280 } … … 431 284 struct message { 432 285 Allocation allocation_; // allocation action 433 inline virtual_dtor; 434 }; 435 436 static inline void ?{}( message & this ) { 437 this.allocation_ = Nodelete; 438 } 439 static inline void ?{}( message & this, Allocation allocation ) { 440 memcpy( &this.allocation_, &allocation, sizeof(allocation) ); // optimization to elide ctor 441 verifyf( this.allocation_ != Finished, "The Finished Allocation status is not supported for message types.\n"); 442 } 443 static inline void ^?{}( message & this ) with(this) { 444 CFA_DEBUG( if ( allocation_ == Nodelete ) printf("A message at location %p was allocated but never sent.\n", &this); ) 445 } 286 }; 287 288 static inline void ?{}( message & this ) { this.allocation_ = Nodelete; } 289 static inline void ?{}( message & this, Allocation allocation ) { this.allocation_ = allocation; } 290 static inline void ^?{}( message & this ) {} 446 291 447 292 static inline void check_message( message & this ) { 448 293 switch ( this.allocation_ ) { // analyze message status 449 case Nodelete: CFA_DEBUG(this.allocation_ = Finished);break;294 case Nodelete: break; 450 295 case Delete: delete( &this ); break; 451 296 case Destroy: ^?{}(this); break; … … 453 298 } // switch 454 299 } 455 static inline void set_allocation( message & this, Allocation state ) {456 this.allocation_ = state;457 }458 300 459 301 static inline void deliver_request( request & this ) { 460 this.receiver->allocation_ = this.fn( *this.receiver, *this.msg ); 302 Allocation actor_allocation = this.fn( *this.receiver, *this.msg ); 303 this.receiver->allocation_ = actor_allocation; 304 check_actor( *this.receiver ); 461 305 check_message( *this.msg ); 462 check_actor( *this.receiver );463 }464 465 // tries to atomically swap two queues and returns 0p if the swap failed466 // returns ptr to newly owned queue if swap succeeds467 static inline work_queue * try_swap_queues( worker & this, unsigned int victim_idx, unsigned int my_idx ) with(this) {468 work_queue * my_queue = request_queues[my_idx];469 work_queue * other_queue = request_queues[victim_idx];470 471 // if either queue is 0p then they are in the process of being stolen472 if ( other_queue == 0p ) return 0p;473 474 // try to set our queue ptr to be 0p. If it fails someone moved our queue so return false475 if ( !__atomic_compare_exchange_n( &request_queues[my_idx], &my_queue, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) )476 return 0p;477 478 // try to set other queue ptr to be our queue ptr. If it fails someone moved the other queue so fix up then return false479 if ( !__atomic_compare_exchange_n( &request_queues[victim_idx], &other_queue, my_queue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) {480 /* paranoid */ verify( request_queues[my_idx] == 0p );481 request_queues[my_idx] = my_queue; // reset my queue ptr back to appropriate val482 return 0p;483 }484 485 // we have successfully swapped and since our queue is 0p no one will touch it so write back new queue ptr non atomically486 request_queues[my_idx] = other_queue; // last write does not need to be atomic487 return other_queue;488 }489 490 // once a worker to steal from has been chosen, choose queue to steal from491 static inline void choose_queue( worker & this, unsigned int victim_id, unsigned int swap_idx ) with(this) {492 // have to calculate victim start and range since victim may be deleted before us in shutdown493 const unsigned int queues_per_worker = executor_->nrqueues / executor_->nworkers;494 const unsigned int extras = executor_->nrqueues % executor_->nworkers;495 unsigned int vic_start, vic_range;496 if ( extras > victim_id ) {497 vic_range = queues_per_worker + 1;498 vic_start = vic_range * victim_id;499 } else {500 vic_start = extras + victim_id * queues_per_worker;501 vic_range = queues_per_worker;502 }503 unsigned int start_idx = prng( vic_range );504 505 unsigned int tries = 0;506 work_queue * curr_steal_queue;507 508 for ( unsigned int i = start_idx; tries < vic_range; i = (i + 1) % vic_range ) {509 tries++;510 curr_steal_queue = request_queues[ i + vic_start ];511 // avoid empty queues and queues that are being operated on512 if ( curr_steal_queue == 0p || curr_steal_queue->being_processed || isEmpty( *curr_steal_queue->c_queue ) )513 continue;514 515 #ifdef ACTOR_STATS516 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx );517 if ( curr_steal_queue ) {518 executor_->w_infos[id].msgs_stolen += curr_steal_queue->c_queue->count;519 executor_->w_infos[id].stolen++;520 // __atomic_add_fetch(&executor_->w_infos[victim_id].stolen_from, 1, __ATOMIC_RELAXED);521 // replaced_queue[swap_idx]++;522 // __atomic_add_fetch(&stolen_arr[ i + vic_start ], 1, __ATOMIC_RELAXED);523 } else {524 executor_->w_infos[id].failed_swaps++;525 }526 #else527 curr_steal_queue = try_swap_queues( this, i + vic_start, swap_idx );528 #endif // ACTOR_STATS529 530 return;531 }532 533 return;534 }535 536 // choose a worker to steal from537 static inline void steal_work( worker & this, unsigned int swap_idx ) with(this) {538 #if RAND539 unsigned int victim = prng( executor_->nworkers );540 if ( victim == id ) victim = ( victim + 1 ) % executor_->nworkers;541 choose_queue( this, victim, swap_idx );542 #elif SEARCH543 unsigned long long min = MAX; // smaller timestamp means longer since service544 int min_id = 0; // use ints not uints to avoid integer underflow without hacky math545 int n_workers = executor_->nworkers;546 unsigned long long curr_stamp;547 int scount = 1;548 for ( int i = (id + 1) % n_workers; scount < n_workers; i = (i + 1) % n_workers, scount++ ) {549 curr_stamp = executor_->w_infos[i].stamp;550 if ( curr_stamp < min ) {551 min = curr_stamp;552 min_id = i;553 }554 }555 choose_queue( this, min_id, swap_idx );556 #endif557 306 } 558 307 559 308 void main( worker & this ) with(this) { 560 // #ifdef ACTOR_STATS 561 // for ( i; executor_->nrqueues ) { 562 // replaced_queue[i] = 0; 563 // __atomic_store_n( &stolen_arr[i], 0, __ATOMIC_SEQ_CST ); 564 // } 565 // #endif 566 567 // threshold of empty queues we see before we go stealing 568 const unsigned int steal_threshold = 2 * range; 569 570 // Store variable data here instead of worker struct to avoid any potential false sharing 571 unsigned int empty_count = 0; 572 request & req; 573 work_queue * curr_work_queue; 574 309 bool should_delete; 575 310 Exit: 576 311 for ( unsigned int i = 0;; i = (i + 1) % range ) { // cycle through set of request buffers 577 curr_work_queue = request_queues[i + start]; 578 579 // check if queue is empty before trying to gulp it 580 if ( isEmpty( *curr_work_queue->c_queue ) ) { 581 #ifdef __STEAL 582 empty_count++; 583 if ( empty_count < steal_threshold ) continue; 584 #else 585 continue; 586 #endif 587 } 588 transfer( *curr_work_queue, ¤t_queue ); 589 #ifdef ACTOR_STATS 590 executor_->w_infos[id].gulps++; 591 #endif // ACTOR_STATS 592 #ifdef __STEAL 593 if ( isEmpty( *current_queue ) ) { 594 if ( unlikely( no_steal ) ) continue; 595 empty_count++; 596 if ( empty_count < steal_threshold ) continue; 597 empty_count = 0; 598 599 __atomic_store_n( &executor_->w_infos[id].stamp, rdtscl(), __ATOMIC_RELAXED ); 600 601 #ifdef ACTOR_STATS 602 executor_->w_infos[id].try_steal++; 603 #endif // ACTOR_STATS 604 605 steal_work( this, start + prng( range ) ); 606 continue; 607 } 608 #endif // __STEAL 312 // C_TODO: potentially check queue count instead of immediately trying to transfer 313 transfer( request_queues[i + start], ¤t_queue ); 609 314 while ( ! isEmpty( *current_queue ) ) { 610 #ifdef ACTOR_STATS 611 executor_->w_infos[id].processed++; 612 #endif 613 &req = &remove( *current_queue ); 614 if ( !&req ) continue; 315 &req = &remove( *current_queue, should_delete ); 316 if ( !&req ) continue; // possibly add some work stealing/idle sleep here 615 317 if ( req.stop ) break Exit; 616 318 deliver_request( req ); 617 } 618 #ifdef __STEAL 619 curr_work_queue->being_processed = false; // set done processing 620 empty_count = 0; // we found work so reset empty counter 621 #endif 622 623 // potentially reclaim some of the current queue's vector space if it is unused 624 reclaim( *current_queue ); 319 320 if ( should_delete ) delete( &req ); 321 } // while 625 322 } // for 626 323 } … … 631 328 632 329 static inline void send( actor & this, request & req ) { 633 verifyf( this.ticket != (unsigned long int)MAX, "Attempted to send message to deleted/dead actor\n" );634 330 send( *__actor_executor_, req, this.ticket ); 635 331 } 636 332 637 static inline void __reset_stats() {638 #ifdef ACTOR_STATS639 __total_tries = 0;640 __total_stolen = 0;641 __all_gulps = 0;642 __total_failed_swaps = 0;643 __all_processed = 0;644 __num_actors_stats = 0;645 __all_msgs_stolen = 0;646 #endif647 }648 649 333 static inline void start_actor_system( size_t num_thds ) { 650 __reset_stats();651 334 __actor_executor_thd = active_thread(); 652 335 __actor_executor_ = alloc(); … … 654 337 } 655 338 656 // TODO: potentially revisit getting number of processors 657 // ( currently the value stored in active_cluster()->procs.total is often stale 658 // and doesn't reflect how many procs are allocated ) 659 // static inline void start_actor_system() { start_actor_system( active_cluster()->procs.total ); } 660 static inline void start_actor_system() { start_actor_system( 1 ); } 339 static inline void start_actor_system() { start_actor_system( active_cluster()->procs.total ); } 661 340 662 341 static inline void start_actor_system( executor & this ) { 663 __reset_stats();664 342 __actor_executor_thd = active_thread(); 665 343 __actor_executor_ = &this; … … 676 354 __actor_executor_passed = false; 677 355 } 678 679 // Default messages to send to any actor to change status680 // assigned at creation to __base_msg_finished to avoid unused message warning681 message __base_msg_finished @= { .allocation_ : Finished };682 struct __DeleteMsg { inline message; } DeleteMsg = __base_msg_finished;683 struct __DestroyMsg { inline message; } DestroyMsg = __base_msg_finished;684 struct __FinishedMsg { inline message; } FinishedMsg = __base_msg_finished;685 686 Allocation receive( actor & this, __DeleteMsg & msg ) { return Delete; }687 Allocation receive( actor & this, __DestroyMsg & msg ) { return Destroy; }688 Allocation receive( actor & this, __FinishedMsg & msg ) { return Finished; }689 -
libcfa/src/concurrency/channel.hfa
rb110bcc r2ed94a9 1 # pragma once1 #include <locks.hfa> 2 2 3 #include <locks.hfa> 4 #include <list.hfa> 5 #include <mutex_stmt.hfa> 3 struct no_reacq_lock { 4 inline exp_backoff_then_block_lock; 5 }; 6 6 7 // link field used for threads waiting on channel 8 struct wait_link { 9 // used to put wait_link on a dl queue 10 inline dlink(wait_link); 11 12 // waiting thread 13 struct thread$ * t; 14 15 // shadow field 16 void * elem; 17 }; 18 P9_EMBEDDED( wait_link, dlink(wait_link) ) 19 20 static inline void ?{}( wait_link & this, thread$ * t, void * elem ) { 21 this.t = t; 22 this.elem = elem; 23 } 24 25 // wake one thread from the list 26 static inline void wake_one( dlist( wait_link ) & queue ) { 27 wait_link & popped = try_pop_front( queue ); 28 unpark( popped.t ); 29 } 30 31 // returns true if woken due to shutdown 32 // blocks thread on list and releases passed lock 33 static inline bool block( dlist( wait_link ) & queue, void * elem_ptr, go_mutex & lock ) { 34 wait_link w{ active_thread(), elem_ptr }; 35 insert_last( queue, w ); 36 unlock( lock ); 37 park(); 38 return w.elem == 0p; 39 } 40 41 // void * used for some fields since exceptions don't work with parametric polymorphism currently 42 exception channel_closed { 43 // on failed insert elem is a ptr to the element attempting to be inserted 44 // on failed remove elem ptr is 0p 45 // on resumption of a failed insert this elem will be inserted 46 // so a user may modify it in the resumption handler 47 void * elem; 48 49 // pointer to chan that is closed 50 void * closed_chan; 51 }; 52 vtable(channel_closed) channel_closed_vt; 53 54 // #define CHAN_STATS // define this to get channel stats printed in dtor 7 // have to override these by hand to get around plan 9 inheritance bug where resolver can't find the appropriate routine to call 8 static inline void ?{}( no_reacq_lock & this ) { ((exp_backoff_then_block_lock &)this){}; } 9 static inline bool try_lock(no_reacq_lock & this) { return try_lock(((exp_backoff_then_block_lock &)this)); } 10 static inline void lock(no_reacq_lock & this) { lock(((exp_backoff_then_block_lock &)this)); } 11 static inline void unlock(no_reacq_lock & this) { unlock(((exp_backoff_then_block_lock &)this)); } 12 static inline void on_notify(no_reacq_lock & this, struct thread$ * t ) { on_notify(((exp_backoff_then_block_lock &)this), t); } 13 static inline size_t on_wait(no_reacq_lock & this) { return on_wait(((exp_backoff_then_block_lock &)this)); } 14 // override wakeup so that we don't reacquire the lock if using a condvar 15 static inline void on_wakeup( no_reacq_lock & this, size_t recursion ) {} 55 16 56 17 forall( T ) { 57 58 struct __attribute__((aligned(128))) channel { 59 size_t size,front, back, count;18 struct channel { 19 size_t size; 20 size_t front, back, count; 60 21 T * buffer; 61 dlist( wait_link ) prods, cons; // lists of blocked threads 62 go_mutex mutex_lock; // MX lock 63 bool closed; // indicates channel close/open 64 #ifdef CHAN_STATS 65 size_t blocks, operations; // counts total ops and ops resulting in a blocked thd 66 #endif 22 fast_cond_var( no_reacq_lock ) prods, cons; 23 no_reacq_lock mutex_lock; 67 24 }; 68 25 … … 70 27 size = _size; 71 28 front = back = count = 0; 72 buffer = a alloc( size );29 buffer = anew( size ); 73 30 prods{}; 74 31 cons{}; 75 32 mutex_lock{}; 76 closed = false;77 #ifdef CHAN_STATS78 blocks = 0;79 operations = 0;80 #endif81 33 } 82 34 83 35 static inline void ?{}( channel(T) &c ){ ((channel(T) &)c){ 0 }; } 84 static inline void ^?{}( channel(T) &c ) with(c) { 85 #ifdef CHAN_STATS 86 printf("Channel %p Blocks: %lu, Operations: %lu, %.2f%% of ops blocked\n", &c, blocks, operations, ((double)blocks)/operations * 100); 87 #endif 88 verifyf( cons`isEmpty && prods`isEmpty, "Attempted to delete channel with waiting threads (Deadlock).\n" ); 89 delete( buffer ); 90 } 36 static inline void ^?{}( channel(T) &c ) with(c) { delete( buffer ); } 91 37 static inline size_t get_count( channel(T) & chan ) with(chan) { return count; } 92 38 static inline size_t get_size( channel(T) & chan ) with(chan) { return size; } 93 static inline bool has_waiters( channel(T) & chan ) with(chan) { return ! cons`isEmpty || !prods`isEmpty; }94 static inline bool has_waiting_consumers( channel(T) & chan ) with(chan) { return ! cons`isEmpty; }95 static inline bool has_waiting_producers( channel(T) & chan ) with(chan) { return ! prods`isEmpty; }39 static inline bool has_waiters( channel(T) & chan ) with(chan) { return !empty( cons ) || !empty( prods ); } 40 static inline bool has_waiting_consumers( channel(T) & chan ) with(chan) { return !empty( cons ); } 41 static inline bool has_waiting_producers( channel(T) & chan ) with(chan) { return !empty( prods ); } 96 42 97 // closes the channel and notifies all blocked threads 98 static inline void close( channel(T) & chan ) with(chan) { 99 lock( mutex_lock ); 100 closed = true; 101 102 // flush waiting consumers and producers 103 while ( has_waiting_consumers( chan ) ) { 104 cons`first.elem = 0p; 105 wake_one( cons ); 106 } 107 while ( has_waiting_producers( chan ) ) { 108 prods`first.elem = 0p; 109 wake_one( prods ); 110 } 111 unlock(mutex_lock); 112 } 113 114 static inline void is_closed( channel(T) & chan ) with(chan) { return closed; } 115 116 static inline void flush( channel(T) & chan, T elem ) with(chan) { 117 lock( mutex_lock ); 118 while ( count == 0 && !cons`isEmpty ) { 119 memcpy(cons`first.elem, (void *)&elem, sizeof(T)); // do waiting consumer work 120 wake_one( cons ); 121 } 122 unlock( mutex_lock ); 123 } 124 125 // handles buffer insert 126 static inline void __buf_insert( channel(T) & chan, T & elem ) with(chan) { 43 static inline void insert_( channel(T) & chan, T elem ) with(chan) { 127 44 memcpy((void *)&buffer[back], (void *)&elem, sizeof(T)); 128 45 count += 1; … … 131 48 } 132 49 133 // does the buffer insert or hands elem directly to consumer if one is waiting134 static inline void __do_insert( channel(T) & chan, T & elem ) with(chan) {135 if ( count == 0 && !cons`isEmpty ) {136 memcpy(cons`first.elem, (void *)&elem, sizeof(T)); // do waiting consumer work137 wake_one( cons );138 } else __buf_insert( chan, elem );139 }140 141 // needed to avoid an extra copy in closed case142 static inline bool __internal_try_insert( channel(T) & chan, T & elem ) with(chan) {143 lock( mutex_lock );144 #ifdef CHAN_STATS145 operations++;146 #endif147 if ( count == size ) { unlock( mutex_lock ); return false; }148 __do_insert( chan, elem );149 unlock( mutex_lock );150 return true;151 }152 153 // attempts a nonblocking insert154 // returns true if insert was successful, false otherwise155 static inline bool try_insert( channel(T) & chan, T elem ) { return __internal_try_insert( chan, elem ); }156 157 // handles closed case of insert routine158 static inline void __closed_insert( channel(T) & chan, T & elem ) with(chan) {159 channel_closed except{&channel_closed_vt, &elem, &chan };160 throwResume except; // throw closed resumption161 if ( !__internal_try_insert( chan, elem ) ) throw except; // if try to insert fails (would block), throw termination162 }163 50 164 51 static inline void insert( channel(T) & chan, T elem ) with(chan) { 165 // check for close before acquire mx166 if ( unlikely(closed) ) {167 __closed_insert( chan, elem );168 return;169 }170 171 52 lock( mutex_lock ); 172 53 173 #ifdef CHAN_STATS 174 if ( !closed ) operations++; 175 #endif 176 177 // if closed handle 178 if ( unlikely(closed) ) { 54 // have to check for the zero size channel case 55 if ( size == 0 && !empty( cons ) ) { 56 memcpy((void *)front( cons ), (void *)&elem, sizeof(T)); 57 notify_one( cons ); 179 58 unlock( mutex_lock ); 180 __closed_insert( chan, elem );181 59 return; 182 60 } 183 61 184 // have to check for the zero size channel case185 if ( size == 0 && !cons`isEmpty ) {186 memcpy(cons`first.elem, (void *)&elem, sizeof(T));187 wake_one( cons );188 unlock( mutex_lock );189 return true;190 }191 192 62 // wait if buffer is full, work will be completed by someone else 193 if ( count == size ) { 194 #ifdef CHAN_STATS 195 blocks++; 196 #endif 197 198 // check for if woken due to close 199 if ( unlikely( block( prods, &elem, mutex_lock ) ) ) 200 __closed_insert( chan, elem ); 63 if ( count == size ) { 64 wait( prods, mutex_lock, (uintptr_t)&elem ); 201 65 return; 202 66 } // if 203 67 204 if ( count == 0 && ! cons`isEmpty ) {205 memcpy(cons`first.elem, (void *)&elem, sizeof(T));// do waiting consumer work206 wake_one( cons );207 } else __buf_insert( chan, elem );68 if ( count == 0 && !empty( cons ) ) 69 // do waiting consumer work 70 memcpy((void *)front( cons ), (void *)&elem, sizeof(T)); 71 else insert_( chan, elem ); 208 72 73 notify_one( cons ); 209 74 unlock( mutex_lock ); 210 return;211 }212 213 // handles buffer remove214 static inline void __buf_remove( channel(T) & chan, T & retval ) with(chan) {215 memcpy((void *)&retval, (void *)&buffer[front], sizeof(T));216 count -= 1;217 front = (front + 1) % size;218 }219 220 // does the buffer remove and potentially does waiting producer work221 static inline void __do_remove( channel(T) & chan, T & retval ) with(chan) {222 __buf_remove( chan, retval );223 if (count == size - 1 && !prods`isEmpty ) {224 __buf_insert( chan, *(T *)prods`first.elem ); // do waiting producer work225 wake_one( prods );226 }227 }228 229 // needed to avoid an extra copy in closed case and single return val case230 static inline bool __internal_try_remove( channel(T) & chan, T & retval ) with(chan) {231 lock( mutex_lock );232 #ifdef CHAN_STATS233 operations++;234 #endif235 if ( count == 0 ) { unlock( mutex_lock ); return false; }236 __do_remove( chan, retval );237 unlock( mutex_lock );238 return true;239 }240 241 // attempts a nonblocking remove242 // returns [T, true] if insert was successful243 // returns [T, false] if insert was successful (T uninit)244 static inline [T, bool] try_remove( channel(T) & chan ) {245 T retval;246 return [ retval, __internal_try_remove( chan, retval ) ];247 }248 249 static inline T try_remove( channel(T) & chan, T elem ) {250 T retval;251 __internal_try_remove( chan, retval );252 return retval;253 }254 255 // handles closed case of insert routine256 static inline void __closed_remove( channel(T) & chan, T & retval ) with(chan) {257 channel_closed except{&channel_closed_vt, 0p, &chan };258 throwResume except; // throw resumption259 if ( !__internal_try_remove( chan, retval ) ) throw except; // if try to remove fails (would block), throw termination260 75 } 261 76 262 77 static inline T remove( channel(T) & chan ) with(chan) { 78 lock( mutex_lock ); 263 79 T retval; 264 if ( unlikely(closed) ) {265 __closed_remove( chan, retval );266 return retval;267 }268 lock( mutex_lock );269 270 #ifdef CHAN_STATS271 if ( !closed ) operations++;272 #endif273 274 if ( unlikely(closed) ) {275 unlock( mutex_lock );276 __closed_remove( chan, retval );277 return retval;278 }279 80 280 81 // have to check for the zero size channel case 281 if ( size == 0 && ! prods`isEmpty) {282 memcpy((void *)&retval, (void *) prods`first.elem, sizeof(T));283 wake_one( prods );82 if ( size == 0 && !empty( prods ) ) { 83 memcpy((void *)&retval, (void *)front( prods ), sizeof(T)); 84 notify_one( prods ); 284 85 unlock( mutex_lock ); 285 86 return retval; … … 287 88 288 89 // wait if buffer is empty, work will be completed by someone else 289 if (count == 0) { 290 #ifdef CHAN_STATS 291 blocks++; 292 #endif 293 // check for if woken due to close 294 if ( unlikely( block( cons, &retval, mutex_lock ) ) ) 295 __closed_remove( chan, retval ); 90 if (count == 0) { 91 wait( cons, mutex_lock, (uintptr_t)&retval ); 296 92 return retval; 297 93 } 298 94 299 95 // Remove from buffer 300 __do_remove( chan, retval ); 96 memcpy((void *)&retval, (void *)&buffer[front], sizeof(T)); 97 count -= 1; 98 front = (front + 1) % size; 301 99 100 if (count == size - 1 && !empty( prods ) ) 101 insert_( chan, *((T *)front( prods )) ); // do waiting producer work 102 103 notify_one( prods ); 302 104 unlock( mutex_lock ); 303 105 return retval; 304 106 } 107 305 108 } // forall( T ) -
libcfa/src/concurrency/clib/cfathread.cfa
rb110bcc r2ed94a9 16 16 // #define EPOLL_FOR_SOCKETS 17 17 18 #include <string.h>19 20 18 #include "fstream.hfa" 21 19 #include "locks.hfa" … … 25 23 #include "time.hfa" 26 24 #include "stdlib.hfa" 27 #include "iofwd.hfa" 25 28 26 #include "cfathread.h" 27 28 extern "C" { 29 #include <string.h> 30 #include <errno.h> 31 } 29 32 30 33 extern void ?{}(processor &, const char[], cluster &, thread$ *); 31 34 extern "C" { 32 extern void __cfactx_invoke_thread(void (*main)(void *), void * this); 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); 33 37 } 34 38 … … 468 472 } 469 473 474 #include <iofwd.hfa> 475 470 476 extern "C" { 477 #include <unistd.h> 478 #include <sys/types.h> 479 #include <sys/socket.h> 480 471 481 //-------------------- 472 482 // IO operations … … 478 488 , protocol); 479 489 } 480 int cfathread_bind(int socket, __CONST_SOCKADDR_ARGaddress, socklen_t address_len) {490 int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len) { 481 491 return bind(socket, address, address_len); 482 492 } … … 486 496 } 487 497 488 int cfathread_accept(int socket, __SOCKADDR_ARGaddress, socklen_t *restrict address_len) {498 int cfathread_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) { 489 499 #if defined(EPOLL_FOR_SOCKETS) 490 500 int ret; … … 503 513 } 504 514 505 int cfathread_connect(int socket, __CONST_SOCKADDR_ARGaddress, socklen_t address_len) {515 int cfathread_connect(int socket, const struct sockaddr *address, socklen_t address_len) { 506 516 #if defined(EPOLL_FOR_SOCKETS) 507 517 int ret; -
libcfa/src/concurrency/clib/cfathread.h
rb110bcc r2ed94a9 9 9 // Author : Thierry Delisle 10 10 // Created On : Tue Sep 22 15:31:20 2020 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Mar 13 23:48:40 202313 // Update Count : 711 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 14 // 15 15 16 #pragma once17 18 16 #if defined(__cforall) || defined(__cplusplus) 19 #include <unistd.h>20 #include <errno.h>21 #include <sys/socket.h>22 23 17 extern "C" { 24 18 #endif 19 #include <asm/types.h> 20 #include <errno.h> 21 #include <unistd.h> 22 23 25 24 //-------------------- 26 25 // Basic types … … 74 73 } cfathread_mutexattr_t; 75 74 typedef struct cfathread_mutex * cfathread_mutex_t; 76 int cfathread_mutex_init(cfathread_mutex_t * restrict mut, const cfathread_mutexattr_t *restrict attr) __attribute__((nonnull (1)));75 int cfathread_mutex_init(cfathread_mutex_t *restrict mut, const cfathread_mutexattr_t *restrict attr) __attribute__((nonnull (1))); 77 76 int cfathread_mutex_destroy(cfathread_mutex_t *mut) __attribute__((nonnull (1))); 78 77 int cfathread_mutex_lock(cfathread_mutex_t *mut) __attribute__((nonnull (1))); … … 92 91 //-------------------- 93 92 // IO operations 93 struct sockaddr; 94 struct msghdr; 94 95 int cfathread_socket(int domain, int type, int protocol); 95 int cfathread_bind(int socket, __CONST_SOCKADDR_ARGaddress, socklen_t address_len);96 int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len); 96 97 int cfathread_listen(int socket, int backlog); 97 int cfathread_accept(int socket, __SOCKADDR_ARG address, socklen_t *restrict address_len);98 int cfathread_connect(int socket, __CONST_SOCKADDR_ARGaddress, socklen_t address_len);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); 99 100 int cfathread_dup(int fildes); 100 101 int cfathread_close(int fildes); -
libcfa/src/concurrency/coroutine.cfa
rb110bcc r2ed94a9 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Feb 16 15:34:46 202313 // Update Count : 2 412 // Last Modified On : Tue Dec 15 12:06:04 2020 13 // Update Count : 23 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #include "coroutine.hfa" -
libcfa/src/concurrency/future.hfa
rb110bcc r2ed94a9 14 14 // 15 15 16 #pragma once16 // #pragma once 17 17 18 18 #include "bits/locks.hfa" -
libcfa/src/concurrency/invoke.h
rb110bcc r2ed94a9 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 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. 12 // Last Modified On : Tue Nov 29 20:42:21 2022 13 // Update Count : 56 14 // 17 15 18 16 #include "bits/containers.hfa" -
libcfa/src/concurrency/io.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #if defined(__CFA_DEBUG__) … … 295 296 // make sure the target hasn't stopped existing since last time 296 297 HELP: if(target < ctxs_count) { 297 // calculate it's age and how young it could be before we give up on helping298 // calculate it's age and how young it could be before we give ip on helping 298 299 const __readyQ_avg_t cutoff = calc_cutoff(ctsc, ctx->cq.id, ctxs_count, io.data, io.tscs, __shard_factor.io, false); 299 300 const __readyQ_avg_t age = moving_average(ctsc, io.tscs[target].t.tv, io.tscs[target].t.ma, false); -
libcfa/src/concurrency/io/call.cfa.in
rb110bcc r2ed94a9 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 38 33 #include "bits/defs.hfa" 39 34 #include "kernel.hfa" … … 48 43 #include <assert.h> 49 44 #include <stdint.h> 45 #include <errno.h> 50 46 #include <linux/io_uring.h> 47 51 48 #include "kernel/fwd.hfa" 52 49 … … 85 82 // I/O Forwards 86 83 //============================================================================================= 84 #include <time.hfa> 85 86 // Some forward declarations 87 #include <errno.h> 88 #include <unistd.h> 87 89 88 90 extern "C" { 91 #include <asm/types.h> 92 #include <sys/socket.h> 93 #include <sys/syscall.h> 94 89 95 #if defined(CFA_HAVE_PREADV2) 90 96 struct iovec; 91 extern ssize_t preadv2 (int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);97 extern ssize_t preadv2 (int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); 92 98 #endif 93 99 #if defined(CFA_HAVE_PWRITEV2) 94 100 struct iovec; 95 extern ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);101 extern ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); 96 102 #endif 97 103 … … 108 114 struct msghdr; 109 115 struct sockaddr; 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); 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); 114 122 115 123 extern int fallocate(int fd, int mode, off_t offset, off_t len); 116 124 extern int posix_fadvise(int fd, off_t offset, off_t len, int advice); 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);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); 120 128 extern int close(int fd); 121 129 122 extern ssize_t read (int fd, void * buf, size_t count);130 extern ssize_t read (int fd, void *buf, size_t count); 123 131 124 132 struct epoll_event; 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);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); 128 136 extern ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags); 129 137 } … … 224 232 calls = [ 225 233 # CFA_HAVE_IORING_OP_READV 226 Call('READV', 'ssize_t preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {234 Call('READV', 'ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', { 227 235 'fd' : 'fd', 228 'addr': '(typeof(sqe->addr))iov', 236 'off' : 'offset', 237 'addr': '(uintptr_t)iov', 229 238 'len' : 'iovcnt', 230 'off' : 'offset',231 'rw_flags' : 'flags'232 239 }, define = 'CFA_HAVE_PREADV2'), 233 240 # CFA_HAVE_IORING_OP_WRITEV 234 Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {241 Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', { 235 242 'fd' : 'fd', 236 'addr': '(typeof(sqe->addr))iov',237 'len' : 'iovcnt',238 243 'off' : 'offset', 239 'rw_flags' : 'flags' 244 'addr': '(uintptr_t)iov', 245 'len' : 'iovcnt' 240 246 }, define = 'CFA_HAVE_PWRITEV2'), 241 247 # CFA_HAVE_IORING_OP_FSYNC … … 244 250 }), 245 251 # CFA_HAVE_IORING_OP_EPOLL_CTL 246 Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event)', {252 Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)', { 247 253 'fd': 'epfd', 254 'addr': 'fd', 248 255 'len': 'op', 249 'addr': 'fd', 250 'off': '(typeof(sqe->off))event' 256 'off': '(uintptr_t)event' 251 257 }), 252 258 # CFA_HAVE_IORING_OP_SYNC_FILE_RANGE … … 258 264 }), 259 265 # CFA_HAVE_IORING_OP_SENDMSG 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',266 Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)', { 267 'fd': 'sockfd', 268 'addr': '(uintptr_t)(struct msghdr *)msg', 263 269 'len': '1', 264 270 'msg_flags': 'flags' 265 271 }), 266 272 # CFA_HAVE_IORING_OP_RECVMSG 267 Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags)', {268 'fd': 'sockfd', 269 'addr': '( typeof(sqe->addr))(struct msghdr *)msg',273 Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)', { 274 'fd': 'sockfd', 275 'addr': '(uintptr_t)(struct msghdr *)msg', 270 276 'len': '1', 271 277 'msg_flags': 'flags' 272 278 }), 273 279 # CFA_HAVE_IORING_OP_SEND 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',280 Call('SEND', 'ssize_t send(int sockfd, const void *buf, size_t len, int flags)', { 281 'fd': 'sockfd', 282 'addr': '(uintptr_t)buf', 277 283 'len': 'len', 278 284 'msg_flags': 'flags' 279 285 }), 280 286 # CFA_HAVE_IORING_OP_RECV 281 Call('RECV', 'ssize_t recv(int sockfd, void * buf, size_t len, int flags)', {282 'fd': 'sockfd', 283 'addr': '( typeof(sqe->addr))buf',287 Call('RECV', 'ssize_t recv(int sockfd, void *buf, size_t len, int flags)', { 288 'fd': 'sockfd', 289 'addr': '(uintptr_t)buf', 284 290 'len': 'len', 285 291 'msg_flags': 'flags' 286 292 }), 287 293 # CFA_HAVE_IORING_OP_ACCEPT 288 Call('ACCEPT', 'int accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t * restrictaddrlen, int flags)', {289 'fd': 'sockfd', 290 'addr': '( typeof(sqe->addr))&addr',291 'addr2': '( typeof(sqe->addr2))addrlen',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', 292 298 'accept_flags': 'flags' 293 299 }), 294 300 # CFA_HAVE_IORING_OP_CONNECT 295 Call('CONNECT', 'int connect(int sockfd, __CONST_SOCKADDR_ARGaddr, socklen_t addrlen)', {296 'fd': 'sockfd', 297 'addr': '( typeof(sqe->addr))&addr',301 Call('CONNECT', 'int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)', { 302 'fd': 'sockfd', 303 'addr': '(uintptr_t)addr', 298 304 'off': 'addrlen' 299 305 }), … … 301 307 Call('FALLOCATE', 'int fallocate(int fd, int mode, off_t offset, off_t len)', { 302 308 'fd': 'fd', 309 'addr': '(uintptr_t)len', 303 310 'len': 'mode', 304 'off': 'offset', 305 'addr': 'len' 311 'off': 'offset' 306 312 }), 307 313 # CFA_HAVE_IORING_OP_FADVISE … … 313 319 }), 314 320 # CFA_HAVE_IORING_OP_MADVISE 315 Call('MADVISE', 'int madvise(void * addr, size_t length, int advice)', {316 'addr': '( typeof(sqe->addr))addr',321 Call('MADVISE', 'int madvise(void *addr, size_t length, int advice)', { 322 'addr': '(uintptr_t)addr', 317 323 'len': 'length', 318 324 'fadvise_advice': 'advice' 319 325 }), 320 326 # CFA_HAVE_IORING_OP_OPENAT 321 Call('OPENAT', 'int openat(int dirfd, const char * pathname, int flags, mode_t mode)', {327 Call('OPENAT', 'int openat(int dirfd, const char *pathname, int flags, mode_t mode)', { 322 328 'fd': 'dirfd', 323 'addr': '( typeof(sqe->addr))pathname',324 ' open_flags': 'flags;',325 ' len': 'mode'329 'addr': '(uintptr_t)pathname', 330 'len': 'mode', 331 'open_flags': 'flags;' 326 332 }), 327 333 # CFA_HAVE_IORING_OP_OPENAT2 328 Call('OPENAT2', 'int openat2(int dirfd, const char * pathname, struct open_how * how, size_t size)', {334 Call('OPENAT2', 'int openat2(int dirfd, const char *pathname, struct open_how * how, size_t size)', { 329 335 'fd': 'dirfd', 330 'addr': ' (typeof(sqe->addr))pathname',331 ' off': '(typeof(sqe->off))how',332 ' len': 'sizeof(*how)'336 'addr': 'pathname', 337 'len': 'sizeof(*how)', 338 'off': '(uintptr_t)how', 333 339 }, define = 'CFA_HAVE_OPENAT2'), 334 340 # CFA_HAVE_IORING_OP_CLOSE … … 337 343 }), 338 344 # CFA_HAVE_IORING_OP_STATX 339 Call('STATX', 'int statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx *statxbuf)', {345 Call('STATX', 'int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf)', { 340 346 'fd': 'dirfd', 341 ' addr': '(typeof(sqe->addr))pathname',342 ' statx_flags': 'flags',347 'off': '(uintptr_t)statxbuf', 348 'addr': 'pathname', 343 349 'len': 'mask', 344 ' off': '(typeof(sqe->off))statxbuf'350 'statx_flags': 'flags' 345 351 }, define = 'CFA_HAVE_STATX'), 346 352 # CFA_HAVE_IORING_OP_READ 347 353 Call('READ', 'ssize_t read(int fd, void * buf, size_t count)', { 348 354 'fd': 'fd', 349 'addr': '( typeof(sqe->addr))buf',355 'addr': '(uintptr_t)buf', 350 356 'len': 'count' 351 357 }), … … 353 359 Call('WRITE', 'ssize_t write(int fd, void * buf, size_t count)', { 354 360 'fd': 'fd', 355 'addr': '( typeof(sqe->addr))buf',361 'addr': '(uintptr_t)buf', 356 362 'len': 'count' 357 363 }), 358 364 # CFA_HAVE_IORING_OP_SPLICE 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)', {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)', { 360 366 'splice_fd_in': 'fd_in', 361 'splice_off_in': 'off_in ? ( typeof(sqe->splice_off_in))*off_in : (typeof(sqe->splice_off_in))-1',367 'splice_off_in': 'off_in ? (__u64)*off_in : (__u64)-1', 362 368 'fd': 'fd_out', 363 'off': 'off_out ? ( typeof(sqe->off))*off_out : (typeof(sqe->off))-1',369 'off': 'off_out ? (__u64)*off_out : (__u64)-1', 364 370 'len': 'len', 365 371 'splice_flags': 'flags' -
libcfa/src/concurrency/io/setup.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #if defined(__CFA_DEBUG__) -
libcfa/src/concurrency/iofwd.hfa
rb110bcc r2ed94a9 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu Apr 23 17:31:00 2020 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Mar 13 23:54:57 202313 // Update Count : 111 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 14 // 15 15 … … 17 17 18 18 #include <unistd.h> 19 #include <sys/socket.h>20 21 19 extern "C" { 22 20 #include <asm/types.h> … … 50 48 typedef __off64_t off64_t; 51 49 50 struct cluster; 51 struct io_context$; 52 53 struct iovec; 54 struct msghdr; 55 struct sockaddr; 56 struct statx; 52 57 struct epoll_event; 58 59 struct io_uring_sqe; 53 60 54 61 //----------------------------------------------------------------------- … … 81 88 // synchronous calls 82 89 #if defined(CFA_HAVE_PREADV2) 83 extern ssize_t cfa_preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);90 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 84 91 #endif 85 92 #if defined(CFA_HAVE_PWRITEV2) 86 extern ssize_t cfa_pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);93 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags); 87 94 #endif 88 95 extern int cfa_fsync(int fd, __u64 submit_flags); 89 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags);96 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event, __u64 submit_flags); 90 97 extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, __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 * restrictaddrlen, int flags, __u64 submit_flags);96 extern int cfa_connect(int sockfd, __CONST_SOCKADDR_ARGaddr, socklen_t addrlen, __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); 97 104 extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, __u64 submit_flags); 98 105 extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, __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);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); 101 108 #if defined(CFA_HAVE_OPENAT2) 102 extern int cfa_openat2(int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);109 extern int cfa_openat2(int dirfd, const char *pathname, struct open_how * how, size_t size, __u64 submit_flags); 103 110 #endif 104 111 extern int cfa_close(int fd, __u64 submit_flags); 105 112 #if defined(CFA_HAVE_STATX) 106 extern int cfa_statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags);113 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags); 107 114 #endif 108 115 extern ssize_t cfa_read(int fd, void * buf, size_t count, __u64 submit_flags); 109 116 extern ssize_t cfa_write(int fd, void * buf, size_t count, __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);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); 111 118 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags); 112 119 … … 114 121 // asynchronous calls 115 122 #if defined(CFA_HAVE_PREADV2) 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);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); 117 124 #endif 118 125 #if defined(CFA_HAVE_PWRITEV2) 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);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); 120 127 #endif 121 128 extern void async_fsync(io_future_t & future, int fd, __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);129 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event *event, __u64 submit_flags); 123 130 extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, __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 * restrictaddrlen, int flags, __u64 submit_flags);129 extern void async_connect(io_future_t & future, int sockfd, __CONST_SOCKADDR_ARGaddr, socklen_t addrlen, __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); 130 137 extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, __u64 submit_flags); 131 138 extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, __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);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); 134 141 #if defined(CFA_HAVE_OPENAT2) 135 extern void async_openat2(io_future_t & future, int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);142 extern void async_openat2(io_future_t & future, int dirfd, const char *pathname, struct open_how * how, size_t size, __u64 submit_flags); 136 143 #endif 137 144 extern void async_close(io_future_t & future, int fd, __u64 submit_flags); 138 145 #if defined(CFA_HAVE_STATX) 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);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); 140 147 #endif 141 148 void async_read(io_future_t & future, int fd, void * buf, size_t count, __u64 submit_flags); 142 149 extern void async_write(io_future_t & future, int fd, void * buf, size_t count, __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);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); 144 151 extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags); 145 152 -
libcfa/src/concurrency/kernel.cfa
rb110bcc r2ed94a9 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 9 08:42:05 202313 // Update Count : 7 712 // Last Modified On : Wed Nov 30 18:14:08 2022 13 // Update Count : 76 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__ -
libcfa/src/concurrency/kernel/cluster.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #include "bits/defs.hfa" … … 68 69 return max_cores_l; 69 70 } 71 72 #if defined(CFA_HAVE_LINUX_LIBRSEQ) 73 // No forward declaration needed 74 #define __kernel_rseq_register rseq_register_current_thread 75 #define __kernel_rseq_unregister rseq_unregister_current_thread 76 #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_register 81 #define __kernel_rseq_unregister __kernel_raw_rseq_unregister 82 #else 83 // No forward declaration needed 84 // No initialization needed 85 static inline void noop(void) {} 86 87 #define __kernel_rseq_register noop 88 #define __kernel_rseq_unregister noop 89 #endif 70 90 71 91 //======================================================================= … … 91 111 // Lock-Free registering/unregistering of threads 92 112 unsigned register_proc_id( void ) with(__scheduler_lock.lock) { 113 __kernel_rseq_register(); 114 93 115 bool * handle = (bool *)&kernelTLS().sched_lock; 94 116 … … 140 162 141 163 __atomic_store_n(cell, 0p, __ATOMIC_RELEASE); 164 165 __kernel_rseq_unregister(); 142 166 } 143 167 … … 481 505 /* paranoid */ verify( mock_head(this) == this.l.prev ); 482 506 } 507 508 #if defined(CFA_HAVE_LINUX_LIBRSEQ) 509 // No definition needed 510 #elif defined(CFA_HAVE_LINUX_RSEQ_H) 511 512 #if defined( __x86_64 ) || defined( __i386 ) 513 #define RSEQ_SIG 0x53053053 514 #elif defined( __ARM_ARCH ) 515 #ifdef __ARMEB__ 516 #define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */ 517 #else 518 #define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */ 519 #endif 520 #endif 521 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 #else 561 // No definition needed 562 #endif -
libcfa/src/concurrency/kernel/cluster.hfa
rb110bcc r2ed94a9 146 146 } 147 147 148 conststatic struct {149 unsigned readyq;150 unsigned io;148 static struct { 149 const unsigned readyq; 150 const unsigned io; 151 151 } __shard_factor = { 2, 1 }; 152 152 -
libcfa/src/concurrency/kernel/private.hfa
rb110bcc r2ed94a9 10 10 // Created On : Mon Feb 13 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 2 16:04:46 202313 // Update Count : 1112 // Last Modified On : Wed Aug 12 08:21:33 2020 13 // Update Count : 9 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 #else 36 #ifndef _GNU_SOURCE 37 #error kernel/private requires gnu_source 38 #endif 31 39 #include <sched.h> 40 #endif 32 41 } 33 42 … … 101 110 // Hardware 102 111 112 #if defined(CFA_HAVE_LINUX_LIBRSEQ) 113 // No data needed 114 #elif defined(CFA_HAVE_LINUX_RSEQ_H) 115 extern "Cforall" { 116 extern __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq; 117 } 118 #else 119 // No data needed 120 #endif 121 103 122 static inline int __kernel_getcpu() { 104 123 /* 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 #else 105 131 return sched_getcpu(); 132 #endif 106 133 } 107 134 -
libcfa/src/concurrency/kernel/startup.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__ 19 20 20 21 // C Includes 21 #include <errno.h> // errno22 #include <errno.h> // errno 22 23 #include <signal.h> 23 #include <string.h> // strerror24 #include <unistd.h> 25 #include <limits.h> // PTHREAD_STACK_MIN 24 #include <string.h> // strerror 25 #include <unistd.h> // sysconf 26 26 27 extern "C" { 27 #include <sys/eventfd.h> // eventfd 28 #include <sys/mman.h> // mprotect 29 #include <sys/resource.h> // getrlimit 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 30 33 } 31 34 … … 33 36 #include "kernel/private.hfa" 34 37 #include "iofwd.hfa" 35 #include "startup.hfa" // STARTUP_PRIORITY_XXX38 #include "startup.hfa" // STARTUP_PRIORITY_XXX 36 39 #include "limits.hfa" 37 40 #include "math.hfa" … … 147 150 __scheduler_RWLock_t __scheduler_lock @= { 0 }; 148 151 152 #if defined(CFA_HAVE_LINUX_LIBRSEQ) 153 // No data needed 154 #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 #else 161 // No data needed 162 #endif 163 149 164 //----------------------------------------------------------------------------- 150 165 // Struct to steal stack -
libcfa/src/concurrency/locks.cfa
rb110bcc r2ed94a9 16 16 17 17 #define __cforall_thread__ 18 #define _GNU_SOURCE 18 19 19 20 #include "locks.hfa" -
libcfa/src/concurrency/locks.hfa
rb110bcc r2ed94a9 32 32 #include <fstream.hfa> 33 33 34 34 35 // futex headers 35 36 #include <linux/futex.h> /* Definition of FUTEX_* constants */ … … 154 155 // futex_mutex 155 156 157 // - No cond var support 156 158 // - Kernel thd blocking alternative to the spinlock 157 159 // - No ownership (will deadlock on reacq) … … 183 185 int state; 184 186 185 for( int spin = 4; spin < 1024; spin += spin) { 186 state = 0; 187 // if unlocked, lock and return 188 if (internal_try_lock(this, state)) return; 189 if (2 == state) break; 190 for (int i = 0; i < spin; i++) Pause(); 191 } 192 193 // // no contention try to acquire 194 // if (internal_try_lock(this, state)) return; 187 188 // // linear backoff omitted for now 189 // for( int spin = 4; spin < 1024; spin += spin) { 190 // state = 0; 191 // // if unlocked, lock and return 192 // if (internal_try_lock(this, state)) return; 193 // if (2 == state) break; 194 // for (int i = 0; i < spin; i++) Pause(); 195 // } 196 197 // no contention try to acquire 198 if (internal_try_lock(this, state)) return; 195 199 196 200 // if not in contended state, set to be in contended state … … 205 209 206 210 static inline void unlock(futex_mutex & this) with(this) { 207 // if uncontended do atomic unlock and then return208 if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return; 211 // if uncontended do atomice unlock and then return 212 if (__atomic_fetch_sub(&val, 1, __ATOMIC_RELEASE) == 1) return; // TODO: try acq/rel 209 213 210 214 // otherwise threads are blocked so we must wake one 215 __atomic_store_n((int *)&val, 0, __ATOMIC_RELEASE); 211 216 futex((int *)&val, FUTEX_WAKE, 1); 212 217 } … … 217 222 // to set recursion count after getting signalled; 218 223 static inline void on_wakeup( futex_mutex & f, size_t recursion ) {} 219 220 //-----------------------------------------------------------------------------221 // go_mutex222 223 // - Kernel thd blocking alternative to the spinlock224 // - No ownership (will deadlock on reacq)225 // - Golang's flavour of mutex226 // - Impl taken from Golang: src/runtime/lock_futex.go227 struct go_mutex {228 // lock state any state other than UNLOCKED is locked229 // enum LockState { UNLOCKED = 0, LOCKED = 1, SLEEPING = 2 };230 231 // stores a lock state232 int val;233 };234 235 static inline void ?{}( go_mutex & this ) with(this) { val = 0; }236 237 static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) {238 return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, new_val, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);239 }240 241 static inline int internal_exchange(go_mutex & this, int swap ) with(this) {242 return __atomic_exchange_n((int*)&val, swap, __ATOMIC_ACQUIRE);243 }244 245 // if this is called recursively IT WILL DEADLOCK!!!!!246 static inline void lock(go_mutex & this) with(this) {247 int state, init_state;248 249 // speculative grab250 state = internal_exchange(this, 1);251 if ( !state ) return; // state == 0252 init_state = state;253 for (;;) {254 for( int i = 0; i < 4; i++ ) {255 while( !val ) { // lock unlocked256 state = 0;257 if (internal_try_lock(this, state, init_state)) return;258 }259 for (int i = 0; i < 30; i++) Pause();260 }261 262 while( !val ) { // lock unlocked263 state = 0;264 if (internal_try_lock(this, state, init_state)) return;265 }266 sched_yield();267 268 // if not in contended state, set to be in contended state269 state = internal_exchange(this, 2);270 if ( !state ) return; // state == 0271 init_state = 2;272 futex((int*)&val, FUTEX_WAIT, 2); // if val is not 2 this returns with EWOULDBLOCK273 }274 }275 276 static inline void unlock( go_mutex & this ) with(this) {277 // if uncontended do atomic unlock and then return278 if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return;279 280 // otherwise threads are blocked so we must wake one281 futex((int *)&val, FUTEX_WAKE, 1);282 }283 284 static inline void on_notify( go_mutex & f, thread$ * t){ unpark(t); }285 static inline size_t on_wait( go_mutex & f ) {unlock(f); return 0;}286 static inline void on_wakeup( go_mutex & f, size_t recursion ) {}287 224 288 225 //----------------------------------------------------------------------------- … … 316 253 static inline void on_wakeup(clh_lock & this, size_t recursion ) { lock(this); } 317 254 255 318 256 //----------------------------------------------------------------------------- 319 257 // Exponential backoff then block lock … … 334 272 this.lock_value = 0; 335 273 } 336 337 static inline void ^?{}( exp_backoff_then_block_lock & this ){} 274 static inline void ^?{}( exp_backoff_then_block_lock & this ) {} 275 // static inline void ?{}( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void; 276 // static inline void ?=?( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void; 338 277 339 278 static inline bool internal_try_lock(exp_backoff_then_block_lock & this, size_t & compare_val) with(this) { 340 return __atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); 279 if (__atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { 280 return true; 281 } 282 return false; 341 283 } 342 284 … … 344 286 345 287 static inline bool try_lock_contention(exp_backoff_then_block_lock & this) with(this) { 346 return !__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE); 288 if (__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE) == 0) { 289 return true; 290 } 291 return false; 347 292 } 348 293 349 294 static inline bool block(exp_backoff_then_block_lock & this) with(this) { 350 lock( spinlock __cfaabi_dbg_ctx2 ); 351 if (__atomic_load_n( &lock_value, __ATOMIC_SEQ_CST)!= 2) {352 unlock( spinlock );353 return true;354 }355 insert_last( blocked_threads, *active_thread() );356 unlock( spinlock );295 lock( spinlock __cfaabi_dbg_ctx2 ); // TODO change to lockfree queue (MPSC) 296 if (lock_value != 2) { 297 unlock( spinlock ); 298 return true; 299 } 300 insert_last( blocked_threads, *active_thread() ); 301 unlock( spinlock ); 357 302 park( ); 358 303 return true; … … 362 307 size_t compare_val = 0; 363 308 int spin = 4; 364 365 309 // linear backoff 366 310 for( ;; ) { … … 380 324 static inline void unlock(exp_backoff_then_block_lock & this) with(this) { 381 325 if (__atomic_exchange_n(&lock_value, 0, __ATOMIC_RELEASE) == 1) return; 382 lock( spinlock __cfaabi_dbg_ctx2 );383 thread$ * t = &try_pop_front( blocked_threads );384 unlock( spinlock );385 unpark( t );326 lock( spinlock __cfaabi_dbg_ctx2 ); 327 thread$ * t = &try_pop_front( blocked_threads ); 328 unlock( spinlock ); 329 unpark( t ); 386 330 } 387 331 -
libcfa/src/concurrency/monitor.cfa
rb110bcc r2ed94a9 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 19 17:00:59 202313 // Update Count : 1 212 // Last Modified On : Wed Dec 4 07:55:14 2019 13 // Update Count : 10 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #include "monitor.hfa" -
libcfa/src/concurrency/mutex.cfa
rb110bcc r2ed94a9 12 12 // Created On : Fri May 25 01:37:11 2018 13 13 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Sun Feb 19 17:01:36 202315 // Update Count : 314 // Last Modified On : Wed Dec 4 09:16:39 2019 15 // Update Count : 1 16 16 // 17 17 18 18 #define __cforall_thread__ 19 #define _GNU_SOURCE 19 20 20 21 #include "mutex.hfa" -
libcfa/src/concurrency/mutex_stmt.hfa
rb110bcc r2ed94a9 1 #pragma once2 3 1 #include "bits/algorithm.hfa" 4 2 #include "bits/defs.hfa" … … 6 4 //----------------------------------------------------------------------------- 7 5 // is_lock 8 forall(L & | sized(L)) 9 trait is_lock { 6 trait is_lock(L & | sized(L)) { 10 7 // For acquiring a lock 11 8 void lock( L & ); … … 27 24 // Sort locks based on address 28 25 __libcfa_small_sort(this.lockarr, count); 26 27 // acquire locks in order 28 // 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 // } 29 37 } 30 38 -
libcfa/src/concurrency/preemption.cfa
rb110bcc r2ed94a9 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 9 08:42:59 202313 // Update Count : 6012 // Last Modified On : Thu Feb 17 11:18:57 2022 13 // Update Count : 59 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 // #define __CFA_DEBUG_PRINT_PREEMPTION__ -
libcfa/src/concurrency/pthread.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #include <signal.h> … … 34 35 struct pthread_values{ 35 36 inline Seqable; 36 void * value;37 void* value; 37 38 bool in_use; 38 39 }; … … 50 51 struct pthread_keys { 51 52 bool in_use; 52 void (* destructor)( void * );53 void (*destructor)( void * ); 53 54 Sequence(pthread_values) threads; 54 55 }; 55 56 56 static void ?{}(pthread_keys& k) {57 static void ?{}(pthread_keys& k){ 57 58 k.threads{}; 58 59 } … … 61 62 static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16))); 62 63 63 static void init_pthread_storage() {64 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ){64 static void init_pthread_storage(){ 65 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){ 65 66 cfa_pthread_keys_storage[i]{}; 66 67 } … … 95 96 96 97 /* condvar helper routines */ 97 static void init(pthread_cond_t * pcond){98 static void init(pthread_cond_t* pcond){ 98 99 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 99 cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t*)pcond;100 cfa2pthr_cond_var_t* _cond = (cfa2pthr_cond_var_t*)pcond; 100 101 ?{}(*_cond); 101 102 } 102 103 103 static cfa2pthr_cond_var_t * get(pthread_cond_t * pcond){104 static cfa2pthr_cond_var_t* get(pthread_cond_t* pcond){ 104 105 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 105 return (cfa2pthr_cond_var_t *)pcond;106 } 107 108 static void destroy(pthread_cond_t * cond){106 return (cfa2pthr_cond_var_t*)pcond; 107 } 108 109 static void destroy(pthread_cond_t* cond){ 109 110 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 110 111 ^?{}(*get(cond)); … … 115 116 116 117 /* mutex helper routines */ 117 static void mutex_check(pthread_mutex_t * t){118 static void mutex_check(pthread_mutex_t* t){ 118 119 // Use double check to improve performance. 119 120 // Check is safe on x86; volatile prevents compiler reordering 120 volatile pthread_mutex_t * const mutex_ = t;121 volatile pthread_mutex_t *const mutex_ = t; 121 122 122 123 // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h … … 135 136 136 137 137 static void init(pthread_mutex_t * plock){138 static void init(pthread_mutex_t* plock){ 138 139 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 139 simple_owner_lock * _lock = (simple_owner_lock*)plock;140 simple_owner_lock* _lock = (simple_owner_lock*)plock; 140 141 ?{}(*_lock); 141 142 } 142 143 143 static simple_owner_lock * get(pthread_mutex_t * plock){144 static simple_owner_lock* get(pthread_mutex_t* plock){ 144 145 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 145 return (simple_owner_lock *)plock;146 } 147 148 static void destroy(pthread_mutex_t * plock){146 return (simple_owner_lock*)plock; 147 } 148 149 static void destroy(pthread_mutex_t* plock){ 149 150 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 150 151 ^?{}(*get(plock)); … … 152 153 153 154 //######################### Attr helpers ######################### 154 typedef struct cfaPthread_attr_t {// thread attributes155 struct cfaPthread_attr_t { // thread attributes 155 156 int contentionscope; 156 157 int detachstate; 157 158 size_t stacksize; 158 void * stackaddr;159 void *stackaddr; 159 160 int policy; 160 161 int inheritsched; 161 162 struct sched_param param; 162 } cfaPthread_attr_t;163 164 static const cfaPthread_attr_t default_attrs {163 } typedef cfaPthread_attr_t; 164 165 static const cfaPthread_attr_t default_attrs{ 165 166 0, 166 167 0, 167 65_000,168 NULL,168 (size_t)65000, 169 (void *)NULL, 169 170 0, 170 171 0, … … 172 173 }; 173 174 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;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; 177 178 } 178 179 … … 189 190 190 191 // pthreads return value 191 void * joinval;192 void *joinval; 192 193 193 194 // pthread attributes 194 195 pthread_attr_t pthread_attr; 195 196 196 void *(* start_routine)(void *);197 void * start_arg;197 void *(*start_routine)(void *); 198 void *start_arg; 198 199 199 200 // thread local data 200 pthread_values * pthreadData;201 pthread_values* pthreadData; 201 202 202 203 // flag used for tryjoin … … 206 207 /* thread part routines */ 207 208 // cfaPthread entry point 208 void main(cfaPthread & _thread) with(_thread){209 joinval = start_routine(start_arg);209 void main(cfaPthread& _thread) with(_thread){ 210 joinval = start_routine(start_arg); 210 211 isTerminated = true; 211 212 } 212 213 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::invokeTask219 pthread_values * value;220 pthread_keys * key;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::invokeTask 220 pthread_values* value; 221 pthread_keys* key; 221 222 bool destcalled = true; 222 if (values != NULL) {223 if (values != NULL){ 223 224 for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) { 224 225 destcalled = false; 225 226 lock(key_lock); 226 for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ){227 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){ 227 228 // for each valid key 228 if ( values[i].in_use) {229 if ( values[i].in_use){ 229 230 value = &values[i]; 230 231 key = &cfa_pthread_keys[i]; … … 233 234 // if a key value has a non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, 234 235 // 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. 235 if (value->value != NULL && key->destructor != NULL) {236 if (value->value != NULL && key->destructor != NULL){ 236 237 unlock(key_lock); 237 238 key->destructor(value->value); // run destructor … … 248 249 } 249 250 250 static void ^?{}(cfaPthread & mutex t) {251 static void ^?{}(cfaPthread & mutex t){ 251 252 // delete pthread local storage 252 253 pthread_values * values = t.pthreadData; … … 254 255 } 255 256 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*)");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*)"); 258 259 259 260 // set up user thread stackSize … … 277 278 //######################### Pthread Attrs ######################### 278 279 279 int pthread_attr_init(pthread_attr_t * attr) libcfa_public __THROW {280 cfaPthread_attr_t * _attr = get(attr);280 int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW { 281 cfaPthread_attr_t* _attr = get(attr); 281 282 ?{}(*_attr, default_attrs); 282 283 return 0; 283 284 } 284 int pthread_attr_destroy(pthread_attr_t * attr) libcfa_public __THROW {285 int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW { 285 286 ^?{}(*get(attr)); 286 287 return 0; 287 288 } 288 289 289 int pthread_attr_setscope( pthread_attr_t * attr, int contentionscope ) libcfa_public __THROW {290 int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW { 290 291 get( attr )->contentionscope = contentionscope; 291 292 return 0; 292 293 } // pthread_attr_setscope 293 294 294 int pthread_attr_getscope( const pthread_attr_t * attr, int *contentionscope ) libcfa_public __THROW {295 int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW { 295 296 *contentionscope = get( attr )->contentionscope; 296 297 return 0; 297 298 } // pthread_attr_getscope 298 299 299 int pthread_attr_setdetachstate( pthread_attr_t * attr, int detachstate ) libcfa_public __THROW {300 int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW { 300 301 get( attr )->detachstate = detachstate; 301 302 return 0; 302 303 } // pthread_attr_setdetachstate 303 304 304 int pthread_attr_getdetachstate( const pthread_attr_t * attr, int *detachstate ) libcfa_public __THROW {305 int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW { 305 306 *detachstate = get( attr )->detachstate; 306 307 return 0; 307 308 } // pthread_attr_getdetachstate 308 309 309 int pthread_attr_setstacksize( pthread_attr_t * attr, size_t stacksize ) libcfa_public __THROW {310 int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW { 310 311 get( attr )->stacksize = stacksize; 311 312 return 0; 312 313 } // pthread_attr_setstacksize 313 314 314 int pthread_attr_getstacksize( const pthread_attr_t * attr, size_t *stacksize ) libcfa_public __THROW {315 int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW { 315 316 *stacksize = get( attr )->stacksize; 316 317 return 0; … … 325 326 } // pthread_attr_setguardsize 326 327 327 int pthread_attr_setstackaddr( pthread_attr_t * attr, void *stackaddr ) libcfa_public __THROW {328 int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW { 328 329 get( attr )->stackaddr = stackaddr; 329 330 return 0; 330 331 } // pthread_attr_setstackaddr 331 332 332 int pthread_attr_getstackaddr( const pthread_attr_t * attr, void **stackaddr ) libcfa_public __THROW {333 int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW { 333 334 *stackaddr = get( attr )->stackaddr; 334 335 return 0; 335 336 } // pthread_attr_getstackaddr 336 337 337 int pthread_attr_setstack( pthread_attr_t * attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW {338 int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW { 338 339 get( attr )->stackaddr = stackaddr; 339 340 get( attr )->stacksize = stacksize; … … 341 342 } // pthread_attr_setstack 342 343 343 int pthread_attr_getstack( const pthread_attr_t * attr, void ** stackaddr, size_t *stacksize ) libcfa_public __THROW {344 int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW { 344 345 *stackaddr = get( attr )->stackaddr; 345 346 *stacksize = get( attr )->stacksize; … … 350 351 // already running thread threadID. It shall be called on unitialized attr 351 352 // and destroyed with pthread_attr_destroy when no longer needed. 352 int pthread_getattr_np( pthread_t threadID, pthread_attr_t * attr ) libcfa_public __THROW { // GNU extension353 int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension 353 354 check_nonnull(attr); 354 355 … … 362 363 //######################### Threads ######################### 363 364 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();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(); 366 367 (*t){_thread, attr, start_routine, arg}; 367 368 return 0; 368 369 } 369 370 370 int pthread_join(pthread_t _thread, void ** value_ptr) libcfa_public __THROW { 371 372 int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 371 373 // if thread is invalid 372 374 if (_thread == NULL) return EINVAL; … … 374 376 375 377 // get user thr pointer 376 cfaPthread * p = lookup(_thread);378 cfaPthread* p = lookup(_thread); 377 379 try { 378 380 join(*p); … … 387 389 } 388 390 389 int pthread_tryjoin_np(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {391 int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 390 392 // if thread is invalid 391 393 if (_thread == NULL) return EINVAL; 392 394 if (_thread == pthread_self()) return EDEADLK; 393 395 394 cfaPthread * p = lookup(_thread);396 cfaPthread* p = lookup(_thread); 395 397 396 398 // thread not finished ? … … 410 412 void pthread_exit(void * status) libcfa_public __THROW { 411 413 pthread_t pid = pthread_self(); 412 cfaPthread * _thread = (cfaPthread*)pid;414 cfaPthread* _thread = (cfaPthread*)pid; 413 415 _thread->joinval = status; // set return value 414 416 _thread->isTerminated = 1; // set terminated flag … … 424 426 //######################### Mutex ######################### 425 427 426 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t * attr) libcfa_public __THROW {428 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t *attr) libcfa_public __THROW { 427 429 check_nonnull(_mutex); 428 430 init(_mutex); … … 433 435 int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW { 434 436 check_nonnull(_mutex); 435 simple_owner_lock * _lock = get(_mutex);436 if (_lock->owner != NULL) {437 simple_owner_lock* _lock = get(_mutex); 438 if (_lock->owner != NULL){ 437 439 return EBUSY; 438 440 } … … 444 446 check_nonnull(_mutex); 445 447 mutex_check(_mutex); 446 simple_owner_lock * _lock = get(_mutex);448 simple_owner_lock* _lock = get(_mutex); 447 449 lock(*_lock); 448 450 return 0; … … 451 453 int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW { 452 454 check_nonnull(_mutex); 453 simple_owner_lock * _lock = get(_mutex);454 if (_lock->owner != active_thread()) {455 simple_owner_lock* _lock = get(_mutex); 456 if (_lock->owner != active_thread()){ 455 457 return EPERM; 456 458 } // current thread does not hold the mutex … … 461 463 int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW { 462 464 check_nonnull(_mutex); 463 simple_owner_lock * _lock = get(_mutex);464 if (_lock->owner != active_thread() && _lock->owner != NULL) {465 simple_owner_lock* _lock = get(_mutex); 466 if (_lock->owner != active_thread() && _lock->owner != NULL){ 465 467 return EBUSY; 466 468 } // if mutex is owned … … 472 474 473 475 /* conditional variable routines */ 474 int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *attr) libcfa_public __THROW {476 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) libcfa_public __THROW { 475 477 check_nonnull(cond); 476 478 init(cond); … … 478 480 } //pthread_cond_init 479 481 480 int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t *_mutex) libcfa_public __THROW {482 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *_mutex) libcfa_public __THROW { 481 483 check_nonnull(_mutex); 482 484 check_nonnull(cond); … … 492 494 } // pthread_cond_timedwait 493 495 494 int pthread_cond_signal(pthread_cond_t * cond) libcfa_public __THROW {496 int pthread_cond_signal(pthread_cond_t *cond) libcfa_public __THROW { 495 497 check_nonnull(cond); 496 498 return notify_one(*get(cond)); 497 499 } // pthread_cond_signal 498 500 499 int pthread_cond_broadcast(pthread_cond_t * cond) libcfa_public __THROW {501 int pthread_cond_broadcast(pthread_cond_t *cond) libcfa_public __THROW { 500 502 check_nonnull(cond); 501 503 return notify_all(*get(cond)); 502 504 } // pthread_cond_broadcast 503 505 504 int pthread_cond_destroy(pthread_cond_t * cond) libcfa_public __THROW {506 int pthread_cond_destroy(pthread_cond_t *cond) libcfa_public __THROW { 505 507 check_nonnull(cond); 506 508 destroy(cond); … … 512 514 //######################### Local storage ######################### 513 515 514 int pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) libcfa_public __THROW {516 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) libcfa_public __THROW { 515 517 static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)"); 516 518 check_nonnull(once_control); … … 525 527 } // pthread_once 526 528 527 int pthread_key_create( pthread_key_t * key, void (*destructor)( void * ) ) libcfa_public __THROW {529 int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) libcfa_public __THROW { 528 530 lock(key_lock); 529 531 for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) { … … 560 562 } // pthread_key_delete 561 563 562 int pthread_setspecific( pthread_key_t key, const void * value ) libcfa_public __THROW {564 int pthread_setspecific( pthread_key_t key, const void *value ) libcfa_public __THROW { 563 565 // get current thread 564 cfaPthread * t = lookup(pthread_self());566 cfaPthread* t = lookup(pthread_self()); 565 567 // if current thread's pthreadData is NULL; initialize it 566 pthread_values * values;567 if (t->pthreadData == NULL) {568 pthread_values* values; 569 if (t->pthreadData == NULL){ 568 570 values = anew( PTHREAD_KEYS_MAX); 569 571 t->pthreadData = values; 570 for ( int i = 0;i < PTHREAD_KEYS_MAX; i++ ){572 for (int i = 0;i < PTHREAD_KEYS_MAX; i++){ 571 573 t->pthreadData[i].in_use = false; 572 574 } // for … … 591 593 } //pthread_setspecific 592 594 593 void * pthread_getspecific(pthread_key_t key) libcfa_public __THROW {595 void* pthread_getspecific(pthread_key_t key) libcfa_public __THROW { 594 596 if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL; 595 597 596 598 // get current thread 597 cfaPthread * t = lookup(pthread_self());599 cfaPthread* t = lookup(pthread_self()); 598 600 if (t->pthreadData == NULL) return NULL; 599 601 lock(key_lock); 600 pthread_values & entry = ((pthread_values *)t->pthreadData)[key];602 pthread_values &entry = ((pthread_values *)t->pthreadData)[key]; 601 603 if ( ! entry.in_use ) { 602 604 unlock( key_lock ); 603 605 return NULL; 604 606 } // if 605 void * value = entry.value;607 void *value = entry.value; 606 608 unlock(key_lock); 607 609 … … 873 875 //######################### Parallelism ######################### 874 876 875 //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_np878 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_np882 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_np886 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_np877 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_np 880 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_np 884 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_np 888 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_np 890 892 891 893 //######################### Cancellation ######################### … … 904 906 } // pthread_cancel 905 907 906 int pthread_setcancelstate( int state, int * oldstate ) libcfa_public __THROW {908 int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW { 907 909 abort("pthread_setcancelstate not implemented"); 908 910 return 0; 909 911 } // pthread_setcancelstate 910 912 911 int pthread_setcanceltype( int type, int * oldtype ) libcfa_public __THROW {913 int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW { 912 914 abort("pthread_setcanceltype not implemented"); 913 915 return 0; … … 916 918 917 919 #pragma GCC diagnostic pop 920 -
libcfa/src/concurrency/ready_queue.cfa
rb110bcc r2ed94a9 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 // #define __CFA_DEBUG_PRINT_READY_QUEUE__ -
libcfa/src/concurrency/select.hfa
rb110bcc r2ed94a9 1 #pragma once2 3 1 #include "containers/list.hfa" 4 2 #include <stdint.h> -
libcfa/src/concurrency/thread.cfa
rb110bcc r2ed94a9 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 9 08:42:33 202313 // Update Count : 10 312 // Last Modified On : Sun Dec 11 20:56:54 2022 13 // Update Count : 102 14 14 // 15 15 16 16 #define __cforall_thread__ 17 #define _GNU_SOURCE 17 18 18 19 #include "thread.hfa" -
libcfa/src/containers/array.hfa
rb110bcc r2ed94a9 9 9 10 10 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 // 11 // 12 // Single-dim array sruct (with explicit packing and atom) 13 // 14 37 15 forall( [N], S & | sized(S), Timmed &, Tbase & ) { 38 39 //40 // Single-dim array sruct (with explicit packing and atom)41 //42 16 struct arpk { 43 17 S strides[N]; -
libcfa/src/containers/list.hfa
rb110bcc r2ed94a9 32 32 static inline tytagref(void, T) ?`inner ( T & this ) { tytagref( void, T ) ret = {this}; return ret; } 33 33 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 ) { \ 34 // use this on every case of plan-9 inheritance, to make embedded a closure of plan-9 inheritance 35 #define P9_EMBEDDED( derived, immedBase ) \ 36 forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \ 37 static inline tytagref(immedBase, Tbase) ?`inner( derived & this ) { \ 62 38 immedBase & ib = this; \ 63 39 Tbase & b = ib`inner; \ -
libcfa/src/containers/vector2.hfa
rb110bcc r2ed94a9 9 9 // Author : Michael Brooks 10 10 // Created On : Thu Jun 23 22:00:00 2021 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 11 // Last Modified By : Michael Brooks 12 // Last Modified On : Thu Jun 23 22:00:00 2021 13 // Update Count : 1 14 // 17 15 18 16 #include <stdlib.hfa> -
libcfa/src/interpose.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 27 21:09:03 2023 13 // Update Count : 196 14 // 15 12 // Last Modified On : Thu Jan 5 22:23:57 2023 13 // Update Count : 180 14 // 15 16 #include <stdarg.h> // va_start, va_end 16 17 #include <stdio.h> 18 #include <string.h> // strlen 17 19 #include <unistd.h> // _exit, getpid 20 #include <signal.h> 18 21 extern "C" { 19 22 #include <dlfcn.h> // dlopen, dlsym … … 21 24 } 22 25 26 #include "bits/debug.hfa" 23 27 #include "bits/defs.hfa" 24 28 #include "bits/signal.hfa" // sigHandler_? … … 36 40 37 41 typedef void (* generic_fptr_t)(void); 38 39 42 static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) { 43 const char * error; 44 40 45 union { generic_fptr_t fptr; void * ptr; } originalFunc; 41 46 42 47 #if defined( _GNU_SOURCE ) 43 if ( version ) { 44 originalFunc.ptr = dlvsym( library, symbol, version ); 45 } else { 48 if ( version ) { 49 originalFunc.ptr = dlvsym( library, symbol, version ); 50 } else { 51 originalFunc.ptr = dlsym( library, symbol ); 52 } 53 #else 46 54 originalFunc.ptr = dlsym( library, symbol ); 55 #endif // _GNU_SOURCE 56 57 error = dlerror(); 58 if ( error ) abort( "interpose_symbol : internal error, %s\n", error ); 59 60 return originalFunc.fptr; 61 } 62 63 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) { 64 const char * error; 65 66 static void * library; 67 static void * pthread_library; 68 if ( ! library ) { 69 #if defined( RTLD_NEXT ) 70 library = RTLD_NEXT; 71 #else 72 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 73 library = dlopen( "libc.so.6", RTLD_LAZY ); 74 error = dlerror(); 75 if ( error ) { 76 abort( "interpose_symbol : failed to open libc, %s\n", error ); 77 } 78 #endif 47 79 } // if 48 #else 49 originalFunc.ptr = dlsym( library, symbol ); 50 #endif // _GNU_SOURCE 51 52 if ( ! originalFunc.ptr ) { // == nullptr 53 abort( "interpose_symbol : internal error, %s\n", dlerror() ); 80 if ( ! pthread_library ) { 81 #if defined( RTLD_NEXT ) 82 pthread_library = RTLD_NEXT; 83 #else 84 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 85 pthread_library = dlopen( "libpthread.so", RTLD_LAZY ); 86 error = dlerror(); 87 if ( error ) { 88 abort( "interpose_symbol : failed to open libpthread, %s\n", error ); 89 } 90 #endif 54 91 } // if 55 return originalFunc.fptr; 56 } 57 58 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) { 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() ); 68 } // if 69 #endif // RTLD_NEXT 70 71 return do_interpose_symbol( library, symbol, version ); 92 93 return do_interpose_symbol(library, symbol, version); 72 94 } 73 95 … … 99 121 preload_libgcc(); 100 122 101 #pragma GCC diagnostic push102 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"123 #pragma GCC diagnostic push 124 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 103 125 INTERPOSE_LIBC( abort, version ); 104 126 INTERPOSE_LIBC( exit , version ); 105 #pragma GCC diagnostic pop127 #pragma GCC diagnostic pop 106 128 107 129 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)" in110 // sigstksz.h, as well as 8192 in sigstack.h. HOWEVER, they forgot to provide a mechanism to tell signal.h to111 // use sigstack.h rather than sigstksz.h. (I'm not happy.) By undefining _GNU_SOURCE before signal.h and112 // redefining it afterwards, you can get 8192, but then nothing works correctly inside of signal.h without113 // _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 SIGSTKSZ117 #define SIGSTKSZ 8192118 130 119 131 // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because … … 281 293 va_start( args, fmt ); 282 294 __abort( false, fmt, args ); 283 // CONTROL NEVER REACHES HERE!295 // CONTROL NEVER REACHES HERE! 284 296 va_end( args ); 285 297 } 286 298 287 299 void abort( bool signalAbort, const char fmt[], ... ) { 288 va_list args;289 va_start( args, fmt );290 __abort( signalAbort, fmt, args );291 // CONTROL NEVER REACHES HERE!292 va_end( args );300 va_list args; 301 va_start( args, fmt ); 302 __abort( signalAbort, fmt, args ); 303 // CONTROL NEVER REACHES HERE! 304 va_end( args ); 293 305 } 294 306 -
libcfa/src/interpose_thread.cfa
rb110bcc r2ed94a9 14 14 // 15 15 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 16 #include <stdarg.h> // va_start, va_end 17 #include <stdio.h> 18 #include <string.h> // strlen 21 19 #include <signal.h> 22 20 #include <pthread.h> 23 #include <signal.h>24 21 extern "C" { 25 22 #include <dlfcn.h> // dlopen, dlsym 23 #include <execinfo.h> // backtrace, messages 26 24 } 27 25 26 #include "bits/debug.hfa" 28 27 #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 libcfa_publicinterpose_symbol(36 generic_fptr_t 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 ) {41 void * library;40 ) libcfa_public { 41 const char * error; 42 42 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() ); 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 50 55 } // if 51 #endif // RTLD_NEXT52 56 53 return do_interpose_symbol( library, symbol, version);57 return do_interpose_symbol(library, symbol, version); 54 58 } 55 59 … … 79 83 #pragma GCC diagnostic push 80 84 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 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 );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 ); 91 95 #pragma GCC diagnostic pop 92 96 } -
libcfa/src/iostream.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 9 09:27:58 202313 // Update Count : 13 6112 // Last Modified On : Sat Aug 27 15:04:15 2022 13 // Update Count : 1358 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", (int)exp10 /* ambiguity with function exp10 */); \669 len2 = snprintf( &buf[len], size - len, "e%d", exp10 ); \ 670 670 } else { \ 671 671 len2 = snprintf( &buf[len], size - len, "%s", suffixes[(exp10 - SUFFIXES_START) / 3] ); \ -
libcfa/src/limits.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 17 12:25:39202313 // Update Count : 8 712 // Last Modified On : Thu Jan 5 22:27:40 2023 13 // Update Count : 84 14 14 // 15 15 16 #define _GNU_SOURCE // access long double M_*l in math.h 16 17 #include <limits.h> 17 18 #include <float.h> -
libcfa/src/stdlib.cfa
rb110bcc r2ed94a9 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 16 16:31:34 202313 // Update Count : 63 312 // Last Modified On : Fri Dec 9 15:11:30 2022 13 // Update Count : 631 14 14 // 15 15 … … 20 20 //--------------------------------------- 21 21 22 #define _XOPEN_SOURCE 600 // posix_memalign, *rand48 22 23 #include <string.h> // memcpy, memset 23 24 //#include <math.h> // fabsf, fabs, fabsl -
libcfa/src/vec/vec.hfa
rb110bcc r2ed94a9 18 18 #include <math.hfa> 19 19 20 forall(T) 21 trait fromint { 20 trait fromint(T) { 22 21 void ?{}(T&, int); 23 22 }; 24 forall(T) 25 trait zeroinit { 23 trait zeroinit(T) { 26 24 void ?{}(T&, zero_t); 27 25 }; 28 forall(T) 29 trait zero_assign { 26 trait zero_assign(T) { 30 27 T ?=?(T&, zero_t); 31 28 }; 32 forall(T) 33 trait subtract { 29 trait subtract(T) { 34 30 T ?-?(T, T); 35 31 }; 36 forall(T) 37 trait negate { 32 trait negate(T) { 38 33 T -?(T); 39 34 }; 40 forall(T) 41 trait add { 35 trait add(T) { 42 36 T ?+?(T, T); 43 37 }; 44 forall(T) 45 trait multiply { 38 trait multiply(T) { 46 39 T ?*?(T, T); 47 40 }; 48 forall(T) 49 trait divide { 41 trait divide(T) { 50 42 T ?/?(T, T); 51 43 }; 52 forall(T) 53 trait lessthan { 44 trait lessthan(T) { 54 45 int ?<?(T, T); 55 46 }; 56 forall(T) 57 trait equality { 47 trait equality(T) { 58 48 int ?==?(T, T); 59 49 }; 60 forall(T) 61 trait sqrt { 50 trait sqrt(T) { 62 51 T sqrt(T); 63 52 }; -
src/AST/Attribute.hpp
rb110bcc r2ed94a9 27 27 class Expr; 28 28 29 /// An entry in an attribute list: `__attribute__(( ... ))`30 29 class Attribute final : public Node { 31 30 public: -
src/AST/Convert.cpp
rb110bcc r2ed94a9 559 559 auto stmt = new SuspendStmt(); 560 560 stmt->then = get<CompoundStmt>().accept1( node->then ); 561 switch (node->kind) {561 switch(node->type) { 562 562 case ast::SuspendStmt::None : stmt->type = SuspendStmt::None ; break; 563 563 case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break; … … 1683 1683 GET_ACCEPT_V(attributes, Attribute), 1684 1684 { old->get_funcSpec().val }, 1685 (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs1685 old->type->isVarArgs 1686 1686 }; 1687 1687 … … 1989 1989 GET_ACCEPT_1(else_, Stmt), 1990 1990 GET_ACCEPT_V(initialization, Stmt), 1991 (old->isDoWhile) ? ast::DoWhile : ast::While,1991 old->isDoWhile, 1992 1992 GET_LABELS_V(old->labels) 1993 1993 ); … … 2131 2131 virtual void visit( const SuspendStmt * old ) override final { 2132 2132 if ( inCache( old ) ) return; 2133 ast::SuspendStmt:: Kindtype;2133 ast::SuspendStmt::Type type; 2134 2134 switch (old->type) { 2135 2135 case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break; -
src/AST/Create.cpp
rb110bcc r2ed94a9 20 20 #include "AST/Decl.hpp" 21 21 #include "AST/Type.hpp" 22 #include "Common/Iterate.hpp"23 22 24 23 namespace ast { -
src/AST/Decl.cpp
rb110bcc r2ed94a9 20 20 #include <unordered_map> 21 21 22 #include "Common/ Eval.h" // for eval22 #include "Common/utility.h" 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, ArgumentFlag isVarArgs)59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool 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( isVarArgs);63 FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(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, ArgumentFlag isVarArgs)83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool 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 );88 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs ); 89 89 for ( auto & param : this->params ) { 90 90 type->params.emplace_back( param->get_type() ); -
src/AST/Decl.hpp
rb110bcc r2ed94a9 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 5 10:42:00 202313 // Update Count : 3 512 // Last Modified On : Thu Nov 24 9:44:00 2022 13 // Update Count : 34 14 14 // 15 15 … … 122 122 }; 123 123 124 /// Function variable arguments flag125 enum ArgumentFlag { FixedArgs, VariableArgs };126 127 124 /// Object declaration `int foo()` 128 125 class FunctionDecl : public DeclWithType { … … 147 144 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 148 145 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 149 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs);146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 150 147 151 148 FunctionDecl( const CodeLocation & location, const std::string & name, … … 153 150 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 154 151 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 155 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs);152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 156 153 157 154 const Type * get_type() const override; … … 316 313 public: 317 314 bool isTyped; // isTyped indicated if the enum has a declaration like: 318 // enum (type_optional) Name {...} 315 // enum (type_optional) Name {...} 319 316 ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum 320 317 enum class EnumHiding { Visible, Hide } hide; … … 374 371 }; 375 372 376 /// Assembly declaration: `asm ... ( "..." : ... )`377 373 class AsmDecl : public Decl { 378 374 public: -
src/AST/Expr.hpp
rb110bcc r2ed94a9 254 254 }; 255 255 256 /// A name qualified by a namespace or type.257 256 class QualifiedNameExpr final : public Expr { 258 257 public: … … 260 259 std::string name; 261 260 262 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 261 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 263 262 : Expr( loc ), type_decl( d ), name( n ) {} 264 263 … … 622 621 }; 623 622 624 /// A name that refers to a generic dimension parameter.625 623 class DimensionExpr final : public Expr { 626 624 public: … … 912 910 }; 913 911 912 914 913 } 915 914 -
src/AST/Fwd.hpp
rb110bcc r2ed94a9 15 15 16 16 #pragma once 17 18 template<typename> struct bitfield;19 17 20 18 #include "AST/Node.hpp" … … 149 147 class TranslationGlobal; 150 148 151 // For the following types, only use the using type.152 namespace CV {153 struct qualifier_flags;154 using Qualifiers = bitfield<qualifier_flags>;155 149 } 156 namespace Function {157 struct spec_flags;158 using Specs = bitfield<spec_flags>;159 }160 namespace Storage {161 struct class_flags;162 using Classes = bitfield<class_flags>;163 }164 namespace Linkage {165 struct spec_flags;166 using Spec = bitfield<spec_flags>;167 }168 169 } -
src/AST/Init.hpp
rb110bcc r2ed94a9 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
rb110bcc r2ed94a9 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:09:00 202313 // Update Count : 412 // Last Modified On : Mon Oct 3 11:04:00 2022 13 // Update Count : 3 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 174 170 } // namespace ast -
src/AST/Inspect.hpp
rb110bcc r2ed94a9 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:09:00 202313 // Update Count : 312 // Last Modified On : Thr Sep 22 13:44:00 2022 13 // Update Count : 2 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 43 40 } -
src/AST/ParseNode.hpp
rb110bcc r2ed94a9 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);44 42 }; 45 43 -
src/AST/Pass.impl.hpp
rb110bcc r2ed94a9 22 22 #include "AST/TranslationUnit.hpp" 23 23 #include "AST/TypeSubstitution.hpp" 24 #include "Common/Iterate.hpp"25 24 26 25 #define VISIT_START( node ) \ … … 2042 2041 if ( __visit_children() ) { 2043 2042 maybe_accept( node, &TupleType::types ); 2043 maybe_accept( node, &TupleType::members ); 2044 2044 } 2045 2045 -
src/AST/Pass.proto.hpp
rb110bcc r2ed94a9 18 18 19 19 #include "Common/Stats/Heap.h" 20 20 21 namespace ast { 21 template<typename core_t> class Pass; 22 class TranslationUnit; 23 struct PureVisitor; 24 template<typename node_t> node_t * deepCopy( const node_t * ); 25 } 26 27 namespace ast::__pass { 28 29 typedef std::function<void( void * )> cleanup_func_t; 30 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 31 32 // boolean reference that may be null 33 // either refers to a boolean value or is null and returns true 34 class bool_ref { 35 public: 36 bool_ref() = default; 37 ~bool_ref() = default; 38 39 operator bool() { return m_ref ? *m_ref : true; } 40 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 41 42 private: 43 44 friend class visit_children_guard; 45 46 bool * set( bool * val ) { 47 bool * prev = m_ref; 48 m_ref = val; 49 return prev; 50 } 51 52 bool * m_ref = nullptr; 53 }; 54 55 // Implementation of the guard value 56 // Created inside the visit scope 57 class guard_value { 58 public: 59 /// Push onto the cleanup 60 guard_value( at_cleanup_t * at_cleanup ) { 61 if( at_cleanup ) { 62 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 63 push( std::move( func ), val ); 64 }; 65 } 66 } 67 68 ~guard_value() { 69 while( !cleanups.empty() ) { 70 auto& cleanup = cleanups.top(); 71 cleanup.func( cleanup.val ); 72 cleanups.pop(); 73 } 74 } 75 76 void push( cleanup_func_t && func, void* val ) { 77 cleanups.emplace( std::move(func), val ); 78 } 79 80 private: 81 struct cleanup_t { 82 cleanup_func_t func; 83 void * val; 84 85 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 86 }; 87 88 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups; 89 }; 90 91 // Guard structure implementation for whether or not children should be visited 92 class visit_children_guard { 93 public: 94 95 visit_children_guard( bool_ref * ref ) 96 : m_val ( true ) 97 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 98 , m_ref ( ref ) 99 {} 100 101 ~visit_children_guard() { 102 if( m_ref ) { 103 m_ref->set( m_prev ); 104 } 105 } 106 107 operator bool() { return m_val; } 108 109 private: 110 bool m_val; 111 bool * m_prev; 112 bool_ref * m_ref; 113 }; 114 115 /// "Short hand" to check if this is a valid previsit function 116 /// Mostly used to make the static_assert look (and print) prettier 117 template<typename core_t, typename node_t> 118 struct is_valid_previsit { 119 using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) ); 120 121 static constexpr bool value = std::is_void< ret_t >::value || 122 std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value; 123 }; 124 125 /// The result is a single node. 126 template< typename node_t > 127 struct result1 { 128 bool differs = false; 129 const node_t * value = nullptr; 130 131 template< typename object_t, typename super_t, typename field_t > 132 void apply( object_t *, field_t super_t::* field ); 133 }; 134 135 /// The result is a container of statements. 136 template< template<class...> class container_t > 137 struct resultNstmt { 138 /// The delta/change on a single node. 139 struct delta { 140 ptr<Stmt> new_val; 141 ssize_t old_idx; 142 bool is_old; 143 144 delta(const Stmt * s, ssize_t i, bool old) : 145 new_val(s), old_idx(i), is_old(old) {} 146 }; 147 148 bool differs = false; 149 container_t< delta > values; 150 151 template< typename object_t, typename super_t, typename field_t > 152 void apply( object_t *, field_t super_t::* field ); 153 154 template< template<class...> class incontainer_t > 155 void take_all( incontainer_t<ptr<Stmt>> * stmts ); 156 157 template< template<class...> class incontainer_t > 158 void take_all( incontainer_t<ptr<Decl>> * decls ); 159 }; 160 161 /// The result is a container of nodes. 162 template< template<class...> class container_t, typename node_t > 163 struct resultN { 164 bool differs = false; 165 container_t<ptr<node_t>> values; 166 167 template< typename object_t, typename super_t, typename field_t > 168 void apply( object_t *, field_t super_t::* field ); 169 }; 170 171 /// Used by previsit implementation 172 /// We need to reassign the result to 'node', unless the function 173 /// returns void, then we just leave 'node' unchanged 174 template<bool is_void> 175 struct __assign; 176 177 template<> 178 struct __assign<true> { 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; 58 }; 59 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 }; 70 } 71 } 72 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 179 122 template<typename core_t, typename node_t> 180 static inline void result( core_t & core, const node_t * & node ) { 181 core.previsit( node ); 182 } 183 }; 184 185 template<> 186 struct __assign<false> { 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 187 237 template<typename core_t, typename node_t> 188 static inline void result( core_t & core, const node_t * & node ) { 189 node = core.previsit( node ); 190 assertf(node, "Previsit must not return NULL"); 191 } 192 }; 193 194 /// Used by postvisit implementation 195 /// We need to return the result unless the function 196 /// returns void, then we just return the original node 197 template<bool is_void> 198 struct __return; 199 200 template<> 201 struct __return<true> { 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 202 251 template<typename core_t, typename node_t> 203 static inline const node_t * result( core_t & core, const node_t * & node ) { 204 core.postvisit( node ); 205 return node; 206 } 207 }; 208 209 template<> 210 struct __return<false> { 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 211 255 template<typename core_t, typename node_t> 212 static inline auto result( core_t & core, const node_t * & node ) { 213 return core.postvisit( node ); 214 } 215 }; 216 217 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 218 // Deep magic (a.k.a template meta programming) to make the templated visitor work 219 // Basically the goal is to make 2 previsit 220 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 221 // 'pass.previsit( node )' that compiles will be used for that node for that type 222 // This requires that this option only compile for passes that actually define an appropriate visit. 223 // SFINAE will make sure the compilation errors in this function don't halt the build. 224 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 225 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 226 // This is needed only to eliminate the need for passes to specify any kind of handlers. 227 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 228 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 229 // the first implementation takes priority in regards to overloading. 230 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 231 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 232 template<typename core_t, typename node_t> 233 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) { 234 static_assert( 235 is_valid_previsit<core_t, node_t>::value, 236 "Previsit may not change the type of the node. It must return its paremeter or void." 237 ); 238 239 __assign< 240 std::is_void< 241 decltype( core.previsit( node ) ) 242 >::value 243 >::result( core, node ); 244 } 245 246 template<typename core_t, typename node_t> 247 static inline auto previsit( core_t &, const node_t *, long ) {} 248 249 // PostVisit : never mutates the passed pointer but may return a different node 250 template<typename core_t, typename node_t> 251 static inline auto postvisit( core_t & core, const node_t * node, int ) -> 252 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 253 { 254 return __return< 255 std::is_void< 256 decltype( core.postvisit( node ) ) 257 >::value 258 >::result( core, node ); 259 } 260 261 template<typename core_t, typename node_t> 262 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; } 263 264 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 265 // Deep magic (a.k.a template meta programming) continued 266 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 267 // from in order to get extra functionallity for example 268 // class ErrorChecker : WithShortCircuiting { ... }; 269 // Pass<ErrorChecker> checker; 270 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 271 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 272 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 273 // For several accessories, the feature is enabled by detecting that a specific field is present 274 // Use a macro the encapsulate the logic of detecting a particular field 275 // The type is not strictly enforced but does match the accessory 276 #define FIELD_PTR( name, default_type ) \ 277 template< typename core_t > \ 278 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \ 279 \ 280 template< typename core_t > \ 281 static inline default_type * name( core_t &, long ) { return nullptr; } 282 283 // List of fields and their expected types 284 FIELD_PTR( typeSubs, const ast::TypeSubstitution * ) 285 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 286 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 287 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 288 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 289 FIELD_PTR( visit_children, __pass::bool_ref ) 290 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 291 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 292 293 // Remove the macro to make sure we don't clash 294 #undef FIELD_PTR 295 296 template< typename core_t > 297 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 298 // Stats::Heap::stacktrace_push(core_t::traceId); 299 } 300 301 template< typename core_t > 302 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 303 // Stats::Heap::stacktrace_pop(); 304 } 305 306 template< typename core_t > 307 static void beginTrace(core_t &, long) {} 308 309 template< typename core_t > 310 static void endTrace(core_t &, long) {} 311 312 // Allows visitor to handle an error on top-level declarations, and possibly suppress the error. 313 // If on_error() returns false, the error will be ignored. By default, it returns true. 314 315 template< typename core_t > 316 static bool on_error (core_t &, ptr<Decl> &, long) { return true; } 317 318 template< typename core_t > 319 static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) { 320 return core.on_error(decl); 321 } 322 323 template< typename core_t, typename node_t > 324 static auto make_location_guard( core_t & core, node_t * node, int ) 325 -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) { 326 ValueGuardPtr<const CodeLocation *> guard( &core.location ); 327 core.location = &node->location; 328 return guard; 329 } 330 331 template< typename core_t, typename node_t > 332 static auto make_location_guard( core_t &, node_t *, long ) -> int { 333 return 0; 334 } 335 336 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 337 // All passes which have such functions are assumed desire this behaviour 338 // detect it using the same strategy 339 namespace scope { 340 template<typename core_t> 341 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) { 342 core.beginScope(); 343 } 344 345 template<typename core_t> 346 static inline void enter( core_t &, long ) {} 347 348 template<typename core_t> 349 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) { 350 core.endScope(); 351 } 352 353 template<typename core_t> 354 static inline void leave( core_t &, long ) {} 355 } // namespace scope 356 357 // Certain passes desire an up to date symbol table automatically 358 // detect the presence of a member name `symtab` and call all the members appropriately 359 namespace symtab { 360 // Some simple scoping rules 361 template<typename core_t> 362 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) { 363 core.symtab.enterScope(); 364 } 365 366 template<typename core_t> 367 static inline auto enter( core_t &, long ) {} 368 369 template<typename core_t> 370 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) { 371 core.symtab.leaveScope(); 372 } 373 374 template<typename core_t> 375 static inline auto leave( core_t &, long ) {} 376 377 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 378 // Create macro to condense these common patterns 379 #define SYMTAB_FUNC1( func, type ) \ 380 template<typename core_t> \ 381 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\ 382 core.symtab.func( arg ); \ 383 } \ 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; } \ 384 284 \ 385 template<typename core_t> \ 386 static inline void func( core_t &, long, type ) {} 387 388 #define SYMTAB_FUNC2( func, type1, type2 ) \ 389 template<typename core_t> \ 390 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\ 391 core.symtab.func( arg1, arg2 ); \ 392 } \ 393 \ 394 template<typename core_t> \ 395 static inline void func( core_t &, long, type1, type2 ) {} 396 397 SYMTAB_FUNC1( addId , const DeclWithType * ); 398 SYMTAB_FUNC1( addType , const NamedTypeDecl * ); 399 SYMTAB_FUNC1( addStruct , const StructDecl * ); 400 SYMTAB_FUNC1( addEnum , const EnumDecl * ); 401 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 402 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 403 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl * ); 404 405 // A few extra functions have more complicated behaviour, they are hand written 406 template<typename core_t> 407 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) { 408 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 409 for ( const auto & param : decl->params ) { 410 fwd->params.push_back( deepCopy( param.get() ) ); 411 } 412 core.symtab.addStruct( fwd ); 413 } 414 415 template<typename core_t> 416 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {} 417 418 template<typename core_t> 419 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) { 420 ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name ); 421 for ( const auto & param : decl->params ) { 422 fwd->params.push_back( deepCopy( param.get() ) ); 423 } 424 core.symtab.addUnion( fwd ); 425 } 426 427 template<typename core_t> 428 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {} 429 430 template<typename core_t> 431 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) { 432 if ( ! core.symtab.lookupStruct( str ) ) { 433 core.symtab.addStruct( str ); 434 } 435 } 436 437 template<typename core_t> 438 static inline void addStruct( core_t &, long, const std::string & ) {} 439 440 template<typename core_t> 441 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) { 442 if ( ! core.symtab.lookupUnion( str ) ) { 443 core.symtab.addUnion( str ); 444 } 445 } 446 447 template<typename core_t> 448 static inline void addUnion( core_t &, long, const std::string & ) {} 449 450 #undef SYMTAB_FUNC1 451 #undef SYMTAB_FUNC2 452 } // namespace symtab 453 454 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 455 // Detect the presence of a member name `subs` and call all members appropriately 456 namespace forall { 457 // Some simple scoping rules 458 template<typename core_t> 459 static inline auto enter( core_t & core, int, const ast::FunctionType * type ) 460 -> decltype( core.subs, void() ) { 461 if ( ! type->forall.empty() ) core.subs.beginScope(); 462 } 463 464 template<typename core_t> 465 static inline auto enter( core_t &, long, const ast::FunctionType * ) {} 466 467 template<typename core_t> 468 static inline auto leave( core_t & core, int, const ast::FunctionType * type ) 469 -> decltype( core.subs, void() ) { 470 if ( ! type->forall.empty() ) { core.subs.endScope(); } 471 } 472 473 template<typename core_t> 474 static inline auto leave( core_t &, long, const ast::FunctionType * ) {} 475 476 // Replaces a TypeInstType's base TypeDecl according to the table 477 template<typename core_t> 478 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst ) 479 -> decltype( core.subs, void() ) { 480 inst = ast::mutate_field( 481 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) ); 482 } 483 484 template<typename core_t> 485 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {} 486 } // namespace forall 487 488 // For passes that need access to the global context. Searches `translationUnit` 489 namespace translation_unit { 490 template<typename core_t> 491 static inline auto get_cptr( core_t & core, int ) 492 -> decltype( &core.translationUnit ) { 493 return &core.translationUnit; 494 } 495 496 template<typename core_t> 497 static inline const TranslationUnit ** get_cptr( core_t &, long ) { 498 return nullptr; 499 } 500 } 501 502 // For passes, usually utility passes, that have a result. 503 namespace result { 504 template<typename core_t> 505 static inline auto get( core_t & core, char ) -> decltype( core.result() ) { 506 return core.result(); 507 } 508 509 template<typename core_t> 510 static inline auto get( core_t & core, int ) -> decltype( core.result ) { 511 return core.result; 512 } 513 514 template<typename core_t> 515 static inline void get( core_t &, long ) {} 516 } 517 518 } // namespace ast::__pass 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 } // namespace forall 492 493 // For passes that need access to the global context. Sreaches `translationUnit` 494 namespace translation_unit { 495 template<typename core_t> 496 static inline auto get_cptr( core_t & core, int ) 497 -> decltype( &core.translationUnit ) { 498 return &core.translationUnit; 499 } 500 501 template<typename core_t> 502 static inline const TranslationUnit ** get_cptr( core_t &, long ) { 503 return nullptr; 504 } 505 } 506 507 // For passes, usually utility passes, that have a result. 508 namespace result { 509 template<typename core_t> 510 static inline auto get( core_t & core, char ) -> decltype( core.result() ) { 511 return core.result(); 512 } 513 514 template<typename core_t> 515 static inline auto get( core_t & core, int ) -> decltype( core.result ) { 516 return core.result; 517 } 518 519 template<typename core_t> 520 static inline void get( core_t &, long ) {} 521 } 522 } // namespace __pass 523 } // namespace ast -
src/AST/Print.cpp
rb110bcc r2ed94a9 29 29 namespace ast { 30 30 31 namespace { 32 33 template<typename C, typename... T> 34 constexpr array<C, sizeof...(T)> make_array( T&&... values ) { 35 return array<C, sizeof...(T)>{ std::forward<T>( values )... }; 36 } 37 38 namespace Names { 39 static constexpr auto FuncSpecifiers = make_array<const char*>( 40 "inline", "_Noreturn", "fortran" 41 ); 42 43 static constexpr auto StorageClasses = make_array<const char*>( 44 "extern", "static", "auto", "register", "__thread", "_Thread_local" 45 ); 46 47 static constexpr auto Qualifiers = make_array<const char*>( 48 "const", "restrict", "volatile", "mutex", "_Atomic" 49 ); 50 } 51 52 template<typename bits_t, size_t N> 53 void print( ostream & os, const bits_t & bits, 54 const array<const char *, N> & names ) { 55 if ( !bits.any() ) return; 56 for ( size_t i = 0 ; i < N ; i += 1 ) { 57 if ( bits[i] ) { 58 os << names[i] << ' '; 59 } 60 } 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 }; 61 37 } 62 38 … … 104 80 static const char* Names[]; 105 81 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 106 119 void print( const std::vector<ast::Label> & labels ) { 107 120 if ( labels.empty() ) return; … … 217 230 } 218 231 219 ast::print( os,node->storage );232 print( node->storage ); 220 233 os << node->typeString(); 221 234 … … 259 272 260 273 void preprint( const ast::Type * node ) { 261 ast::print( os,node->qualifiers );274 print( node->qualifiers ); 262 275 } 263 276 … … 265 278 print( node->forall ); 266 279 print( node->assertions ); 267 ast::print( os,node->qualifiers );280 print( node->qualifiers ); 268 281 } 269 282 270 283 void preprint( const ast::BaseInstType * node ) { 271 284 print( node->attributes ); 272 ast::print( os,node->qualifiers );285 print( node->qualifiers ); 273 286 } 274 287 … … 281 294 } 282 295 283 ast::print( os,node->storage );296 print( node->storage ); 284 297 285 298 if ( node->type ) { … … 325 338 if ( ! short_mode ) printAll( node->attributes ); 326 339 327 ast::print( os, node->storage ); 328 ast::print( os, node->funcSpec ); 340 print( node->storage ); 341 print( node->funcSpec ); 342 343 329 344 330 345 if ( node->type && node->isTypeFixed ) { … … 369 384 --indent; 370 385 } 371 }372 373 if ( ! node->withExprs.empty() ) {374 // Not with a clause, but the 'with clause'.375 ++indent;376 os << " with clause" << endl << indent;377 printAll( node->withExprs );378 --indent;379 386 } 380 387 … … 739 746 virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final { 740 747 os << "Suspend Statement"; 741 switch (node-> kind) {742 case ast::SuspendStmt::None : os << " with implicit target"; break;743 case ast::SuspendStmt::Generator: os << " for generator"; break;744 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;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; 745 752 } 746 753 os << endl; … … 1620 1627 }; 1621 1628 1622 } // namespace1623 1624 1629 void print( ostream & os, const ast::Node * node, Indenter indent ) { 1625 1630 Printer printer { os, indent, false }; … … 1632 1637 } 1633 1638 1634 void print( ostream & os, Function::Specs specs ) { 1635 print( os, specs, Names::FuncSpecifiers ); 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; 1636 1645 } 1637 1638 void print( ostream & os, Storage::Classes storage ) {1639 print( os, storage, Names::StorageClasses );1640 }1641 1642 void print( ostream & os, CV::Qualifiers qualifiers ) {1643 print( os, qualifiers, Names::Qualifiers );1644 }1645 1646 } // namespace ast -
src/AST/Print.hpp
rb110bcc r2ed94a9 16 16 #pragma once 17 17 18 #include <iosfwd> 18 #include <iostream> 19 #include <utility> // for forward 19 20 20 #include "AST/ Fwd.hpp"21 #include "AST/Node.hpp" 21 22 #include "Common/Indenter.h" 22 23 23 24 namespace ast { 25 26 class Decl; 24 27 25 28 /// Print a node with the given indenter … … 41 44 } 42 45 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 50 46 } -
src/AST/Stmt.hpp
rb110bcc r2ed94a9 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 5 10:34:00 202313 // Update Count : 3 712 // Last Modified On : Wed Apr 20 14:34:00 2022 13 // Update Count : 36 14 14 // 15 15 … … 205 205 }; 206 206 207 // A while loop or a do-while loop:208 enum WhileDoKind { While, DoWhile };209 210 207 // While loop: while (...) ... else ... or do ... while (...) else ...; 211 208 class WhileDoStmt final : public Stmt { … … 215 212 ptr<Stmt> else_; 216 213 std::vector<ptr<Stmt>> inits; 217 WhileDoKindisDoWhile;214 bool isDoWhile; 218 215 219 216 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )217 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 221 218 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 222 219 223 220 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )221 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 225 222 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 226 223 … … 367 364 public: 368 365 ptr<CompoundStmt> then; 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) {}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) {} 373 370 374 371 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 397 394 }; 398 395 399 // Clause in a waitfor statement: waitfor (..., ...) ...400 396 class WaitForClause final : public StmtClause { 401 397 public: … … 458 454 MUTATE_FRIEND 459 455 }; 460 461 456 } // namespace ast 462 457 -
src/AST/SymbolTable.cpp
rb110bcc r2ed94a9 70 70 if ( baseExpr ) { 71 71 if (baseExpr->env) { 72 Expr * base = deepCopy(baseExpr);72 Expr * base = shallowCopy(baseExpr); 73 73 const TypeSubstitution * subs = baseExpr->env; 74 74 base->env = nullptr; … … 260 260 void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) { 261 261 // default handling of conflicts is to raise an error 262 addId Common( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );262 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 263 263 } 264 264 265 265 void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) { 266 266 // default handling of conflicts is to raise an error 267 addId Common( decl, OnConflict::error(), nullptr, deleter );267 addId( decl, OnConflict::error(), nullptr, deleter ); 268 268 } 269 269 … … 677 677 } 678 678 679 void SymbolTable::addId Common(680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, 681 const Expr * baseExpr, constDecl * deleter ) {679 void SymbolTable::addId( 680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 681 const Decl * deleter ) { 682 682 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 683 683 if (kind == NUMBER_OF_KINDS) { // not a special decl 684 addId ToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);684 addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter); 685 685 } 686 686 else { … … 695 695 assertf(false, "special decl with non-function type"); 696 696 } 697 addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addIdToTable( 702 const DeclWithType * decl, const std::string & lookupKey, 703 IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, 704 const Expr * baseExpr, const Decl * deleter ) { 697 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addId( 702 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 703 const Decl * deleter ) { 705 704 ++*stats().add_calls; 706 705 const std::string &name = decl->name; … … 779 778 void SymbolTable::addMembers( 780 779 const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) { 781 for ( const ptr<Decl> &decl : aggr->members ) {782 auto dwt = decl.as<DeclWithType>();783 if ( nullptr == dwt ) continue;784 addIdCommon( dwt, handleConflicts, expr );785 // Inline through unnamed struct/union members.786 if ( "" != dwt->name ) continue;787 const Type * t = dwt->get_type()->stripReferences();788 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {789 if ( ! dynamic_cast<const StructInstType *>(rty)790 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;791 ResolvExpr::Cost cost = ResolvExpr::Cost::zero;792 ast::ptr<ast::TypeSubstitution> tmp = expr->env;793 expr = mutate_field(expr, &Expr::env, nullptr);794 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost ); 795 base = mutate_field(base, &Expr::env, tmp);796 797 addMembers(798 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );780 for ( const Decl * decl : aggr->members ) { 781 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) { 782 addId( dwt, handleConflicts, expr ); 783 if ( dwt->name == "" ) { 784 const Type * t = dwt->get_type()->stripReferences(); 785 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 786 if ( ! dynamic_cast<const StructInstType *>(rty) 787 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; 788 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; 789 ast::ptr<ast::TypeSubstitution> tmp = expr->env; 790 expr = mutate_field(expr, &Expr::env, nullptr); 791 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost ); 792 base = mutate_field(base, &Expr::env, tmp); 793 794 addMembers( 795 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 796 } 797 } 799 798 } 800 799 } -
src/AST/SymbolTable.hpp
rb110bcc r2ed94a9 192 192 193 193 /// common code for addId, addDeletedId, etc. 194 void addId Common(195 const DeclWithType * decl, OnConflict handleConflicts, 196 const Expr * baseExpr = nullptr, constDecl * deleter = nullptr );194 void addId( 195 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr, 196 const Decl * deleter = nullptr ); 197 197 198 198 /// common code for addId when special decls are placed into separate tables 199 void addIdToTable( 200 const DeclWithType * decl, const std::string & lookupKey, 201 IdTable::Ptr & idTable, OnConflict handleConflicts, 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 202 201 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 203 202 204 203 /// adds all of the members of the Aggregate (addWith helper) 205 204 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/TranslationUnit.hpp
rb110bcc r2ed94a9 10 10 // Created On : Tue Jun 11 15:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hr Mar 9 16:41:00 202313 // Update Count : 212 // Last Modified On : Tue Mar 11 11:19:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 17 17 18 18 #include <map> 19 #include < list>19 #include <vector> 20 20 21 21 #include "Fwd.hpp" … … 28 28 29 29 ptr<Type> sizeType; 30 const FunctionDecl * dereference = nullptr;31 const StructDecl * dtorStruct = nullptr;32 const FunctionDecl * dtorDestroy = nullptr;30 const FunctionDecl * dereference; 31 const StructDecl * dtorStruct; 32 const FunctionDecl * dtorDestroy; 33 33 }; 34 34 -
src/AST/Type.cpp
rb110bcc r2ed94a9 10 10 // Created On : Mon May 13 15:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 15:59:00 202313 // Update Count : 712 // Last Modified On : Thu Nov 24 9:49:00 2022 13 // Update Count : 6 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) ) {} 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 } 202 220 203 221 bool isUnboundType(const Type * type) { -
src/AST/Type.hpp
rb110bcc r2ed94a9 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 15:58:00 202313 // Update Count : 912 // Last Modified On : Thu Nov 24 9:47:00 2022 13 // Update Count : 8 14 14 // 15 15 … … 265 265 }; 266 266 267 /// Function variable arguments flag 268 enum ArgumentFlag { FixedArgs, VariableArgs }; 269 267 270 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 268 271 class FunctionType final : public Type { … … 457 460 public: 458 461 std::vector<ptr<Type>> types; 462 std::vector<ptr<Decl>> members; 459 463 460 464 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} ); -
src/AST/porting.md
rb110bcc r2ed94a9 213 213 * `get_statement()` exclusively used for code location, replaced with `CodeLocation` field 214 214 215 `CaseStmt` => `CaseClause`215 `CaseStmt` 216 216 * `_isDefault` has been removed 217 217 * `isDefault` calculates value from `cond` … … 227 227 * `block` -> `body` and `finallyBlock` -> `finally` 228 228 229 `ThrowStmt` and `CatchStmt` => `CatchClause`229 `ThrowStmt` `CatchStmt` 230 230 * moved `Kind` enums to shared `ast::ExceptionKind` enum 231 231 232 `FinallyStmt` => `FinallyClause`232 `FinallyStmt` 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`283 282 284 283 `TypeInstType` -
src/CodeGen/CodeGenerator.cc
rb110bcc r2ed94a9 17 17 #include <cassert> // for assert, assertf 18 18 #include <list> // for _List_iterator, list, list<>::it... 19 #include <sstream> // for stringstream20 19 21 20 #include "AST/Decl.hpp" // for DeclWithType 22 21 #include "Common/UniqueName.h" // for UniqueName 22 #include "Common/utility.h" // for CodeLocation, toString 23 23 #include "GenType.h" // for genType 24 24 #include "InitTweak/InitTweak.h" // for getPointerBase -
src/Common/CodeLocationTools.cpp
rb110bcc r2ed94a9 208 208 209 209 struct LeafKindVisitor : public ast::Visitor { 210 LeafKind result;210 LeafKind kind; 211 211 212 212 #define VISIT(node_type, return_type) \ 213 213 const ast::return_type * visit( const ast::node_type * ) final { \ 214 result= LeafKind::node_type; \214 kind = LeafKind::node_type; \ 215 215 return nullptr; \ 216 216 } … … 222 222 223 223 LeafKind get_leaf_kind( ast::Node const * node ) { 224 return ast::Pass<LeafKindVisitor>::read( node ); 224 LeafKindVisitor visitor; 225 node->accept( visitor ); 226 return visitor.kind; 225 227 } 226 228 -
src/Common/DeclStats.cpp
rb110bcc r2ed94a9 23 23 #include <iostream> 24 24 #include <map> 25 #include <sstream>26 25 #include <unordered_map> 27 26 #include <unordered_set> -
src/Common/Eval.cc
rb110bcc r2ed94a9 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Eval.cc -- Evaluate parts of the ast at compile time.7 // utility.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 13 13 // Update Count : 119 14 14 // 15 16 #include "Eval.h"17 15 18 16 #include <utility> // for pair -
src/Common/ResolvProtoDump.cpp
rb110bcc r2ed94a9 19 19 #include <iostream> 20 20 #include <set> 21 #include <sstream>22 21 #include <unordered_set> 23 22 … … 27 26 #include "AST/Type.hpp" 28 27 #include "CodeGen/OperatorTable.h" 28 #include "Common/utility.h" 29 29 30 30 namespace { -
src/Common/SemanticError.h
rb110bcc r2ed94a9 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 25 12:01:31202313 // Update Count : 3 712 // Last Modified On : Thu Feb 2 10:59:10 2023 13 // Update Count : 36 14 14 // 15 15 … … 56 56 {"self-assign" , Severity::Warn , "self assignment of expression: %s" }, 57 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" },58 {"qualifiers-zero_t-one_t" , Severity::Warn , "questionable use of type qualifier %s with %s" }, 59 59 {"aggregate-forward-decl" , Severity::Warn , "forward declaration of nested aggregate: %s" }, 60 60 {"superfluous-decl" , Severity::Warn , "declaration does not allocate storage: %s" }, -
src/Common/module.mk
rb110bcc r2ed94a9 20 20 Common/CodeLocationTools.hpp \ 21 21 Common/CodeLocationTools.cpp \ 22 Common/CompilerError.h \ 23 Common/Debug.h \ 22 24 Common/DeclStats.hpp \ 23 25 Common/DeclStats.cpp \ 24 26 Common/ErrorObjects.h \ 25 27 Common/Eval.cc \ 26 Common/Eval.h \27 28 Common/Examine.cc \ 28 29 Common/Examine.h \ … … 30 31 Common/Indenter.h \ 31 32 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/ ToString.hpp\54 Common/UnimplementedError.h \ 55 55 Common/UniqueName.cc \ 56 56 Common/UniqueName.h \ -
src/Common/utility.h
rb110bcc r2ed94a9 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h -- General utilities used across the compiler.7 // utility.h -- 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 : Fri Feb 17 15:25:00 202313 // Update Count : 5 312 // Last Modified On : Mon Apr 25 14:26:00 2022 13 // Update Count : 51 14 14 // 15 15 … … 19 19 #include <cctype> 20 20 #include <algorithm> 21 #include <functional> 21 22 #include <iostream> 23 #include <iterator> 22 24 #include <list> 23 25 #include <memory> 26 #include <sstream> 24 27 #include <string> 25 28 #include <type_traits> 29 #include <utility> 26 30 #include <vector> 27 31 #include <cstring> // memcmp … … 45 49 return 0; 46 50 } // 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 } // if 61 } 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; 47 74 } 48 75 … … 141 168 splice( src, dst ); 142 169 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 list 193 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 element 206 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 ); 143 210 } 144 211 … … 169 236 } 170 237 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 amount 250 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 171 273 // determines if pref is a prefix of str 172 274 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 173 275 if ( pref.size() > str.size() ) return false; 174 return pref == str.substr(start, pref.size()); 175 } 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; 176 302 177 303 // ----------------------------------------------------------------------------- … … 230 356 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 231 357 }; 358 359 // ----------------------------------------------------------------------------- 360 // Helper struct and function to support 361 // for ( val : reverseIterate( container ) ) {} 362 // syntax to have a for each that iterates backwards 363 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 can 470 // 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 support 535 // for ( val : lazy_map( container1, f ) ) {} 536 // syntax to have a for each that iterates a container, mapping each element by applying f 537 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 } 232 564 233 565 // ----------------------------------------------------------------------------- … … 251 583 } // ilog2 252 584 585 // ----------------------------------------------------------------------------- 586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated 587 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 the 597 /// 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 position 607 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 position 611 ++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::less 624 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 253 629 // Local Variables: // 254 630 // tab-width: 4 // -
src/CompilationState.cc
rb110bcc r2ed94a9 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 19:12:50 202313 // Update Count : 611 // Last Modified By : Henry Xue 12 // Last Modified On : Tue Jul 20 04:27:35 2021 13 // Update Count : 5 14 14 // 15 15 … … 27 27 expraltp = false, 28 28 genericsp = false, 29 invariant = false,30 29 libcfap = false, 31 30 nopreludep = false, -
src/CompilationState.h
rb110bcc r2ed94a9 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 19:12:53 202313 // Update Count : 611 // Last Modified By : Henry Xue 12 // Last Modified On : Tue Jul 20 04:27:35 2021 13 // Update Count : 5 14 14 // 15 15 … … 26 26 expraltp, 27 27 genericsp, 28 invariant,29 28 libcfap, 30 29 nopreludep, -
src/Concurrency/Actors.cpp
rb110bcc r2ed94a9 45 45 // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass 46 46 void previsit( const StructDecl * decl ) { 47 if ( !decl->body ) return; 48 if ( decl->name == "actor" ) { 49 actorStructDecls.insert( decl ); // skip inserting fwd decl 50 *actorDecl = decl; 51 } else if( decl->name == "message" ) { 52 messageStructDecls.insert( decl ); // skip inserting fwd decl 53 *msgDecl = decl; 54 } else if( decl->name == "request" ) *requestDecl = decl; 55 else { 56 GuardValue(insideStruct); 57 insideStruct = true; 58 parentDecl = mutate( decl ); 59 } 47 GuardValue(insideStruct); 48 insideStruct = true; 49 parentDecl = mutate( decl ); 50 if( decl->name == "actor" ) *actorDecl = decl; 51 if( decl->name == "message" ) *msgDecl = decl; 52 if( decl->name == "request" ) *requestDecl = decl; 60 53 } 61 54 … … 71 64 } 72 65 73 // this collects the derived actor and message struct decl ptrs66 // this collects the valid actor and message struct decl pts 74 67 void postvisit( const StructInstType * node ) { 75 68 if ( ! *actorDecl || ! *msgDecl ) return; 76 69 if ( insideStruct && !namedDecl ) { 77 auto actorIter = actorStructDecls.find( node->aggr() ); 78 if ( actorIter != actorStructDecls.end() ) { 70 if ( node->aggr() == *actorDecl ) { 79 71 actorStructDecls.insert( parentDecl ); 80 return; 81 } 82 auto messageIter = messageStructDecls.find( node->aggr() ); 83 if ( messageIter != messageStructDecls.end() ) { 72 } else if ( node->aggr() == *msgDecl ) { 84 73 messageStructDecls.insert( parentDecl ); 85 74 } … … 191 180 }; 192 181 193 // generates the definitions of send operators for actors 194 // collects data needed for next pass that does the circular defn resolution 195 // for message send operators (via table above) 196 struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> { 182 #define __ALLOC 0 // C_TODO: complete swap to no-alloc version 183 184 struct GenReceiveDecls : public ast::WithDeclsToAdd<> { 197 185 unordered_set<const StructDecl *> & actorStructDecls; 198 186 unordered_set<const StructDecl *> & messageStructDecls; … … 203 191 FwdDeclTable & forwardDecls; 204 192 205 // generates the operator for actor message sends206 193 void postvisit( const FunctionDecl * decl ) { 207 194 // return if not of the form receive( param1, param2 ) or if it is a forward decl … … 222 209 auto messageIter = messageStructDecls.find( arg2InstType->aggr() ); 223 210 if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) { 211 212 // check that we have found all the decls we need from <actor.hfa> 213 if ( !*allocationDecl || !*requestDecl ) 214 SemanticError( decl->location, "using actors requires a header, add #include <actor.hfa>\n" ); 215 224 216 ////////////////////////////////////////////////////////////////////// 225 217 // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions 226 218 /* 227 219 static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) { 228 request new_req;220 request * new_req = alloc(); 229 221 Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive; 230 222 __receive_fn fn = (__receive_fn)my_work_fn; 231 new_req{ &receiver, &msg, fn };232 send( receiver, new_req );223 (*new_req){ &receiver, &msg, fn }; 224 send( receiver, *new_req ); 233 225 return receiver; 234 226 } 235 */ 227 */ // C_TODO: update this with new no alloc version 236 228 CompoundStmt * sendBody = new CompoundStmt( decl->location ); 237 229 230 #if __ALLOC 231 // Generates: request * new_req = alloc(); 232 sendBody->push_back( new DeclStmt( 233 decl->location, 234 new ObjectDecl( 235 decl->location, 236 "new_req", 237 new PointerType( new StructInstType( *requestDecl ) ), 238 new SingleInit( decl->location, new UntypedExpr( decl->location, new NameExpr( decl->location, "alloc" ), {} ) ) 239 ) 240 )); 241 #else 238 242 // Generates: request new_req; 239 243 sendBody->push_back( new DeclStmt( … … 245 249 ) 246 250 )); 251 #endif 247 252 248 253 // Function type is: Allocation (*)( derived_actor &, derived_msg & ) … … 263 268 )); 264 269 265 // Function type is: Allocation (*)( actor &, mess age & )270 // Function type is: Allocation (*)( actor &, messsage & ) 266 271 FunctionType * genericReceive = new FunctionType(); 267 272 genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) ); … … 269 274 genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 270 275 271 // Generates: Allocation (*fn)( actor &, mess age & ) = (Allocation (*)( actor &, message & ))my_work_fn;276 // Generates: Allocation (*fn)( actor &, messsage & ) = (Allocation (*)( actor &, messsage & ))my_work_fn; 272 277 // More readable synonymous code: 273 278 // typedef Allocation (*__receive_fn)(actor &, message &); … … 285 290 )); 286 291 292 #if __ALLOC 293 // Generates: (*new_req){ &receiver, &msg, fn }; 294 sendBody->push_back( new ExprStmt( 295 decl->location, 296 new UntypedExpr ( 297 decl->location, 298 new NameExpr( decl->location, "?{}" ), 299 { 300 new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), { new NameExpr( decl->location, "new_req" ) } ), 301 new AddressExpr( new NameExpr( decl->location, "receiver" ) ), 302 new AddressExpr( new NameExpr( decl->location, "msg" ) ), 303 new NameExpr( decl->location, "fn" ) 304 } 305 ) 306 )); 307 308 // Generates: send( receiver, *new_req ); 309 sendBody->push_back( new ExprStmt( 310 decl->location, 311 new UntypedExpr ( 312 decl->location, 313 new NameExpr( decl->location, "send" ), 314 { 315 { 316 new NameExpr( decl->location, "receiver" ), 317 new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), { new NameExpr( decl->location, "new_req" ) } ) 318 } 319 } 320 ) 321 )); 322 #else 287 323 // Generates: new_req{ &receiver, &msg, fn }; 288 324 sendBody->push_back( new ExprStmt( … … 314 350 ) 315 351 )); 352 #endif 316 353 317 354 // Generates: return receiver; … … 321 358 FunctionDecl * sendOperatorFunction = new FunctionDecl( 322 359 decl->location, 323 "? <<?",360 "?|?", 324 361 {}, // forall 325 362 { … … 351 388 // forward decls to resolve use before decl problem for '|' routines 352 389 forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) ); 390 // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) ); 353 391 354 392 sendOperatorFunction->stmts = sendBody; … … 358 396 359 397 public: 360 Gen FuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,398 GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 361 399 const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl, 362 400 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), … … 364 402 }; 365 403 366 367 // separate pass is needed since this pass resolves circular defn issues 368 // generates the forward declarations of the send operator for actor routines 369 struct FwdDeclOperator : public ast::WithDeclsToAdd<> { 404 struct GenFwdDecls : public ast::WithDeclsToAdd<> { 370 405 unordered_set<const StructDecl *> & actorStructDecls; 371 406 unordered_set<const StructDecl *> & messageStructDecls; 372 407 FwdDeclTable & forwardDecls; 373 408 374 // handles forward declaring the message operator375 409 void postvisit( const StructDecl * decl ) { 376 410 list<FunctionDecl *> toAddAfter; … … 399 433 400 434 public: 401 FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 402 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {} 435 GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 436 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), 437 forwardDecls(forwardDecls) {} 403 438 }; 404 439 … … 426 461 Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 427 462 allocationDecl, actorDecl, msgDecl ); 428 429 // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass 430 if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr ) 431 return; 432 463 433 464 // second pass locates all receive() routines that overload the generic receive fn 434 465 // it then generates the appropriate operator '|' send routines for the receive routines 435 Pass<Gen FuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,466 Pass<GenReceiveDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 436 467 allocationDecl, actorDecl, msgDecl, forwardDecls ); 437 468 438 469 // The third pass forward declares operator '|' send routines 439 Pass< FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );470 Pass<GenFwdDecls>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls ); 440 471 } 441 472 -
src/Concurrency/Actors.hpp
rb110bcc r2ed94a9 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Actors.hpp-- Implement concurrency constructs from their keywords.7 // Keywords.h -- Implement concurrency constructs from their keywords. 8 8 // 9 9 // Author : Colby Parsons -
src/Concurrency/KeywordsNew.cpp
rb110bcc r2ed94a9 779 779 780 780 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 781 switch ( stmt-> kind) {781 switch ( stmt->type ) { 782 782 case ast::SuspendStmt::None: 783 783 // Use the context to determain the implicit target. -
src/ControlStruct/ExceptDeclNew.cpp
rb110bcc r2ed94a9 15 15 16 16 #include "ExceptDecl.h" 17 18 #include <sstream>19 17 20 18 #include "AST/Decl.hpp" -
src/ControlStruct/ExceptTranslateNew.cpp
rb110bcc r2ed94a9 314 314 nullptr, 315 315 ast::Storage::Classes{}, 316 ast::Linkage::Cforall, 317 {}, 318 { ast::Function::Inline } 316 ast::Linkage::Cforall 319 317 ); 320 318 } -
src/ControlStruct/MLEMutator.cc
rb110bcc r2ed94a9 25 25 #include <memory> // for allocator_traits<>::value_... 26 26 27 #include "Common/ ToString.hpp" // for toString27 #include "Common/utility.h" // for toString, operator+ 28 28 #include "ControlStruct/LabelGenerator.h" // for LabelGenerator 29 29 #include "MLEMutator.h" -
src/GenPoly/Box.cc
rb110bcc r2ed94a9 31 31 #include "Common/SemanticError.h" // for SemanticError 32 32 #include "Common/UniqueName.h" // for UniqueName 33 #include "Common/ ToString.hpp" // for toCString33 #include "Common/utility.h" // for toString 34 34 #include "FindFunction.h" // for findFunction, findAndReplace... 35 35 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_i... … … 80 80 CallAdapter(); 81 81 82 void premutate( Declaration * declaration );83 82 void premutate( FunctionDecl * functionDecl ); 84 83 void premutate( TypeDecl * typeDecl ); … … 455 454 456 455 CallAdapter::CallAdapter() : tempNamer( "_temp" ) {} 457 458 void CallAdapter::premutate( Declaration * ) {459 // Prevent type declaration information from leaking out.460 GuardScope( scopeTyVars );461 }462 456 463 457 void CallAdapter::premutate( FunctionDecl *functionDecl ) { -
src/GenPoly/FindFunction.cc
rb110bcc r2ed94a9 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 : Fri Oct 7 17:05:20 202213 // Update Count : 711 // Last Modified By : Rob Schluntz 12 // Last Modified On : Fri Feb 05 12:22:20 2016 13 // Update Count : 6 14 14 // 15 15 … … 18 18 #include <utility> // for pair 19 19 20 #include "AST/Pass.hpp" // for Pass21 #include "AST/Type.hpp"22 20 #include "Common/PassVisitor.h" // for PassVisitor 23 21 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::iterator … … 91 89 handleForall( pointerType->get_forall() ); 92 90 } 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 } // if130 } // for131 }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 } // if150 } // if151 return ret;152 }153 154 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {155 GuardScope( typeVars );156 //handleForall( type->forall );157 }158 159 } // namespace160 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 183 91 } // namespace GenPoly 184 92 -
src/GenPoly/FindFunction.h
rb110bcc r2ed94a9 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 : Fri Oct 7 10:30:00 202213 // Update Count : 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:23:36 2017 13 // Update Count : 2 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 45 32 } // namespace GenPoly 46 33 -
src/GenPoly/GenPoly.cc
rb110bcc r2ed94a9 275 275 } 276 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 }284 285 277 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) { 286 278 // if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) { … … 327 319 return 0; 328 320 } 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 }340 321 341 322 Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) { … … 815 796 } 816 797 817 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {818 typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );819 }820 821 798 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) { 822 typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );799 typeVars.insert( *type, ast::TypeData( type->base ) ); 823 800 } 824 801 … … 845 822 } 846 823 847 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {848 for ( auto & typeDecl : decl->type_params ) {849 addToTypeVarMap( typeDecl, typeVars );850 }851 }852 853 824 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) { 854 825 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) { -
src/GenPoly/GenPoly.h
rb110bcc r2ed94a9 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 );114 113 115 114 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 116 115 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ); 117 116 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ); 118 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );119 117 120 118 /// Prints type variable map -
src/GenPoly/Lvalue.cc
rb110bcc r2ed94a9 17 17 #include <string> // for string 18 18 19 #include "Common/ToString.hpp" // for toCString20 19 #include "Common/UniqueName.h" 21 20 #include "Common/PassVisitor.h" -
src/GenPoly/LvalueNew.cpp
rb110bcc r2ed94a9 25 25 #include "AST/Pass.hpp" 26 26 #include "Common/SemanticError.h" // for SemanticWarning 27 #include "Common/ToString.hpp" // for toCString28 27 #include "Common/UniqueName.h" // for UniqueName 29 28 #include "GenPoly/GenPoly.h" // for genFunctionType -
src/InitTweak/FixInit.cc
rb110bcc r2ed94a9 32 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 33 33 #include "Common/SemanticError.h" // for SemanticError 34 #include "Common/ToString.hpp" // for toCString35 34 #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 … … 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 1235 1241 template< typename... Params > 1236 1242 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1237 SemanticErrorException err( loc, toString( params... ) ); 1238 errors.append( err ); 1243 // toggle warnings vs. errors here. 1244 // warn( params... ); 1245 error( *this, loc, params... ); 1239 1246 } 1240 1247 -
src/InitTweak/FixInitNew.cpp
rb110bcc r2ed94a9 14 14 #include <utility> // for pair 15 15 16 #include "AST/DeclReplacer.hpp"17 #include "AST/Expr.hpp"18 16 #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"24 17 #include "CodeGen/GenType.h" // for genPrettyType 25 18 #include "CodeGen/OperatorTable.h" 19 #include "Common/CodeLocationTools.hpp" 26 20 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 27 21 #include "Common/SemanticError.h" // for SemanticError 28 #include "Common/ToString.hpp" // for toCString29 22 #include "Common/UniqueName.h" // for UniqueName 23 #include "Common/utility.h" // for CodeLocation, ValueGuard, toSt... 30 24 #include "FixGlobalInit.h" // for fixGlobalInit 31 25 #include "GenInit.h" // for genCtorDtor … … 34 28 #include "ResolvExpr/Unify.h" // for typesCompatible 35 29 #include "SymTab/Autogen.h" // for genImplicitCall 36 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall37 30 #include "SymTab/Indexer.h" // for Indexer 38 31 #include "SymTab/Mangler.h" // for Mangler … … 52 45 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy 53 46 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 54 55 extern bool ctordtorp; // print all debug 55 56 extern bool ctorp; // print ctor debug … … 62 63 namespace InitTweak { 63 64 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::Cforall90 );91 return new ast::FunctionDecl( loc,92 fname,93 std::move(typeParams),94 {dstParam},95 {},96 new ast::CompoundStmt(loc),97 {},98 ast::Linkage::Cforall99 );100 }101 102 65 struct SelfAssignChecker { 103 66 void previsit( const ast::ApplicationExpr * appExpr ); … … 144 107 private: 145 108 /// hack to implement WithTypeSubstitution while conforming to mutation safety. 146 ast::TypeSubstitution * env = nullptr;147 bool envModified = false;109 ast::TypeSubstitution * env; 110 bool envModified; 148 111 }; 149 112 … … 158 121 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 159 122 160 protected:123 protected: 161 124 ObjectSet curVars; 162 125 }; … … 239 202 240 203 SemanticErrorException errors; 241 private:204 private: 242 205 template< typename... Params > 243 206 void emit( CodeLocation, const Params &... params ); … … 325 288 static UniqueName dtorNamer( "__cleanup_dtor" ); 326 289 std::string name = dtorNamer.newName(); 327 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );290 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false ); 328 291 stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) ); 329 292 … … 559 522 { 560 523 static UniqueName tempNamer("_tmp_cp"); 524 assert( env ); 561 525 const CodeLocation loc = impCpCtorExpr->location; 562 526 // CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; ) … … 570 534 571 535 // xxx - this originally mutates arg->result in place. is it correct? 572 assert( env );573 536 result = env->applyFree( result.get() ).node; 574 537 auto mutResult = result.get_and_mutate(); … … 1117 1080 void InsertDtors::previsit( const ast::BranchStmt * stmt ) { 1118 1081 switch( stmt->kind ) { 1119 case ast::BranchStmt::Continue:1120 case ast::BranchStmt::Break:1082 case ast::BranchStmt::Continue: 1083 case ast::BranchStmt::Break: 1121 1084 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 1122 1085 // always be empty), but it serves as a small sanity check. 1123 case ast::BranchStmt::Goto:1086 case ast::BranchStmt::Goto: 1124 1087 handleGoto( stmt ); 1125 1088 break; 1126 default:1089 default: 1127 1090 assert( false ); 1128 1091 } // switch … … 1340 1303 } 1341 1304 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 1342 1311 template< typename... Params > 1343 1312 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1344 SemanticErrorException err( loc, toString( params... ) ); 1345 errors.append( err ); 1313 // toggle warnings vs. errors here. 1314 // warn( params... ); 1315 error( *this, loc, params... ); 1346 1316 } 1347 1317 … … 1349 1319 // xxx - functions returning ast::ptr seems wrong... 1350 1320 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1351 return res.release(); 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 ); 1352 1324 } 1353 1325 -
src/InitTweak/GenInit.cc
rb110bcc r2ed94a9 31 31 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 32 32 #include "Common/SemanticError.h" // for SemanticError 33 #include "Common/ToString.hpp" // for toCString34 33 #include "Common/UniqueName.h" // for UniqueName 35 34 #include "Common/utility.h" // for ValueGuard, maybeClone … … 39 38 #include "ResolvExpr/Resolver.h" 40 39 #include "SymTab/Autogen.h" // for genImplicitCall 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall42 40 #include "SymTab/Mangler.h" // for Mangler 43 41 #include "SynTree/LinkageSpec.h" // for isOverridable, C -
src/Parser/DeclarationNode.cc
rb110bcc r2ed94a9 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 12:34:05 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thr Apr 20 11:46:00 202313 // Update Count : 1 39311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 8 17:07:00 2022 13 // Update Count : 1185 14 14 // 15 16 #include "DeclarationNode.h"17 15 18 16 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 23 21 #include <string> // for string, operator+, allocator, char... 24 22 25 #include "AST/Attribute.hpp" // for Attribute26 #include "AST/Copy.hpp" // for shallowCopy27 #include "AST/Decl.hpp" // for Decl28 #include "AST/Expr.hpp" // for Expr29 #include "AST/Print.hpp" // for print30 #include "AST/Stmt.hpp" // for AsmStmt, DirectiveStmt31 #include "AST/StorageClasses.hpp" // for Storage::Class32 #include "AST/Type.hpp" // for Type33 #include "Common/CodeLocation.h" // for CodeLocation34 #include "Common/Iterate.hpp" // for reverseIterate35 23 #include "Common/SemanticError.h" // for SemanticError 36 24 #include "Common/UniqueName.h" // for UniqueName 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 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::... 41 33 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 42 34 #include "TypedefTable.h" // for TypedefTable … … 49 41 50 42 // These must harmonize with the corresponding DeclarationNode enumerations. 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 }; 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" }; 68 50 69 51 UniqueName DeclarationNode::anonymous( "__anonymous" ); 70 52 71 extern ast::Linkage::Spec linkage; // defined in parser.yy53 extern LinkageSpec::Spec linkage; // defined in parser.yy 72 54 73 55 DeclarationNode::DeclarationNode() : … … 75 57 76 58 // variable.name = nullptr; 77 variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS;59 variable.tyClass = TypeDecl::NUMBER_OF_KINDS; 78 60 variable.assertions = nullptr; 79 61 variable.initializer = nullptr; 80 62 63 // attr.name = nullptr; 64 attr.expr = nullptr; 65 attr.type = nullptr; 66 81 67 assert.condition = nullptr; 82 68 assert.message = nullptr; … … 84 70 85 71 DeclarationNode::~DeclarationNode() { 72 // delete attr.name; 73 delete attr.expr; 74 delete attr.type; 75 86 76 // delete variable.name; 87 77 delete variable.assertions; 88 78 delete variable.initializer; 89 79 90 // delete type;80 // delete type; 91 81 delete bitfieldWidth; 92 82 … … 113 103 newnode->hasEllipsis = hasEllipsis; 114 104 newnode->linkage = linkage; 115 newnode->asmName = maybeC opy( asmName );116 newnode->attributes = attributes;105 newnode->asmName = maybeClone( asmName ); 106 cloneAll( attributes, newnode->attributes ); 117 107 newnode->initializer = maybeClone( initializer ); 118 108 newnode->extension = extension; … … 125 115 newnode->variable.initializer = maybeClone( variable.initializer ); 126 116 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 127 121 newnode->assert.condition = maybeClone( assert.condition ); 128 newnode->assert.message = maybeC opy( assert.message );122 newnode->assert.message = maybeClone( assert.message ); 129 123 return newnode; 130 124 } // DeclarationNode::clone … … 136 130 } // if 137 131 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 );132 if ( linkage != LinkageSpec::Cforall ) { 133 os << LinkageSpec::name( linkage ) << " "; 134 } // if 135 136 storageClasses.print( os ); 137 funcSpecs.print( os ); 144 138 145 139 if ( type ) { … … 160 154 } // if 161 155 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 156 for ( Attribute * attr: reverseIterate( attributes ) ) { 157 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str(); 158 } // for 168 159 169 160 os << endl; … … 177 168 } 178 169 179 DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {170 DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) { 180 171 DeclarationNode * newnode = new DeclarationNode; 181 172 newnode->storageClasses = sc; … … 183 174 } // DeclarationNode::newStorageClass 184 175 185 DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) {176 DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) { 186 177 DeclarationNode * newnode = new DeclarationNode; 187 178 newnode->funcSpecs = fs; … … 189 180 } // DeclarationNode::newFuncSpecifier 190 181 191 DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) {182 DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) { 192 183 DeclarationNode * newnode = new DeclarationNode; 193 184 newnode->type = new TypeData(); … … 249 240 } 250 241 251 DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {242 DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) { 252 243 DeclarationNode * newnode = new DeclarationNode; 253 244 newnode->type = new TypeData( TypeData::Aggregate ); 254 245 newnode->type->aggregate.kind = kind; 255 newnode->type->aggregate.anon = name == nullptr; 256 newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 246 newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 257 247 newnode->type->aggregate.actuals = actuals; 258 248 newnode->type->aggregate.fields = fields; … … 260 250 newnode->type->aggregate.tagged = false; 261 251 newnode->type->aggregate.parent = nullptr; 252 newnode->type->aggregate.anon = name == nullptr; 262 253 return newnode; 263 254 } // DeclarationNode::newAggregate … … 266 257 DeclarationNode * newnode = new DeclarationNode; 267 258 newnode->type = new TypeData( TypeData::Enum ); 268 newnode->type->enumeration.anon = name == nullptr; 269 newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 259 newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 270 260 newnode->type->enumeration.constants = constants; 271 261 newnode->type->enumeration.body = body; 262 newnode->type->enumeration.anon = name == nullptr; 272 263 newnode->type->enumeration.typed = typed; 273 264 newnode->type->enumeration.hiding = hiding; 274 if ( base && base->type ) {265 if ( base && base->type) { 275 266 newnode->type->base = base->type; 276 267 } // if … … 278 269 return newnode; 279 270 } // DeclarationNode::newEnum 271 272 280 273 281 274 DeclarationNode * DeclarationNode::newName( const string * name ) { … … 330 323 } // DeclarationNode::newFromTypeGen 331 324 332 DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {325 DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) { 333 326 DeclarationNode * newnode = newName( name ); 334 327 newnode->type = nullptr; … … 342 335 newnode->type = new TypeData( TypeData::Aggregate ); 343 336 newnode->type->aggregate.name = name; 344 newnode->type->aggregate.kind = ast::AggregateDecl::Trait;337 newnode->type->aggregate.kind = AggregateDecl::Trait; 345 338 newnode->type->aggregate.params = params; 346 339 newnode->type->aggregate.fields = asserts; … … 352 345 newnode->type = new TypeData( TypeData::AggregateInst ); 353 346 newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate ); 354 newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait;347 newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait; 355 348 newnode->type->aggInst.aggregate->aggregate.name = name; 356 349 newnode->type->aggInst.params = params; … … 387 380 newnode->type->array.dimension = size; 388 381 newnode->type->array.isStatic = isStatic; 389 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType< ast::ConstantExpr *>() ) {382 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ConstantExpr * >() ) { 390 383 newnode->type->array.isVarLen = false; 391 384 } else { … … 457 450 DeclarationNode * newnode = new DeclarationNode; 458 451 newnode->type = nullptr; 459 std:: vector<ast::ptr<ast::Expr>> exprs;452 std::list< Expression * > exprs; 460 453 buildList( expr, exprs ); 461 newnode->attributes.push_back( 462 new ast::Attribute( *name, std::move( exprs ) ) ); 454 newnode->attributes.push_back( new Attribute( *name, exprs ) ); 463 455 delete name; 464 456 return newnode; … … 477 469 } 478 470 479 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr* message ) {471 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression * message ) { 480 472 DeclarationNode * newnode = new DeclarationNode; 481 473 newnode->assert.condition = condition; … … 484 476 } 485 477 486 static void appendError( string & dst, const string & src ) { 478 479 void appendError( string & dst, const string & src ) { 487 480 if ( src.empty() ) return; 488 481 if ( dst.empty() ) { dst = src; return; } … … 491 484 492 485 void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) { 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() ); 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 502 494 } // for 503 495 } // DeclarationNode::checkQualifiers 504 496 505 497 void DeclarationNode::checkSpecifiers( DeclarationNode * src ) { 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 } 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 537 519 } // if 538 520 … … 544 526 storageClasses |= q->storageClasses; 545 527 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 528 for ( Attribute * attr: reverseIterate( q->attributes ) ) { 529 attributes.push_front( attr->clone() ); 530 } // for 553 531 return this; 554 532 } // DeclarationNode::copySpecifiers … … 598 576 599 577 checkQualifiers( type, q->type ); 600 if ( (builtin == Zero || builtin == One) && q->type->qualifiers. any()&& error.length() == 0 ) {601 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] );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] ); 602 580 } // if 603 581 addQualifiersToType( q->type, type ); … … 620 598 } else { 621 599 switch ( dst->kind ) { 622 case TypeData::Unknown:600 case TypeData::Unknown: 623 601 src->qualifiers |= dst->qualifiers; 624 602 dst = src; 625 603 src = nullptr; 626 604 break; 627 case TypeData::Basic:605 case TypeData::Basic: 628 606 dst->qualifiers |= src->qualifiers; 629 607 if ( src->kind != TypeData::Unknown ) { … … 653 631 } // if 654 632 break; 655 default:633 default: 656 634 switch ( src->kind ) { 657 case TypeData::Aggregate:658 case TypeData::Enum:635 case TypeData::Aggregate: 636 case TypeData::Enum: 659 637 dst->base = new TypeData( TypeData::AggregateInst ); 660 638 dst->base->aggInst.aggregate = src; … … 665 643 src = nullptr; 666 644 break; 667 default:645 default: 668 646 if ( dst->forall ) { 669 647 dst->forall->appendList( src->forall ); … … 736 714 737 715 DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) { 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 } // if744 return this;716 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) { 717 if ( variable.assertions ) { 718 variable.assertions->appendList( assertions ); 719 } else { 720 variable.assertions = assertions; 721 } // if 722 return this; 745 723 } // if 746 724 747 725 assert( type ); 748 726 switch ( type->kind ) { 749 case TypeData::Symbolic:727 case TypeData::Symbolic: 750 728 if ( type->symbolic.assertions ) { 751 729 type->symbolic.assertions->appendList( assertions ); … … 754 732 } // if 755 733 break; 756 default:734 default: 757 735 assert( false ); 758 736 } // switch … … 818 796 DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) { 819 797 if ( a ) { 820 spliceBegin( attributes, a->attributes ); 798 for ( Attribute *attr: reverseIterate( a->attributes ) ) { 799 attributes.push_front( attr ); 800 } // for 821 801 a->attributes.clear(); 822 802 } // if … … 851 831 if ( type ) { 852 832 switch ( type->kind ) { 853 case TypeData::Aggregate:854 case TypeData::Enum:833 case TypeData::Aggregate: 834 case TypeData::Enum: 855 835 p->type->base = new TypeData( TypeData::AggregateInst ); 856 836 p->type->base->aggInst.aggregate = type; … … 861 841 break; 862 842 863 default:843 default: 864 844 p->type->base = type; 865 845 } // switch … … 883 863 884 864 DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) { 885 if ( ! a ) return this;865 if ( ! a ) return this; 886 866 assert( a->type->kind == TypeData::Array ); 887 867 TypeData * lastArray = findLast( a->type ); 888 868 if ( type ) { 889 869 switch ( type->kind ) { 890 case TypeData::Aggregate:891 case TypeData::Enum:870 case TypeData::Aggregate: 871 case TypeData::Enum: 892 872 lastArray->base = new TypeData( TypeData::AggregateInst ); 893 873 lastArray->base->aggInst.aggregate = type; … … 897 877 lastArray->base->qualifiers |= type->qualifiers; 898 878 break; 899 default:879 default: 900 880 lastArray->base = type; 901 881 } // switch … … 939 919 940 920 DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) { 941 assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );921 assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." ); 942 922 variable.initializer = init; 943 923 return this; … … 1003 983 } 1004 984 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 ) { 985 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) { 1089 986 SemanticErrorException errors; 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) ) {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() ) ) { 1093 990 try { 1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1096 991 bool extracted = false; 992 bool anon = false; 1097 993 if ( DeclarationNode * extr = cur->extractAggregate() ) { 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; 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; 1106 1000 1107 1001 // need to remember the cases where a declaration contains an anonymous aggregate definition 1002 extracted = true; 1108 1003 assert( extr->type ); 1109 1004 if ( extr->type->kind == TypeData::Aggregate ) { 1110 // typedef struct { int A } B is the only case? 1111 extracted_named = !extr->type->aggregate.anon; 1005 anon = extr->type->aggregate.anon; 1112 1006 } else if ( extr->type->kind == TypeData::Enum ) { 1113 // typedef enum { A } B is the only case? 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1007 // xxx - is it useful to have an implicit anonymous enum member? 1008 anon = extr->type->enumeration.anon; 1117 1009 } 1118 1010 } // if … … 1120 1012 } // if 1121 1013 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 } 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; 1142 1038 } // if 1143 *out++ = decl;1144 1039 } // if 1145 } catch ( SemanticErrorException & e ) {1040 } catch( SemanticErrorException & e ) { 1146 1041 errors.append( e ); 1147 1042 } // try … … 1154 1049 1155 1050 // currently only builds assertions, function parameters, and return values 1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {1051 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) { 1157 1052 SemanticErrorException errors; 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) ) {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() ) ) { 1161 1056 try { 1162 ast::Decl* decl = cur->build();1163 assert f( decl, "buildList: build for ast::DeclWithType.");1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {1057 Declaration * decl = cur->build(); 1058 assert( decl ); 1059 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 1165 1060 dwt->location = cur->location; 1166 1061 *out++ = dwt; 1167 } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) {1062 } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) { 1168 1063 // e.g., int foo(struct S) {} 1169 auto inst = new ast::StructInstType(agg->name );1170 auto obj = new ast::ObjectDecl( cur->location, "", inst);1171 obj->l inkage = linkage;1064 StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name ); 1065 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr ); 1066 obj->location = cur->location; 1172 1067 *out++ = obj; 1173 1068 delete agg; 1174 } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) {1069 } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) { 1175 1070 // e.g., int foo(union U) {} 1176 auto inst = new ast::UnionInstType( agg->name ); 1177 auto obj = new ast::ObjectDecl( cur->location, 1178 "", inst, nullptr, ast::Storage::Classes(), 1179 linkage ); 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; 1180 1074 *out++ = obj; 1181 } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) {1075 } else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) { 1182 1076 // e.g., int foo(enum E) {} 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 ); 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; 1191 1080 *out++ = obj; 1192 } else {1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." );1194 1081 } // if 1195 } catch ( SemanticErrorException & e ) {1082 } catch( SemanticErrorException & e ) { 1196 1083 errors.append( e ); 1197 1084 } // try … … 1203 1090 } // buildList 1204 1091 1205 void buildTypeList( const DeclarationNode * firstNode, 1206 std::vector<ast::ptr<ast::Type>> & outputList ) { 1092 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) { 1207 1093 SemanticErrorException errors; 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 ) ) { 1094 std::back_insert_iterator< std::list< Type * > > out( outputList ); 1095 const DeclarationNode * cur = firstNode; 1096 1097 while ( cur ) { 1211 1098 try { 1212 1099 * out++ = cur->buildType(); 1213 } catch ( SemanticErrorException & e ) {1100 } catch( SemanticErrorException & e ) { 1214 1101 errors.append( e ); 1215 1102 } // try 1216 } // for 1103 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1104 } // while 1217 1105 1218 1106 if ( ! errors.isEmpty() ) { … … 1221 1109 } // buildTypeList 1222 1110 1223 ast::Decl* DeclarationNode::build() const {1111 Declaration * DeclarationNode::build() const { 1224 1112 if ( ! error.empty() ) SemanticError( this, error + " in declaration of " ); 1225 1113 1226 1114 if ( asmStmt ) { 1227 auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() ); 1228 return new ast::AsmDecl( stmt->location, stmt ); 1115 return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) ); 1229 1116 } // if 1230 1117 if ( directiveStmt ) { 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 ) { 1118 return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) ); 1119 } // if 1120 1121 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) { 1236 1122 // otype is internally converted to dtype + otype parameters 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." );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." ); 1239 1125 assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." ); 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 ); 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() ); 1249 1128 return ret; 1250 1129 } // if … … 1268 1147 } // if 1269 1148 bool isDelete = initializer && initializer->get_isDelete(); 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 ); 1149 Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension ); 1281 1150 if ( isDelete ) { 1282 auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl );1151 DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl ); 1283 1152 dwt->isDeleted = true; 1284 1153 } … … 1287 1156 1288 1157 if ( assert.condition ) { 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 ); 1158 return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) ); 1292 1159 } 1293 1160 … … 1300 1167 } // if 1301 1168 if ( enumInLine ) { 1302 return new ast::InlineMemberDecl( location, 1303 *name, (ast::Type*)nullptr, storageClasses, linkage ); 1169 return new InlineMemberDecl( *name, storageClasses, linkage, nullptr ); 1304 1170 } // if 1305 1171 assertf( name, "ObjectDecl must a have name\n" ); 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 { 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 { 1320 1176 assert( type ); 1321 1177 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 } // if 1183 1322 1184 switch ( type->kind ) { 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; 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 1344 1199 return simpletypes; 1345 1200 } // switch -
src/Parser/ExpressionNode.cc
rb110bcc r2ed94a9 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 13:17:07 2015 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" 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 7 09:18:56 2021 13 // Update Count : 1077 14 // 17 15 18 16 #include <cassert> // for assert … … 23 21 #include <string> // for string, operator+, operator== 24 22 25 #include "AST/Expr.hpp" // for NameExpr26 #include "AST/Type.hpp" // for BaseType, SueInstType27 23 #include "Common/SemanticError.h" // for SemanticError 28 24 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 29 #include "DeclarationNode.h" // for DeclarationNode 30 #include "InitializerNode.h" // for InitializerNode 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 31 31 #include "parserutility.h" // for notZeroExpr 32 33 class Initializer; 32 34 33 35 using namespace std; … … 46 48 // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their 47 49 // type. 50 51 extern const Type::Qualifiers noQualifiers; // no qualifiers on constants 48 52 49 53 // static inline bool checkH( char c ) { return c == 'h' || c == 'H'; } … … 67 71 size_t end = str.length() - 1; 68 72 if ( posn == end ) { type = 3; return; } // no length after 'l' => long 69 73 70 74 string::size_type next = posn + 1; // advance to length 71 75 if ( str[next] == '3' ) { // 32 … … 118 122 if ( str[i] == '1' ) v |= 1; 119 123 i += 1; 120 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;124 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break; 121 125 v <<= 1; 122 126 } // for 123 127 } // scanbin 124 128 125 ast::Expr * build_constantInteger( 126 const CodeLocation & location, string & str ) { 127 static const ast::BasicType::Kind kind[2][6] = { 129 Expression * build_constantInteger( string & str ) { 130 static const BasicType::Kind kind[2][6] = { 128 131 // short (h) must be before char (hh) because shorter type has the longer suffix 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, },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, }, 131 134 }; 132 135 … … 138 141 string str2( "0x0" ); 139 142 unsigned long long int v, v2 = 0; // converted integral value 140 ast::Expr* ret, * ret2;143 Expression * ret, * ret2; 141 144 142 145 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128 … … 146 149 // special constants 147 150 if ( str == "0" ) { 148 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0);151 ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) ); 149 152 goto CLEANUP; 150 153 } // if 151 154 if ( str == "1" ) { 152 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1);155 ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) ); 153 156 goto CLEANUP; 154 157 } // if 158 159 string::size_type posn; 155 160 156 161 // 'u' can appear before or after length suffix … … 161 166 } else { 162 167 // At least one digit in integer constant, so safe to backup while looking for suffix. 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 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: ; 190 191 } // if 191 192 … … 195 196 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str ); 196 197 #endif // ! __SIZEOF_INT128__ 197 198 198 199 if ( str[0] == '0' ) { // radix character ? 199 200 dec = false; … … 205 206 unsigned int len = str.length(); 206 207 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str ); 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 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: ; 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 ast::ConstantExpr( location, 304 new ast::BasicType( kind[Unsigned][type] ), str, v ); 303 ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) ); 305 304 if ( Unsigned && type < 2 ) { // hh or h, less than int ? 306 305 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values. 307 ret = new ast::CastExpr( location, 308 ret, 309 new ast::BasicType( kind[Unsigned][type] ), 310 ast::ExplicitCast ); 306 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 311 307 } else if ( ltype != -1 ) { // explicit length ? 312 308 if ( ltype == 6 ) { // int128, (int128)constant 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 ); 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 ) ); 325 313 } else { // explicit length, (length_type)constant 326 ret = new ast::CastExpr( location, 327 ret, 328 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ), 329 ast::ExplicitCast ); 314 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false ); 330 315 if ( ltype == 5 ) { // pointer, intptr( (uintptr_t)constant ) 331 ret = build_func( location, 332 new ExpressionNode( 333 build_varref( location, new string( "intptr" ) ) ), 334 new ExpressionNode( ret ) ); 316 ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) ); 335 317 } // if 336 318 } // if … … 376 358 377 359 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 }, 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 }, 383 364 }; 384 365 … … 417 398 418 399 assert( 0 <= type && type < 12 ); 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 ); 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 ); 429 403 } // if 430 404 … … 441 415 } // sepString 442 416 443 ast::Expr * build_constantChar( const CodeLocation & location,string & str ) {417 Expression * build_constantChar( string & str ) { 444 418 string units; // units 445 419 sepString( str, units, '\'' ); // separate constant from units 446 420 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] ); 421 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) ); 451 422 if ( units.length() != 0 ) { 452 ret = new ast::UntypedExpr( location, 453 new ast::NameExpr( location, units ), 454 { ret } ); 423 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 455 424 } // if 456 425 … … 459 428 } // build_constantChar 460 429 461 ast::Expr * build_constantStr( 462 const CodeLocation & location, 463 string & str ) { 430 Expression * build_constantStr( string & str ) { 464 431 assert( str.length() > 0 ); 465 432 string units; // units 466 433 sepString( str, units, '"' ); // separate constant from units 467 434 468 ast::Type * strtype;435 Type * strtype; 469 436 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1 470 case 'u':437 case 'u': 471 438 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char 472 439 // lookup type of associated typedef 473 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );440 strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false ); 474 441 break; 475 case 'U':476 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );442 case 'U': 443 strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false ); 477 444 break; 478 case 'L':479 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );445 case 'L': 446 strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false ); 480 447 break; 481 Default: // char default string type482 default:483 strtype = new ast::BasicType( ast::BasicType::Char );448 Default: // char default string type 449 default: 450 strtype = new BasicType( Type::Qualifiers( ), BasicType::Char ); 484 451 } // switch 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 ); 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 ) ); 492 456 if ( units.length() != 0 ) { 493 ret = new ast::UntypedExpr( location, 494 new ast::NameExpr( location, units ), 495 { ret } ); 457 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 496 458 } // if 497 459 … … 500 462 } // build_constantStr 501 463 502 ast::Expr * build_field_name_FLOATING_FRACTIONconstant( 503 const CodeLocation & location, const string & str ) { 464 Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) { 504 465 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str ); 505 ast::Expr * ret = build_constantInteger( location, 506 *new string( str.substr(1) ) ); 466 Expression * ret = build_constantInteger( *new string( str.substr(1) ) ); 507 467 delete &str; 508 468 return ret; 509 469 } // build_field_name_FLOATING_FRACTIONconstant 510 470 511 ast::Expr * build_field_name_FLOATING_DECIMALconstant( 512 const CodeLocation & location, const string & str ) { 471 Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) { 513 472 if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str ); 514 ast::Expr * ret = build_constantInteger( 515 location, *new string( str.substr( 0, str.size()-1 ) ) ); 473 Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) ); 516 474 delete &str; 517 475 return ret; 518 476 } // build_field_name_FLOATING_DECIMALconstant 519 477 520 ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location, 521 const string & str ) { 478 Expression * build_field_name_FLOATINGconstant( const string & str ) { 522 479 // str is of the form A.B -> separate at the . and return member expression 523 480 int a, b; … … 525 482 stringstream ss( str ); 526 483 ss >> a >> dot >> b; 527 auto ret = new ast::UntypedMemberExpr( location, 528 ast::ConstantExpr::from_int( location, b ), 529 ast::ConstantExpr::from_int( location, a ) 530 ); 484 UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) ); 531 485 delete &str; 532 486 return ret; 533 487 } // build_field_name_FLOATINGconstant 534 488 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 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; 548 499 } // make_field_name_fraction_constants 549 500 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 ) ); 501 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) { 502 return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) ); 554 503 } // build_field_name_fraction_constants 555 504 556 ast::NameExpr * build_varref( const CodeLocation & location, 557 const string * name ) { 558 ast::NameExpr * expr = new ast::NameExpr( location, *name ); 505 NameExpr * build_varref( const string * name ) { 506 NameExpr * expr = new NameExpr( *name ); 559 507 delete name; 560 508 return expr; 561 509 } // build_varref 562 510 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 ); 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 ); 571 518 } 572 519 } 573 520 } 574 return new ast::QualifiedNameExpr( location,newDecl, name->name );521 return new QualifiedNameExpr( newDecl, name->name ); 575 522 } 576 523 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 ); 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 ); 581 527 } 582 528 583 ast::DimensionExpr * build_dimensionref( const CodeLocation & location, 584 const string * name ) { 585 ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name ); 529 DimensionExpr * build_dimensionref( const string * name ) { 530 DimensionExpr * expr = new DimensionExpr( *name ); 586 531 delete name; 587 532 return expr; … … 599 544 }; // OperName 600 545 601 ast::Expr * build_cast( const CodeLocation & location, 602 DeclarationNode * decl_node, 603 ExpressionNode * expr_node ) { 604 ast::Type * targetType = maybeMoveBuildType( decl_node ); 605 if ( dynamic_cast<ast::VoidType *>( targetType ) ) { 546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { 547 Type * targetType = maybeMoveBuildType( decl_node ); 548 if ( dynamic_cast< VoidType * >( targetType ) ) { 606 549 delete targetType; 607 return new ast::CastExpr( location, 608 maybeMoveBuild( expr_node ), 609 ast::ExplicitCast ); 550 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false ); 610 551 } else { 611 return new ast::CastExpr( location, 612 maybeMoveBuild( expr_node ), 613 targetType, 614 ast::ExplicitCast ); 552 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false ); 615 553 } // if 616 554 } // build_cast 617 555 618 ast::Expr * build_keyword_cast( const CodeLocation & location, 619 ast::AggregateDecl::Aggregate target, 620 ExpressionNode * expr_node ) { 621 return new ast::KeywordCastExpr( location, 622 maybeMoveBuild( expr_node ), 623 target 624 ); 556 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) { 557 return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target ); 625 558 } 626 559 627 ast::Expr * build_virtual_cast( const CodeLocation & location, 628 DeclarationNode * decl_node, 629 ExpressionNode * expr_node ) { 630 return new ast::VirtualCastExpr( location, 631 maybeMoveBuild( expr_node ), 632 maybeMoveBuildType( decl_node ) 633 ); 560 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { 561 return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) ); 634 562 } // build_virtual_cast 635 563 636 ast::Expr * build_fieldSel( const CodeLocation & location, 637 ExpressionNode * expr_node, 638 ast::Expr * member ) { 639 return new ast::UntypedMemberExpr( location, 640 member, 641 maybeMoveBuild( expr_node ) 642 ); 564 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) { 565 return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) ); 643 566 } // build_fieldSel 644 567 645 ast::Expr * build_pfieldSel( const CodeLocation & location, 646 ExpressionNode * expr_node, 647 ast::Expr * member ) { 648 auto deref = new ast::UntypedExpr( location, 649 new ast::NameExpr( location, "*?" ) 650 ); 568 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) { 569 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 651 570 deref->location = expr_node->location; 652 deref-> args.push_back( maybeMoveBuild( expr_node) );653 auto ret = new ast::UntypedMemberExpr( location,member, deref );571 deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) ); 572 UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref ); 654 573 return ret; 655 574 } // build_pfieldSel 656 575 657 ast::Expr * build_offsetOf( const CodeLocation & location, 658 DeclarationNode * decl_node, 659 ast::NameExpr * member ) { 660 ast::Expr * ret = new ast::UntypedOffsetofExpr( location, 661 maybeMoveBuildType( decl_node ), 662 member->name 663 ); 664 ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt ); 576 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) { 577 Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() ); 665 578 delete member; 666 579 return ret; 667 580 } // build_offsetOf 668 581 669 ast::Expr * build_and_or( const CodeLocation & location, 670 ExpressionNode * expr_node1, 671 ExpressionNode * expr_node2, 672 ast::LogicalFlag flag ) { 673 return new ast::LogicalExpr( location, 674 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 675 notZeroExpr( maybeMoveBuild( expr_node2 ) ), 676 flag 677 ); 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 ); 678 584 } // build_and_or 679 585 680 ast::Expr * build_unary_val( const CodeLocation & location, 681 OperKinds op, 682 ExpressionNode * expr_node ) { 683 std::vector<ast::ptr<ast::Expr>> args; 684 args.push_back( maybeMoveBuild( expr_node ) ); 685 return new ast::UntypedExpr( location, 686 new ast::NameExpr( location, OperName[ (int)op ] ), 687 std::move( args ) 688 ); 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 ); 689 590 } // build_unary_val 690 591 691 ast::Expr * build_binary_val( const CodeLocation & location, 692 OperKinds op,693 ExpressionNode * expr_node1,694 ExpressionNode * expr_node2 ) {695 std::vector<ast::ptr<ast::Expr>> args; 696 args.push_back( maybeMoveBuild( expr_node1 ) ); 697 args.push_back( maybeMoveBuild( expr_node2 ) ); 698 return new ast::UntypedExpr( location,699 new ast::NameExpr( location, OperName[ (int)op ] ),700 std::move( args )701 );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 ); 702 603 } // build_binary_val 703 604 704 ast::Expr * build_cond( const CodeLocation & location, 705 ExpressionNode * expr_node1,706 ExpressionNode * expr_node2,707 ExpressionNode * expr_node3 ) {708 return new ast::ConditionalExpr( location,709 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 710 maybeMoveBuild( expr_node2 ), 711 maybeMoveBuild( expr_node3 ) 712 );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) ); 713 614 } // build_cond 714 615 715 ast::Expr * build_tuple( const CodeLocation & location, 716 ExpressionNode * expr_node ) { 717 std::vector<ast::ptr<ast::Expr>> exprs; 616 Expression * build_tuple( ExpressionNode * expr_node ) { 617 list< Expression * > exprs; 718 618 buildMoveList( expr_node, exprs ); 719 return new ast::UntypedTupleExpr( location, std::move( exprs ) );619 return new UntypedTupleExpr( exprs );; 720 620 } // build_tuple 721 621 722 ast::Expr * build_func( const CodeLocation & location, 723 ExpressionNode * function, 724 ExpressionNode * expr_node ) { 725 std::vector<ast::ptr<ast::Expr>> args; 622 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) { 623 list< Expression * > args; 726 624 buildMoveList( expr_node, args ); 727 return new ast::UntypedExpr( location, 728 maybeMoveBuild( function ), 729 std::move( args ) 730 ); 625 return new UntypedExpr( maybeMoveBuild< Expression >(function), args ); 731 626 } // build_func 732 627 733 ast::Expr * build_compoundLiteral( const CodeLocation & location, 734 DeclarationNode * decl_node, 735 InitializerNode * kids ) { 736 // compound literal type 737 ast::Decl * newDecl = maybeBuild( decl_node ); 738 // non-sue compound-literal type 739 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) { 740 return new ast::CompoundLiteralExpr( location, 741 newDeclWithType->get_type(), 742 maybeMoveBuild( kids ) ); 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) ); 743 632 // these types do not have associated type information 744 } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) { 745 if ( newDeclStructDecl->body ) { 746 return new ast::CompoundLiteralExpr( location, 747 new ast::StructInstType( newDeclStructDecl ), 748 maybeMoveBuild( kids ) ); 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) ); 749 636 } else { 750 return new ast::CompoundLiteralExpr( location, 751 new ast::StructInstType( newDeclStructDecl->name ), 752 maybeMoveBuild( kids ) ); 753 } // if 754 } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl ) ) { 755 if ( newDeclUnionDecl->body ) { 756 return new ast::CompoundLiteralExpr( location, 757 new ast::UnionInstType( newDeclUnionDecl ), 758 maybeMoveBuild( kids ) ); 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) ); 759 642 } else { 760 return new ast::CompoundLiteralExpr( location, 761 new ast::UnionInstType( newDeclUnionDecl->name ), 762 maybeMoveBuild( kids ) ); 763 } // if 764 } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl ) ) { 765 if ( newDeclEnumDecl->body ) { 766 return new ast::CompoundLiteralExpr( location, 767 new ast::EnumInstType( newDeclEnumDecl ), 768 maybeMoveBuild( kids ) ); 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) ); 769 648 } else { 770 return new ast::CompoundLiteralExpr( location, 771 new ast::EnumInstType( newDeclEnumDecl->name ), 772 maybeMoveBuild( kids ) ); 649 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 773 650 } // if 774 651 } else { … … 779 656 // Local Variables: // 780 657 // tab-width: 4 // 658 // mode: c++ // 659 // compile-command: "make install" // 781 660 // End: // -
src/Parser/InitializerNode.cc
rb110bcc r2ed94a9 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:20:24 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 4 11:18:00 202313 // Update Count : 2 711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 28 23:27:20 2017 13 // Update Count : 26 14 14 // 15 16 #include "InitializerNode.h"17 15 18 16 #include <iostream> // for operator<<, ostream, basic_ostream … … 20 18 #include <string> // for operator<<, string 21 19 22 #include "AST/Expr.hpp" // for Expr 23 #include "AST/Init.hpp" // for Designator, Init, ListInit, Sing... 20 using namespace std; 21 24 22 #include "Common/SemanticError.h" // for SemanticError 25 23 #include "Common/utility.h" // for maybeBuild 26 #include "ExpressionNode.h" // for ExpressionNode 27 #include "DeclarationNode.h" // for buildList 28 29 using namespace std; 30 31 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) { 32 return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct; 33 } 24 #include "ParseNode.h" // for InitializerNode, ExpressionNode 25 #include "SynTree/Expression.h" // for Expression 26 #include "SynTree/Initializer.h" // for Initializer, ListInit, SingleInit 34 27 35 28 InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des ) … … 40 33 if ( kids ) 41 34 set_last( nullptr ); 42 } // InitializerNode::InitializerNode 35 } // InitializerNode::InitializerNode 43 36 44 37 InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des ) … … 92 85 } // InitializerNode::printOneLine 93 86 94 ast::Init* InitializerNode::build() const {87 Initializer * InitializerNode::build() const { 95 88 assertf( ! isDelete, "Should not build delete stmt InitializerNode" ); 96 89 if ( aggregate ) { 97 90 // steal designators from children 98 std:: vector<ast::ptr<ast::Designation>> designlist;91 std::list< Designation * > designlist; 99 92 InitializerNode * child = next_init(); 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 ) ) ); 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 ) ); 105 97 } // for 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 ); 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 119 106 } // if 120 107 return nullptr; -
src/Parser/ParseNode.h
rb110bcc r2ed94a9 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:28:16 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Mon Apr 3 17:55:00 202313 // Update Count : 9 4211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Nov 2 21:27:07 2022 13 // Update Count : 939 14 14 // 15 15 … … 24 24 #include <string> // for string 25 25 26 #include "AST/Expr.hpp" // for Expr, NameExpr LogicalFlag27 #include "AST/Fwd.hpp" // for ptr, Decl, DeclWithType,28 #include "AST/Stmt.hpp" // for Stmt29 26 #include "Common/CodeLocation.h" // for CodeLocation 30 27 #include "Common/SemanticError.h" // for SemanticError 31 28 #include "Common/UniqueName.h" // for UniqueName 32 #include "Common/utility.h" // for maybeClone 33 #include "Parser/parserutility.h" // for maybeBuild, maybeCopy 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::... 34 36 35 37 class Attribute; … … 38 40 class DeclarationWithType; 39 41 class Initializer; 40 class InitializerNode;41 42 class ExpressionNode; 42 43 struct StatementNode; … … 80 81 CodeLocation location = yylloc; 81 82 }; // ParseNode 83 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 list 114 InitializerNode * kids; 115 bool maybeConstructed; 116 bool isDelete; 117 }; // InitializerNode 118 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 implications 141 private: 142 bool extension = false; 143 }; // ExpressionNode 144 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 } // if 156 } 157 }; 82 158 83 159 // Must harmonize with OperName. … … 96 172 97 173 struct LabelNode { 98 std:: vector<ast::Label> labels;174 std::list< Label > labels; 99 175 }; 100 176 177 Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string 178 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 ); 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 message 219 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 attributes 259 static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement 260 static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement 261 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 functions 289 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 }; // DeclarationNode 362 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 }; // StatementNode 397 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 } // if 466 } catch( SemanticErrorException & e ) { 467 errors.append( e ); 468 } // try 469 const ParseNode * temp = (cur->get_next()); 470 cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr 471 if ( ! cur && temp ) { // non-homogeneous nodes ? 472 SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." ); 473 } // if 474 } // while 475 if ( ! errors.isEmpty() ) { 476 throw errors; 477 } // if 478 } 479 480 // in DeclarationNode.cc 481 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.cc 101 492 std::ostream & operator<<( std::ostream & out, const ParseNode * node ); 102 493 -
src/Parser/ParserTypes.h
rb110bcc r2ed94a9 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/RunParser.cpp
rb110bcc r2ed94a9 10 10 // Created On : Mon Dec 19 11:00:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 6 9:42:00 202313 // Update Count : 312 // Last Modified On : Thr Dec 22 10:18:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 20 20 #include "CodeTools/TrackLoc.h" // for fillLocations 21 21 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 22 #include "Parser/ DeclarationNode.h"// for DeclarationNode, buildList22 #include "Parser/ParseNode.h" // for DeclarationNode, buildList 23 23 #include "Parser/TypedefTable.h" // for TypedefTable 24 24 25 25 // Variables global to the parsing code. 26 ast::Linkage::Spec linkage = ast::Linkage::Cforall;26 LinkageSpec::Spec linkage = LinkageSpec::Cforall; 27 27 TypedefTable typedefTable; 28 28 DeclarationNode * parseTree = nullptr; 29 29 30 void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit ) {30 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit ) { 31 31 extern int yyparse( void ); 32 32 extern FILE * yyin; … … 46 46 47 47 ast::TranslationUnit buildUnit(void) { 48 std::vector<ast::ptr<ast::Decl>> decls; 49 buildList( parseTree, decls ); 48 std::list<Declaration *> translationUnit; 49 buildList( parseTree, translationUnit ); 50 50 51 delete parseTree; 51 52 parseTree = nullptr; 52 53 53 ast::TranslationUnit transUnit; 54 for ( auto decl : decls ) { 55 transUnit.decls.emplace_back( std::move( decl ) ); 56 } 54 // When the parse/buildList code is translated to the new ast, these 55 // fill passes (and the one after 'Hoist Type Decls') should be redundent 56 // because the code locations should already be filled. 57 CodeTools::fillLocations( translationUnit ); 58 ast::TranslationUnit transUnit = convert( std::move( translationUnit ) ); 59 forceFillCodeLocations( transUnit ); 57 60 return transUnit; 58 61 } -
src/Parser/RunParser.hpp
rb110bcc r2ed94a9 10 10 // Created On : Mon Dec 19 10:42:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Feb 16 10:08:00 202313 // Update Count : 212 // Last Modified On : Thr Dec 22 10:23:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 18 18 #include <iosfwd> // for ostream 19 19 20 #include " AST/LinkageSpec.hpp"// for Spec20 #include "SynTree/LinkageSpec.h" // for Spec 21 21 namespace ast { 22 22 class TranslationUnit; … … 29 29 /// The input file is closed when complete. Exits instead of returning on 30 30 /// error or if alwaysExit is true. 31 void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit = false );31 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit = false ); 32 32 33 33 /// Drain the internal accumulator of parsed code and build a translation -
src/Parser/StatementNode.cc
rb110bcc r2ed94a9 10 10 // Author : Rodolfo G. Esteves 11 11 // Created On : Sat May 16 14:59:41 2015 12 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 11 10:16:00 2023 14 // Update Count : 428 15 // 16 17 #include "StatementNode.h" 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Wed Feb 2 20:29:30 2022 14 // Update Count : 425 15 // 18 16 19 17 #include <cassert> // for assert, strict_dynamic_cast, assertf 18 #include <list> // for list 20 19 #include <memory> // for unique_ptr 21 20 #include <string> // for string 22 21 23 #include "AST/Label.hpp" // for Label24 #include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla...25 22 #include "Common/SemanticError.h" // for SemanticError 26 23 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 27 #include "DeclarationNode.h" // for DeclarationNode 28 #include "ExpressionNode.h" // for ExpressionNode 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 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 }49 35 50 36 StatementNode::StatementNode( DeclarationNode * decl ) { … … 52 38 DeclarationNode * agg = decl->extractAggregate(); 53 39 if ( agg ) { 54 StatementNode * nextStmt = new StatementNode( 55 new ast::DeclStmt( decl->location, maybeBuild( decl ) ) ); 40 StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) ); 56 41 set_next( nextStmt ); 57 42 if ( decl->get_next() ) { … … 66 51 agg = decl; 67 52 } // if 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 ) ) ); 53 stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) ); 71 54 } // StatementNode::StatementNode 72 55 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; 56 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 57 StatementNode * prev = this; 88 58 // find end of list and maintain previous pointer 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()) );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()) ); 92 62 prev = curr; 93 63 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev);95 64 // convert from StatementNode list to Statement list 96 std::vector<ast::ptr<ast::Stmt>> stmts; 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 66 list< Statement * > stmts; 97 67 buildMoveList( stmt, stmts ); 98 68 // splice any new Statements to end of current Statements 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(); 69 CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get()); 70 caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); 104 71 return this; 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 } 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(); 113 79 } // build_expr 114 80 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 ); 120 } // if 121 122 ast::Expr * cond = nullptr; 81 Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) { 82 if ( ctl->init != 0 ) { 83 buildMoveList( ctl->init, init ); 84 } // if 85 86 Expression * cond = nullptr; 123 87 if ( ctl->condition ) { 124 88 // compare the provided condition against 0 125 cond = notZeroExpr( maybeMoveBuild ( ctl->condition) );89 cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) ); 126 90 } else { 127 for ( ast::ptr<ast::Stmt> & stmt : inits) {91 for ( Statement * stmt : init ) { 128 92 // build the && of all of the declared variables compared against 0 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;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; 133 97 } 134 98 } … … 137 101 } // build_if_control 138 102 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 ); 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 ); 149 121 } // build_if 150 122 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; 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 ) ); 167 132 } // if 168 133 } // for 169 134 } // if 170 135 // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements 171 return new ast::SwitchStmt( location, 172 maybeMoveBuild( ctl ), std::move( aststmt ) ); 136 return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt ); 173 137 } // build_switch 174 138 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, {} ); 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 179 141 } // build_case 180 142 181 ast::CaseClause * build_default( const CodeLocation & location ) { 182 // stmt starts empty and then added to 183 return new ast::CaseClause( location, nullptr, {} ); 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 184 145 } // build_default 185 146 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 ); 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 ); 197 159 } // build_while 198 160 199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 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 200 169 // do-while cannot have declarations in the contitional, so init is always empty 201 return new ast::WhileDoStmt( location, 202 notZeroExpr( maybeMoveBuild( ctl ) ), 203 buildMoveSingle( stmt ), 204 buildMoveOptional( else_ ), 205 {}, 206 ast::DoWhile 207 ); 170 return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true ); 208 171 } // build_do_while 209 172 210 ast::Stmt * build_for( const CodeLocation & location,ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {211 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty173 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) { 174 list< Statement * > astinit; // maybe empty 212 175 buildMoveList( forctl->init, astinit ); 213 176 214 ast::Expr* astcond = nullptr; // maybe empty215 astcond = notZeroExpr( maybeMoveBuild ( forctl->condition) );216 217 ast::Expr* astincr = nullptr; // maybe empty218 astincr = maybeMoveBuild ( forctl->change);177 Expression * astcond = nullptr; // maybe empty 178 astcond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) ); 179 180 Expression * astincr = nullptr; // maybe empty 181 astincr = maybeMoveBuild< Expression >(forctl->change); 219 182 delete forctl; 220 183 221 return new ast::ForStmt( location, 222 std::move( astinit ), 223 astcond, 224 astincr, 225 buildMoveSingle( stmt ), 226 buildMoveOptional( else_ ) 227 ); 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() ); 228 192 } // build_for 229 193 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 ); 194 Statement * build_branch( BranchStmt::Type kind ) { 195 Statement * ret = new BranchStmt( "", kind ); 196 return ret; 235 197 } // build_branch 236 198 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 ); 199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) { 200 Statement * ret = new BranchStmt( * identifier, kind ); 242 201 delete identifier; // allocated by lexer 243 202 return ret; 244 203 } // build_branch 245 204 246 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) { 247 ast::Expr * expr = maybeMoveBuild( ctl ); 248 return new ast::BranchStmt( expr->location, expr ); 205 Statement * build_computedgoto( ExpressionNode * ctl ) { 206 return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 249 207 } // build_computedgoto 250 208 251 ast::Stmt * build_return( const CodeLocation & location,ExpressionNode * ctl ) {252 std::vector<ast::ptr<ast::Expr>> exps;209 Statement * build_return( ExpressionNode * ctl ) { 210 list< Expression * > exps; 253 211 buildMoveList( ctl, exps ); 254 return new ast::ReturnStmt( location, 255 exps.size() > 0 ? exps.back().release() : nullptr 256 ); 212 return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr ); 257 213 } // build_return 258 214 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; 215 Statement * build_throw( ExpressionNode * ctl ) { 216 list< Expression * > exps; 264 217 buildMoveList( ctl, exps ); 265 218 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 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 ); 219 return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr ); 275 220 } // build_throw 276 221 277 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) { 278 return build_throw_stmt( loc, ctl, ast::Resume ); 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 ); 279 227 } // build_resume 280 228 281 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) { 282 230 (void)ctl; 283 231 (void)target; … … 285 233 } // build_resume_at 286 234 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() ); 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 ); 241 } // build_try 242 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() ); 248 } // build_catch 249 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() ) ); 255 } // build_finally 256 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() ); 294 267 } 295 return new ast::TryStmt( location, 296 tryBlock, 297 std::move( aststmt ), 298 finallyBlock 299 ); 300 } // build_try 301 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 ); 309 } // build_catch 310 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 ); 317 } // build_finally 318 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_func = maybeBuild( targetExpr ); 331 clause->stmt = maybeMoveBuild( stmt ); 332 clause->cond = notZeroExpr( maybeMoveBuild( when ) ); 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 ); 333 277 334 278 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 335 279 targetExpr->set_next( nullptr ); 336 buildMoveList ( next, clause->target_args );280 buildMoveList< Expression >( next, target.arguments ); 337 281 338 282 delete targetExpr; 339 283 340 existing->clauses.insert( existing->clauses.begin(), clause ); 341 342 return existing; 284 node->clauses.push_back( WaitForStmt::Clause{ 285 target, 286 maybeMoveBuild<Statement >( stmt ), 287 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 288 }); 289 290 return node; 343 291 } // build_waitfor 344 292 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; 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; 360 325 } // build_waitfor_timeout 361 326 362 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 363 std::vector<ast::ptr<ast::Expr>> e; 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; 364 342 buildMoveList( exprs, e ); 365 ast::Stmt * s = maybeMoveBuild( stmt );366 return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );343 Statement * s = maybeMoveBuild<Statement>( stmt ); 344 return new DeclStmt( new WithStmt( e, s ) ); 367 345 } // build_with 368 346 369 ast::Stmt * build_compound( const CodeLocation & location,StatementNode * first ) {370 auto cs = new ast::CompoundStmt( location);371 buildMoveList( first, cs-> kids);347 Statement * build_compound( StatementNode * first ) { 348 CompoundStmt * cs = new CompoundStmt(); 349 buildMoveList( first, cs->get_kids() ); 372 350 return cs; 373 351 } // build_compound … … 377 355 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a 378 356 // conical form for code generation. 379 StatementNode * maybe_build_compound( const CodeLocation & location,StatementNode * first ) {357 StatementNode * maybe_build_compound( StatementNode * first ) { 380 358 // Optimization: if the control-structure statement is a compound statement, do not wrap it. 381 359 // e.g., if (...) {...} do not wrap the existing compound statement. 382 if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 383 return new StatementNode( build_compound( location, first ) ); 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 ); 384 364 } // if 385 365 return first; … … 387 367 388 368 // Question 389 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {390 std::vector<ast::ptr<ast::Expr>> out, in;391 std::vector<ast::ptr<ast::ConstantExpr>> clob;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; 392 372 393 373 buildMoveList( output, out ); 394 374 buildMoveList( input, in ); 395 375 buildMoveList( clobber, clob ); 396 return new ast::AsmStmt( location, 397 is_volatile, 398 maybeMoveBuild( instruction ), 399 std::move( out ), 400 std::move( in ), 401 std::move( clob ), 402 gotolabels ? gotolabels->labels : std::vector<ast::Label>() 403 ); 376 return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels ); 404 377 } // build_asm 405 378 406 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) { 407 auto stmt = new ast::DirectiveStmt( location, *directive ); 408 delete directive; 409 return stmt; 379 Statement * build_directive( string * directive ) { 380 return new DirectiveStmt( *directive ); 410 381 } // build_directive 411 382 412 ast::Stmt * build_mutex( const CodeLocation & location,ExpressionNode * exprs, StatementNode * stmt ) {413 std::vector<ast::ptr<ast::Expr>> expList;383 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) { 384 list< Expression * > expList; 414 385 buildMoveList( exprs, expList ); 415 ast::Stmt * body = maybeMoveBuild( stmt );416 return new ast::MutexStmt( location, body, std::move( expList ));386 Statement * body = maybeMoveBuild<Statement>( stmt ); 387 return new MutexStmt( body, expList ); 417 388 } // build_mutex 418 389 -
src/Parser/TypeData.cc
rb110bcc r2ed94a9 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:12:51 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 4 13:39:00 202313 // Update Count : 6 8011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 10 22:36:52 2022 13 // Update Count : 677 14 14 // 15 16 #include "TypeData.h"17 15 18 16 #include <cassert> // for assert 19 17 #include <ostream> // for operator<<, ostream, basic_ostream 20 18 21 #include "AST/Decl.hpp" // for AggregateDecl, ObjectDecl, TypeDe...22 #include "AST/Init.hpp" // for SingleInit, ListInit23 #include "AST/Print.hpp" // for print24 19 #include "Common/SemanticError.h" // for SemanticError 25 #include "Common/utility.h" // for splice, spliceBegin 26 #include "Parser/ExpressionNode.h" // for ExpressionNode 27 #include "Parser/StatementNode.h" // for StatementNode 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" 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 case Basic: 41 // No unique data to initialize. 42 break; 43 case Array: 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; 44 47 array.dimension = nullptr; 45 48 array.isVarLen = false; 46 49 array.isStatic = false; 47 50 break; 48 case Function: 51 case Function: 52 // function = new Function_t; 49 53 function.params = nullptr; 50 54 function.idList = nullptr; … … 53 57 function.withExprs = nullptr; 54 58 break; 55 case Enum: 59 // Enum is an Aggregate, so both structures are initialized together. 60 case Enum: 61 // enumeration = new Enumeration_t; 56 62 enumeration.name = nullptr; 57 63 enumeration.constants = nullptr; … … 59 65 enumeration.anon = false; 60 66 break; 61 case Aggregate: 62 aggregate.kind = ast::AggregateDecl::NoAggregate; 67 case Aggregate: 68 // aggregate = new Aggregate_t; 69 aggregate.kind = AggregateDecl::NoAggregate; 63 70 aggregate.name = nullptr; 64 71 aggregate.params = nullptr; … … 70 77 aggregate.anon = false; 71 78 break; 72 case AggregateInst: 79 case AggregateInst: 80 // aggInst = new AggInst_t; 73 81 aggInst.aggregate = nullptr; 74 82 aggInst.params = nullptr; 75 83 aggInst.hoistType = false; 76 84 break; 77 case Symbolic: 78 case SymbolicInst: 85 case Symbolic: 86 case SymbolicInst: 87 // symbolic = new Symbolic_t; 79 88 symbolic.name = nullptr; 80 89 symbolic.params = nullptr; … … 82 91 symbolic.assertions = nullptr; 83 92 break; 84 case Tuple: 93 case Tuple: 94 // tuple = new Tuple_t; 85 95 tuple = nullptr; 86 96 break; 87 case Typeof: 88 case Basetypeof: 97 case Typeof: 98 case Basetypeof: 99 // typeexpr = new Typeof_t; 89 100 typeexpr = nullptr; 90 101 break; 91 case Vtable:92 case Builtin:93 // No unique data to initialize.94 break;95 case Qualified:102 case Vtable: 103 break; 104 case Builtin: 105 // builtin = new Builtin_t; 106 case Qualified: 96 107 qualified.parent = nullptr; 97 108 qualified.child = nullptr; … … 106 117 107 118 switch ( kind ) { 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: 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: 117 130 delete array.dimension; 118 break; 119 case Function: 131 // delete array; 132 break; 133 case Function: 120 134 delete function.params; 121 135 delete function.idList; … … 123 137 delete function.body; 124 138 delete function.withExprs; 125 break; 126 case Aggregate: 139 // delete function; 140 break; 141 case Aggregate: 127 142 delete aggregate.name; 128 143 delete aggregate.params; 129 144 delete aggregate.actuals; 130 145 delete aggregate.fields; 131 break; 132 case AggregateInst: 146 // delete aggregate; 147 break; 148 case AggregateInst: 133 149 delete aggInst.aggregate; 134 150 delete aggInst.params; 135 break; 136 case Enum: 151 // delete aggInst; 152 break; 153 case Enum: 137 154 delete enumeration.name; 138 155 delete enumeration.constants; 139 break; 140 case Symbolic: 141 case SymbolicInst: 156 // delete enumeration; 157 break; 158 case Symbolic: 159 case SymbolicInst: 142 160 delete symbolic.name; 143 161 delete symbolic.params; 144 162 delete symbolic.actuals; 145 163 delete symbolic.assertions; 146 break; 147 case Tuple: 164 // delete symbolic; 165 break; 166 case Tuple: 167 // delete tuple->members; 148 168 delete tuple; 149 169 break; 150 case Typeof: 151 case Basetypeof: 170 case Typeof: 171 case Basetypeof: 172 // delete typeexpr->expr; 152 173 delete typeexpr; 153 174 break; 154 case Vtable: 155 case Builtin: 156 // No unique data to deconstruct. 157 break; 158 case Qualified: 175 case Vtable: 176 break; 177 case Builtin: 178 // delete builtin; 179 break; 180 case Qualified: 159 181 delete qualified.parent; 160 182 delete qualified.child; 161 break;162 183 } // switch 163 184 } // TypeData::~TypeData … … 171 192 172 193 switch ( kind ) { 173 case Unknown:174 case EnumConstant:175 case Pointer:176 case Reference:177 case GlobalScope:194 case Unknown: 195 case EnumConstant: 196 case Pointer: 197 case Reference: 198 case GlobalScope: 178 199 // nothing else to copy 179 200 break; 180 case Basic:201 case Basic: 181 202 newtype->basictype = basictype; 182 203 newtype->complextype = complextype; … … 184 205 newtype->length = length; 185 206 break; 186 case Array:207 case Array: 187 208 newtype->array.dimension = maybeClone( array.dimension ); 188 209 newtype->array.isVarLen = array.isVarLen; 189 210 newtype->array.isStatic = array.isStatic; 190 211 break; 191 case Function:212 case Function: 192 213 newtype->function.params = maybeClone( function.params ); 193 214 newtype->function.idList = maybeClone( function.idList ); … … 196 217 newtype->function.withExprs = maybeClone( function.withExprs ); 197 218 break; 198 case Aggregate:219 case Aggregate: 199 220 newtype->aggregate.kind = aggregate.kind; 200 221 newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr; … … 207 228 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr; 208 229 break; 209 case AggregateInst:230 case AggregateInst: 210 231 newtype->aggInst.aggregate = maybeClone( aggInst.aggregate ); 211 232 newtype->aggInst.params = maybeClone( aggInst.params ); 212 233 newtype->aggInst.hoistType = aggInst.hoistType; 213 234 break; 214 case Enum:235 case Enum: 215 236 newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr; 216 237 newtype->enumeration.constants = maybeClone( enumeration.constants ); … … 218 239 newtype->enumeration.anon = enumeration.anon; 219 240 break; 220 case Symbolic:221 case SymbolicInst:241 case Symbolic: 242 case SymbolicInst: 222 243 newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr; 223 244 newtype->symbolic.params = maybeClone( symbolic.params ); … … 226 247 newtype->symbolic.isTypedef = symbolic.isTypedef; 227 248 break; 228 case Tuple:249 case Tuple: 229 250 newtype->tuple = maybeClone( tuple ); 230 251 break; 231 case Typeof:232 case Basetypeof:252 case Typeof: 253 case Basetypeof: 233 254 newtype->typeexpr = maybeClone( typeexpr ); 234 255 break; 235 case Vtable:236 break; 237 case Builtin:256 case Vtable: 257 break; 258 case Builtin: 238 259 assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One ); 239 260 newtype->builtintype = builtintype; 240 261 break; 241 case Qualified:262 case Qualified: 242 263 newtype->qualified.parent = maybeClone( qualified.parent ); 243 264 newtype->qualified.child = maybeClone( qualified.child ); … … 249 270 250 271 void TypeData::print( ostream &os, int indent ) const { 251 ast::print( os, qualifiers ); 272 for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) { 273 if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' '; 274 } // for 252 275 253 276 if ( forall ) { … … 257 280 258 281 switch ( kind ) { 259 case Basic:282 case Basic: 260 283 if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " "; 261 284 if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " "; … … 263 286 if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " "; 264 287 break; 265 case Pointer:288 case Pointer: 266 289 os << "pointer "; 267 290 if ( base ) { … … 270 293 } // if 271 294 break; 272 case Reference:295 case Reference: 273 296 os << "reference "; 274 297 if ( base ) { … … 277 300 } // if 278 301 break; 279 case Array:302 case Array: 280 303 if ( array.isStatic ) { 281 304 os << "static "; … … 293 316 } // if 294 317 break; 295 case Function:318 case Function: 296 319 os << "function" << endl; 297 320 if ( function.params ) { … … 321 344 } // if 322 345 break; 323 case Aggregate:324 os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;346 case Aggregate: 347 os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl; 325 348 if ( aggregate.params ) { 326 349 os << string( indent + 2, ' ' ) << "with type parameters" << endl; … … 339 362 } // if 340 363 break; 341 case AggregateInst:364 case AggregateInst: 342 365 if ( aggInst.aggregate ) { 343 366 os << "instance of " ; … … 351 374 } // if 352 375 break; 353 case Enum:354 os << "enumeration " << *enumeration.name << endl;;376 case Enum: 377 os << "enumeration "; 355 378 if ( enumeration.constants ) { 356 379 os << "with constants" << endl; … … 365 388 } // if 366 389 break; 367 case EnumConstant:390 case EnumConstant: 368 391 os << "enumeration constant "; 369 392 break; 370 case Symbolic:393 case Symbolic: 371 394 if ( symbolic.isTypedef ) { 372 395 os << "typedef definition "; … … 388 411 } // if 389 412 break; 390 case SymbolicInst:413 case SymbolicInst: 391 414 os << *symbolic.name; 392 415 if ( symbolic.actuals ) { … … 396 419 } // if 397 420 break; 398 case Tuple:421 case Tuple: 399 422 os << "tuple "; 400 423 if ( tuple ) { … … 403 426 } // if 404 427 break; 405 case Basetypeof:428 case Basetypeof: 406 429 os << "base-"; 407 430 #if defined(__GNUC__) && __GNUC__ >= 7 … … 409 432 #endif 410 433 // FALL THROUGH 411 case Typeof:434 case Typeof: 412 435 os << "type-of expression "; 413 436 if ( typeexpr ) { … … 415 438 } // if 416 439 break; 417 case Vtable:440 case Vtable: 418 441 os << "vtable"; 419 442 break; 420 case Builtin:443 case Builtin: 421 444 os << DeclarationNode::builtinTypeNames[builtintype]; 422 445 break; 423 case GlobalScope:424 break; 425 case Qualified:446 case GlobalScope: 447 break; 448 case Qualified: 426 449 qualified.parent->print( os ); 427 450 os << "."; 428 451 qualified.child->print( os ); 429 452 break; 430 case Unknown:453 case Unknown: 431 454 os << "entity of unknown type "; 432 455 break; 433 default:456 default: 434 457 os << "internal error: TypeData::print " << kind << endl; 435 458 assert( false ); … … 439 462 const std::string * TypeData::leafName() const { 440 463 switch ( kind ) { 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: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: 455 478 assertf(false, "Tried to get leaf name from kind without a name: %d", kind); 456 479 break; 457 case Aggregate:480 case Aggregate: 458 481 return aggregate.name; 459 case Enum:482 case Enum: 460 483 return enumeration.name; 461 case Symbolic:462 case SymbolicInst:484 case Symbolic: 485 case SymbolicInst: 463 486 return symbolic.name; 464 case Qualified:487 case Qualified: 465 488 return qualified.child->leafName(); 466 489 } // switch … … 469 492 470 493 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 } 494 template< typename ForallList > 495 void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) { 496 buildList( firstNode, outputList ); 483 497 auto n = firstNode; 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 ); 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 769 525 } // for 770 526 } // buildForall 771 527 772 528 773 ast::Type * typebuild( const TypeData * td ) {529 Type * typebuild( const TypeData * td ) { 774 530 assert( td ); 775 531 switch ( td->kind ) { 776 case TypeData::Unknown:532 case TypeData::Unknown: 777 533 // fill in implicit int 778 return new ast::BasicType( 779 ast::BasicType::SignedInt, 780 buildQualifiers( td ) 781 ); 782 case TypeData::Basic: 534 return new BasicType( buildQualifiers( td ), BasicType::SignedInt ); 535 case TypeData::Basic: 783 536 return buildBasicType( td ); 784 case TypeData::Pointer:537 case TypeData::Pointer: 785 538 return buildPointer( td ); 786 case TypeData::Array:539 case TypeData::Array: 787 540 return buildArray( td ); 788 case TypeData::Reference:541 case TypeData::Reference: 789 542 return buildReference( td ); 790 case TypeData::Function:791 return buildFunction Type( td );792 case TypeData::AggregateInst:543 case TypeData::Function: 544 return buildFunction( td ); 545 case TypeData::AggregateInst: 793 546 return buildAggInst( td ); 794 case TypeData::EnumConstant:795 return new ast::EnumInstType( "", buildQualifiers( td ));796 case TypeData::SymbolicInst:547 case TypeData::EnumConstant: 548 return new EnumInstType( buildQualifiers( td ), "" ); 549 case TypeData::SymbolicInst: 797 550 return buildSymbolicInst( td ); 798 case TypeData::Tuple:551 case TypeData::Tuple: 799 552 return buildTuple( td ); 800 case TypeData::Typeof:801 case TypeData::Basetypeof:553 case TypeData::Typeof: 554 case TypeData::Basetypeof: 802 555 return buildTypeof( td ); 803 case TypeData::Vtable:556 case TypeData::Vtable: 804 557 return buildVtable( td ); 805 case TypeData::Builtin:558 case TypeData::Builtin: 806 559 switch ( td->builtintype ) { 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 ) );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 ) ); 813 566 } // switch 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: 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: 825 574 assert( false ); 826 575 } // switch … … 834 583 835 584 switch ( td->kind ) { 836 case TypeData::Aggregate:585 case TypeData::Aggregate: 837 586 if ( ! toplevel && td->aggregate.body ) { 838 587 ret = td->clone(); 839 588 } // if 840 589 break; 841 case TypeData::Enum:590 case TypeData::Enum: 842 591 if ( ! toplevel && td->enumeration.body ) { 843 592 ret = td->clone(); 844 593 } // if 845 594 break; 846 case TypeData::AggregateInst:595 case TypeData::AggregateInst: 847 596 if ( td->aggInst.aggregate ) { 848 597 ret = typeextractAggregate( td->aggInst.aggregate, false ); 849 598 } // if 850 599 break; 851 default:600 default: 852 601 if ( td->base ) { 853 602 ret = typeextractAggregate( td->base, false ); … … 858 607 859 608 860 ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {609 Type::Qualifiers buildQualifiers( const TypeData * td ) { 861 610 return td->qualifiers; 862 611 } // buildQualifiers … … 867 616 } // genTSError 868 617 869 ast::Type * buildBasicType( const TypeData * td ) {870 ast::BasicType::Kind ret;618 Type * buildBasicType( const TypeData * td ) { 619 BasicType::Kind ret; 871 620 872 621 switch ( td->basictype ) { 873 case DeclarationNode::Void:622 case DeclarationNode::Void: 874 623 if ( td->signedness != DeclarationNode::NoSignedness ) { 875 624 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 878 627 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); 879 628 } // if 880 return new ast::VoidType( buildQualifiers( td ) );881 break; 882 883 case DeclarationNode::Bool:629 return new VoidType( buildQualifiers( td ) ); 630 break; 631 632 case DeclarationNode::Bool: 884 633 if ( td->signedness != DeclarationNode::NoSignedness ) { 885 634 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 889 638 } // if 890 639 891 ret = ast::BasicType::Bool;892 break; 893 894 case DeclarationNode::Char:640 ret = BasicType::Bool; 641 break; 642 643 case DeclarationNode::Char: 895 644 // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the 896 645 // character types. The implementation shall define char to have the same range, representation, and behavior as 897 646 // either signed char or unsigned char. 898 static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };647 static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char }; 899 648 900 649 if ( td->length != DeclarationNode::NoLength ) { … … 905 654 break; 906 655 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 },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 }, 911 660 }; 912 661 913 Integral: ;662 Integral: ; 914 663 if ( td->signedness == DeclarationNode::NoSignedness ) { 915 664 const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed; … … 918 667 break; 919 668 920 case DeclarationNode::Int128:921 ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;669 case DeclarationNode::Int128: 670 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128; 922 671 if ( td->length != DeclarationNode::NoLength ) { 923 672 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); … … 925 674 break; 926 675 927 case DeclarationNode::Float:928 case DeclarationNode::Double:929 case DeclarationNode::LongDouble: // not set until below930 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, },676 case DeclarationNode::Float: 677 case DeclarationNode::Double: 678 case DeclarationNode::LongDouble: // not set until below 679 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, }, 942 691 }; 943 692 944 FloatingPoint: ;693 FloatingPoint: ; 945 694 if ( td->signedness != DeclarationNode::NoSignedness ) { 946 695 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 966 715 break; 967 716 968 case DeclarationNode::NoBasicType:717 case DeclarationNode::NoBasicType: 969 718 // No basic type in declaration => default double for Complex/Imaginary and int type for integral types 970 719 if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) { … … 975 724 const_cast<TypeData *>(td)->basictype = DeclarationNode::Int; 976 725 goto Integral; 977 default:978 assertf( false, "unknown basic type" );726 default: 727 assertf( false, "unknown basic type" ); 979 728 return nullptr; 980 729 } // switch 981 730 982 ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) ); 731 BasicType * bt = new BasicType( buildQualifiers( td ), ret ); 732 buildForall( td->forall, bt->get_forall() ); 983 733 return bt; 984 734 } // buildBasicType 985 735 986 736 987 ast::PointerType * buildPointer( const TypeData * td ) {988 ast::PointerType * pt;737 PointerType * buildPointer( const TypeData * td ) { 738 PointerType * pt; 989 739 if ( td->base ) { 990 pt = new ast::PointerType( 991 typebuild( td->base ), 992 buildQualifiers( td ) 993 ); 740 pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) ); 994 741 } else { 995 pt = new ast::PointerType( 996 new ast::BasicType( ast::BasicType::SignedInt ), 997 buildQualifiers( td ) 998 ); 742 pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 999 743 } // if 744 buildForall( td->forall, pt->get_forall() ); 1000 745 return pt; 1001 746 } // buildPointer 1002 747 1003 748 1004 ast::ArrayType * buildArray( const TypeData * td ) {1005 ast::ArrayType * at;749 ArrayType * buildArray( const TypeData * td ) { 750 ArrayType * at; 1006 751 if ( td->base ) { 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 ); 752 at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array.dimension ), 753 td->array.isVarLen, td->array.isStatic ); 1014 754 } else { 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 ); 755 at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 756 maybeBuild< Expression >( td->array.dimension ), td->array.isVarLen, td->array.isStatic ); 1022 757 } // if 758 buildForall( td->forall, at->get_forall() ); 1023 759 return at; 1024 760 } // buildArray 1025 761 1026 762 1027 ast::ReferenceType * buildReference( const TypeData * td ) {1028 ast::ReferenceType * rt;763 ReferenceType * buildReference( const TypeData * td ) { 764 ReferenceType * rt; 1029 765 if ( td->base ) { 1030 rt = new ast::ReferenceType( 1031 typebuild( td->base ), 1032 buildQualifiers( td ) 1033 ); 766 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) ); 1034 767 } else { 1035 rt = new ast::ReferenceType( 1036 new ast::BasicType( ast::BasicType::SignedInt ), 1037 buildQualifiers( td ) 1038 ); 768 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 1039 769 } // if 770 buildForall( td->forall, rt->get_forall() ); 1040 771 return rt; 1041 772 } // buildReference 1042 773 1043 774 1044 ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {775 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1045 776 assert( td->kind == TypeData::Aggregate ); 1046 ast::AggregateDecl * at;777 AggregateDecl * at; 1047 778 switch ( td->aggregate.kind ) { 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: 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: 1079 797 assert( false ); 1080 798 } // switch 1081 799 1082 buildList( td->aggregate.fields, at-> members);800 buildList( td->aggregate.fields, at->get_members() ); 1083 801 at->set_body( td->aggregate.body ); 1084 802 … … 1087 805 1088 806 1089 ast::BaseInstType * buildComAggInst( 1090 const TypeData * type, 1091 std::vector<ast::ptr<ast::Attribute>> && attributes, 1092 ast::Linkage::Spec linkage ) { 807 ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1093 808 switch ( type->kind ) { 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: 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: 1160 859 assert( false ); 1161 860 } // switch 1162 assert( false );1163 861 } // buildAggInst 1164 862 1165 863 1166 ast::BaseInstType * buildAggInst( const TypeData * td ) {864 ReferenceToType * buildAggInst( const TypeData * td ) { 1167 865 assert( td->kind == TypeData::AggregateInst ); 1168 866 1169 ast::BaseInstType * ret = nullptr; 867 // ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() ); 868 ReferenceToType * ret = nullptr; 1170 869 TypeData * type = td->aggInst.aggregate; 1171 870 switch ( type->kind ) { 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: 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: 1205 894 assert( false ); 1206 895 } // switch 1207 896 1208 ret->hoistType = td->aggInst.hoistType; 1209 buildList( td->aggInst.params, ret->params ); 897 ret->set_hoistType( td->aggInst.hoistType ); 898 buildList( td->aggInst.params, ret->get_parameters() ); 899 buildForall( td->forall, ret->get_forall() ); 1210 900 return ret; 1211 901 } // buildAggInst 1212 902 1213 903 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 ) { 904 NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) { 1220 905 assert( td->kind == TypeData::Symbolic ); 1221 ast::NamedTypeDecl * ret;906 NamedTypeDecl * ret; 1222 907 assert( td->base ); 1223 908 if ( td->symbolic.isTypedef ) { 1224 ret = new ast::TypedefDecl( 1225 td->location, 1226 name, 1227 scs, 1228 typebuild( td->base ), 1229 linkage 1230 ); 909 ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage ); 1231 910 } else { 1232 ret = new ast::TypeDecl( 1233 td->location, 1234 name, 1235 scs, 1236 typebuild( td->base ), 1237 ast::TypeDecl::Dtype, 1238 true 1239 ); 911 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); 1240 912 } // if 1241 buildList( td->symbolic.assertions, ret-> assertions);1242 splice( ret->base.get_and_mutate()->attributes, attributes );913 buildList( td->symbolic.assertions, ret->get_assertions() ); 914 ret->base->attributes.splice( ret->base->attributes.end(), attributes ); 1243 915 return ret; 1244 916 } // buildSymbolic 1245 917 1246 918 1247 ast::EnumDecl * buildEnum( 1248 const TypeData * td, 1249 std::vector<ast::ptr<ast::Attribute>> && attributes, 1250 ast::Linkage::Spec linkage ) { 919 EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1251 920 assert( td->kind == TypeData::Enum ); 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; 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; 1264 926 for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) { 1265 927 if ( cur->enumInLine ) { … … 1268 930 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 1269 931 } else if ( cur->has_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 ); 932 ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members); 933 member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) ); 1277 934 } else if ( !cur->initializer ) { 1278 if ( baseType && (!dynamic_cast< ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {935 if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isInteger())) { 1279 936 SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." ); 1280 937 } … … 1283 940 // if 1284 941 } // for 1285 ret-> body = td->enumeration.body;942 ret->set_body( td->enumeration.body ); 1286 943 return ret; 1287 944 } // buildEnum 1288 945 1289 946 1290 ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {947 TypeInstType * buildSymbolicInst( const TypeData * td ) { 1291 948 assert( td->kind == TypeData::SymbolicInst ); 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 ); 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() ); 1298 952 return ret; 1299 953 } // buildSymbolicInst 1300 954 1301 955 1302 ast::TupleType * buildTuple( const TypeData * td ) {956 TupleType * buildTuple( const TypeData * td ) { 1303 957 assert( td->kind == TypeData::Tuple ); 1304 std:: vector<ast::ptr<ast::Type>> types;958 std::list< Type * > types; 1305 959 buildTypeList( td->tuple, types ); 1306 ast::TupleType * ret = new ast::TupleType( 1307 std::move( types ), 1308 buildQualifiers( td ) 1309 ); 960 TupleType * ret = new TupleType( buildQualifiers( td ), types ); 961 buildForall( td->forall, ret->get_forall() ); 1310 962 return ret; 1311 963 } // buildTuple 1312 964 1313 965 1314 ast::TypeofType * buildTypeof( const TypeData * td ) {966 TypeofType * buildTypeof( const TypeData * td ) { 1315 967 assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof ); 1316 968 assert( td->typeexpr ); 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 ); 969 // assert( td->typeexpr->expr ); 970 return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof }; 1323 971 } // buildTypeof 1324 972 1325 973 1326 ast::VTableType * buildVtable( const TypeData * td ) {974 VTableType * buildVtable( const TypeData * td ) { 1327 975 assert( td->base ); 1328 return new ast::VTableType( 1329 typebuild( td->base ), 1330 buildQualifiers( td ) 1331 ); 976 return new VTableType{ buildQualifiers( td ), typebuild( td->base ) }; 1332 977 } // buildVtable 1333 978 1334 979 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 ) { 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 ) { 1419 981 if ( td->kind == TypeData::Function ) { 1420 982 if ( td->function.idList ) { // KR function ? … … 1422 984 } // if 1423 985 1424 return buildFunctionDecl( 1425 td, name, scs, funcSpec, linkage, 1426 asmName, std::move( attributes ) ); 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 ); 1427 992 } else if ( td->kind == TypeData::Aggregate ) { 1428 return buildAggregate( td, std::move( attributes ), linkage );993 return buildAggregate( td, attributes, linkage ); 1429 994 } else if ( td->kind == TypeData::Enum ) { 1430 return buildEnum( td, std::move( attributes ), linkage );995 return buildEnum( td, attributes, linkage ); 1431 996 } else if ( td->kind == TypeData::Symbolic ) { 1432 return buildSymbolic( td, std::move( attributes ), name, scs, linkage );997 return buildSymbolic( td, attributes, name, scs, linkage ); 1433 998 } else { 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; 999 return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName ); 1445 1000 } // if 1446 1001 return nullptr; … … 1448 1003 1449 1004 1450 ast::FunctionType * buildFunctionType( const TypeData * td ) {1005 FunctionType * buildFunction( const TypeData * td ) { 1451 1006 assert( td->kind == TypeData::Function ); 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 ); 1007 FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis ); 1008 buildList( td->function.params, ft->parameters ); 1458 1009 buildForall( td->forall, ft->forall ); 1459 1010 if ( td->base ) { 1460 1011 switch ( td->base->kind ) { 1461 case TypeData::Tuple:1462 build TypeList( td->base->tuple, ft->returns );1012 case TypeData::Tuple: 1013 buildList( td->base->tuple, ft->returnVals ); 1463 1014 break; 1464 default: 1465 ft->returns.push_back( typebuild( td->base ) ); 1466 break; 1015 default: 1016 ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) ); 1467 1017 } // switch 1468 1018 } else { 1469 ft->returns.push_back( 1470 new ast::BasicType( ast::BasicType::SignedInt ) ); 1019 ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) ); 1471 1020 } // if 1472 1021 return ft; 1473 } // buildFunction Type1022 } // buildFunction 1474 1023 1475 1024 … … 1502 1051 param->type = decl->type; // set copy declaration type to parameter type 1503 1052 decl->type = nullptr; // reset declaration type 1504 // Copy and reset attributes from declaration to parameter: 1505 splice( param->attributes, decl->attributes ); 1053 param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter 1506 1054 } // if 1507 1055 } // for -
src/Parser/TypeData.h
rb110bcc r2ed94a9 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 15:18:36 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Mar 1 10:44:00 202313 // Update Count : 20 611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 10 22:18:49 2022 13 // Update Count : 203 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 "AST/Type.hpp" // for Type 23 #include "DeclarationNode.h" // for DeclarationNode 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 24 26 25 27 struct TypeData { … … 28 30 29 31 struct Aggregate_t { 30 ast::AggregateDecl::Aggregate kind;32 AggregateDecl::Aggregate kind; 31 33 const std::string * name = nullptr; 32 34 DeclarationNode * params = nullptr; … … 35 37 bool body; 36 38 bool anon; 39 37 40 bool tagged; 38 41 const std::string * parent = nullptr; … … 91 94 DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType; 92 95 93 ast::CV::Qualifiers qualifiers;96 Type::Qualifiers qualifiers; 94 97 DeclarationNode * forall = nullptr; 95 98 … … 112 115 }; 113 116 114 ast::Type * typebuild( const TypeData * );117 Type * typebuild( const TypeData * ); 115 118 TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true ); 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 * ); 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 * ); 136 137 void buildKRFunction( const TypeData::Function_t & function ); 137 138 -
src/Parser/TypedefTable.cc
rb110bcc r2ed94a9 16 16 17 17 #include "TypedefTable.h" 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 18 #include <cassert> // for assert 19 #include <iostream> 29 20 using namespace std; 30 21 31 22 #if 0 32 23 #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 } // switch44 } // kindName45 24 #else 46 25 #define debugPrint( code ) 47 26 #endif 27 28 using namespace std; // string, iostream 29 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 } // switch 41 } // kindName 42 ); 48 43 49 44 TypedefTable::~TypedefTable() { … … 83 78 typedefTable.addToEnclosingScope( name, kind, "MTD" ); 84 79 } // if 85 } // TypedefTable::makeTypedef86 87 void TypedefTable::makeTypedef( const string & name ) {88 return makeTypedef( name, TYPEDEFname );89 80 } // TypedefTable::makeTypedef 90 81 -
src/Parser/TypedefTable.h
rb110bcc r2ed94a9 19 19 20 20 #include "Common/ScopedMap.h" // for ScopedMap 21 #include "ParserTypes.h" 22 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname 21 23 22 24 class TypedefTable { 23 25 struct Note { size_t level; bool forall; }; 24 26 typedef ScopedMap< std::string, int, Note > KindTable; 25 KindTable kindTable; 27 KindTable kindTable; 26 28 unsigned int level = 0; 27 29 public: … … 31 33 bool existsCurr( const std::string & identifier ) const; 32 34 int isKind( const std::string & identifier ) const; 33 void makeTypedef( const std::string & name, int kind ); 34 void makeTypedef( const std::string & name ); 35 void makeTypedef( const std::string & name, int kind = TYPEDEFname ); 35 36 void addToScope( const std::string & identifier, int kind, const char * ); 36 37 void addToEnclosingScope( const std::string & identifier, int kind, const char * ); -
src/Parser/lex.ll
rb110bcc r2ed94a9 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Sat Mar 25 08:09:03202313 * Update Count : 76 812 * Last Modified On : Mon Jan 30 19:03:34 2023 13 * Update Count : 767 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 DeclarationNode47 #include "ExpressionNode.h" // for LabelNode48 #include "InitializerNode.h" // for InitializerNode49 46 #include "ParseNode.h" 50 #include "ParserTypes.h" // for Token51 #include "StatementNode.h" // for CondCtl, ForCtrl52 47 #include "TypedefTable.h" 53 // This (generated) header must come late as it is missing includes.54 #include "parser.hh" // generated info55 48 56 49 string * build_postfix_name( string * name ); … … 221 214 __alignof { KEYWORD_RETURN(ALIGNOF); } // GCC 222 215 __alignof__ { KEYWORD_RETURN(ALIGNOF); } // GCC 223 and { QKEYWORD_RETURN(WAND); } // CFA224 216 asm { KEYWORD_RETURN(ASM); } 225 217 __asm { KEYWORD_RETURN(ASM); } // GCC -
src/Parser/module.mk
rb110bcc r2ed94a9 21 21 SRC += \ 22 22 Parser/DeclarationNode.cc \ 23 Parser/DeclarationNode.h \24 23 Parser/ExpressionNode.cc \ 25 Parser/ExpressionNode.h \26 24 Parser/InitializerNode.cc \ 27 Parser/InitializerNode.h \28 25 Parser/lex.ll \ 29 26 Parser/ParseNode.cc \ … … 36 33 Parser/RunParser.hpp \ 37 34 Parser/StatementNode.cc \ 38 Parser/StatementNode.h \39 35 Parser/TypeData.cc \ 40 36 Parser/TypeData.h \ -
src/Parser/parser.yy
rb110bcc r2ed94a9 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 // Last Modified By : Andrew Beach12 // Last Modified On : T ue Apr 4 14:02:00202313 // Update Count : 632911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 21:36:16 2023 13 // Update Count : 5865 14 14 // 15 15 … … 44 44 45 45 #include <cstdio> 46 #include <sstream>47 46 #include <stack> 48 47 using namespace std; 49 48 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_... 49 #include "SynTree/Declaration.h" 50 #include "ParseNode.h" 56 51 #include "TypedefTable.h" 57 52 #include "TypeData.h" 53 #include "SynTree/LinkageSpec.h" 58 54 #include "Common/SemanticError.h" // error_str 59 55 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 60 56 61 #include "SynTree/Attribute.h" // for Attribute57 #include "SynTree/Attribute.h" // for Attribute 62 58 63 59 // lex uses __null in a boolean context, it's fine. … … 67 63 68 64 extern DeclarationNode * parseTree; 69 extern ast::Linkage::Spec linkage;65 extern LinkageSpec::Spec linkage; 70 66 extern TypedefTable typedefTable; 71 67 72 stack< ast::Linkage::Spec> linkageStack;68 stack<LinkageSpec::Spec> linkageStack; 73 69 74 70 bool appendStr( string & to, string & from ) { … … 203 199 } // fieldDecl 204 200 205 #define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc,*new string( "0" ) ) )206 #define NEW_ONE new ExpressionNode( build_constantInteger( yylloc,*new string( "1" ) ) )201 #define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) ) 202 #define NEW_ONE new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) 207 203 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 208 204 #define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body." … … 210 206 #define MISSING_HIGH "Missing high value for down-to range so index is uninitialized." 211 207 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 ) { 208 ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 233 209 if ( index->initializer ) { 234 210 SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); … … 237 213 SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." ); 238 214 } // if 239 DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) ); 240 return makeForCtrl( location, initDecl, compop, comp, inc ); 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 ); 241 220 } // forCtrl 242 221 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 ) ) );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 ) ) ); 247 226 } // if 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 ); 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 ); 253 234 } // forCtrl 254 235 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 );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 ); 261 242 } else { 262 243 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr; … … 300 281 %union { 301 282 Token tok; 302 ExpressionNode * expr; 283 ParseNode * pn; 284 ExpressionNode * en; 303 285 DeclarationNode * decl; 304 ast::AggregateDecl::Aggregate aggKey;305 ast::TypeDecl::Kind tclass;306 StatementNode * s tmt;307 ClauseNode * clause;308 ast::WaitForStmt * wfs;286 AggregateDecl::Aggregate aggKey; 287 TypeDecl::Kind tclass; 288 StatementNode * sn; 289 WaitForStmt * wfs; 290 Expression * constant; 309 291 CondCtl * ifctl; 310 ForCtrl * forctl; 311 LabelNode * labels; 312 InitializerNode * init; 313 OperKinds oper; 292 ForCtrl * fctl; 293 OperKinds compop; 294 LabelNode * label; 295 InitializerNode * in; 296 OperKinds op; 314 297 std::string * str; 315 bool is_volatile;316 EnumHiding enum_hiding;317 ast::ExceptionKind except_kind;318 ast::GenericExpr * genexpr;298 bool flag; 299 EnumHiding hide; 300 CatchStmt::Kind catch_kind; 301 GenericExpr * genexpr; 319 302 } 320 303 321 // ************************ TERMINAL TOKENS ********************************304 //************************* TERMINAL TOKENS ******************************** 322 305 323 306 // keywords … … 354 337 355 338 // names and constants: lexer differentiates between identifier and typedef names 356 %token<tok> IDENTIFIER TYPEDIMname TYPEDEFname TYPEGENname357 %token<tok> TIMEOUT W AND WORCATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA339 %token<tok> IDENTIFIER QUOTED_IDENTIFIER TYPEDIMname TYPEDEFname TYPEGENname 340 %token<tok> TIMEOUT WOR CATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA 358 341 %token<tok> INTEGERconstant CHARACTERconstant STRINGliteral 359 342 %token<tok> DIRECTIVE … … 381 364 %type<tok> identifier identifier_at identifier_or_type_name attr_name 382 365 %type<tok> quasi_keyword 383 %type< expr> string_literal366 %type<constant> string_literal 384 367 %type<str> string_literal_list 385 368 386 %type< enum_hiding> hide_opt visible_hide_opt369 %type<hide> hide_opt visible_hide_opt 387 370 388 371 // expressions 389 %type<e xpr> constant390 %type<e xpr> tuple tuple_expression_list391 %type<op er> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator392 %type<e xpr> primary_expression postfix_expression unary_expression393 %type<e xpr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression394 %type<e xpr> shift_expression relational_expression equality_expression395 %type<e xpr> AND_expression exclusive_OR_expression inclusive_OR_expression396 %type<e xpr> logical_AND_expression logical_OR_expression397 %type<e xpr> conditional_expression constant_expression assignment_expression assignment_expression_opt398 %type<e xpr> comma_expression comma_expression_opt399 %type<e xpr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt372 %type<en> constant 373 %type<en> tuple tuple_expression_list 374 %type<op> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator 375 %type<en> primary_expression postfix_expression unary_expression 376 %type<en> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression 377 %type<en> shift_expression relational_expression equality_expression 378 %type<en> AND_expression exclusive_OR_expression inclusive_OR_expression 379 %type<en> logical_AND_expression logical_OR_expression 380 %type<en> conditional_expression constant_expression assignment_expression assignment_expression_opt 381 %type<en> comma_expression comma_expression_opt 382 %type<en> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt 400 383 %type<ifctl> conditional_declaration 401 %type<f orctl> for_control_expression for_control_expression_list402 %type< oper> upupeq updown updowneq downupdowneq403 %type<e xpr> subrange384 %type<fctl> for_control_expression for_control_expression_list 385 %type<compop> upupeq updown updowneq downupdowneq 386 %type<en> subrange 404 387 %type<decl> asm_name_opt 405 %type<e xpr> asm_operands_opt asm_operands_list asm_operand406 %type<label s> label_list407 %type<e xpr> asm_clobbers_list_opt408 %type< is_volatile> asm_volatile_opt409 %type<e xpr> handler_predicate_opt388 %type<en> asm_operands_opt asm_operands_list asm_operand 389 %type<label> label_list 390 %type<en> asm_clobbers_list_opt 391 %type<flag> asm_volatile_opt 392 %type<en> handler_predicate_opt 410 393 %type<genexpr> generic_association generic_assoc_list 411 394 412 395 // statements 413 %type<stmt> statement labeled_statement compound_statement 414 %type<stmt> statement_decl statement_decl_list statement_list_nodecl 415 %type<stmt> selection_statement if_statement 416 %type<clause> switch_clause_list_opt switch_clause_list 417 %type<expr> case_value 418 %type<clause> case_clause case_value_list case_label case_label_list 419 %type<stmt> iteration_statement jump_statement 420 %type<stmt> expression_statement asm_statement 421 %type<stmt> with_statement 422 %type<expr> with_clause_opt 423 %type<stmt> exception_statement 424 %type<clause> handler_clause finally_clause 425 %type<except_kind> handler_key 426 %type<stmt> mutex_statement 427 %type<expr> when_clause when_clause_opt waitfor waituntil timeout 428 %type<stmt> waitfor_statement waituntil_statement 429 %type<wfs> wor_waitfor_clause waituntil_clause wand_waituntil_clause wor_waituntil_clause 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 430 412 431 413 // declarations … … 439 421 %type<decl> assertion assertion_list assertion_list_opt 440 422 441 %type<e xpr> bit_subrange_size_opt bit_subrange_size423 %type<en> bit_subrange_size_opt bit_subrange_size 442 424 443 425 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 452 434 453 435 %type<decl> enumerator_list enum_type enum_type_nobody 454 %type<in it> enumerator_value_opt436 %type<in> enumerator_value_opt 455 437 456 438 %type<decl> external_definition external_definition_list external_definition_list_opt … … 459 441 460 442 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract 461 %type<e xpr> field field_name_list field_name fraction_constants_opt443 %type<en> field field_name_list field_name fraction_constants_opt 462 444 463 445 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 500 482 %type<decl> typedef_name typedef_declaration typedef_expression 501 483 502 %type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function 503 %type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr 484 %type<decl> variable_type_redeclarator type_ptr type_array type_function 504 485 505 486 %type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function … … 508 489 %type<decl> type_parameter type_parameter_list type_initializer_opt 509 490 510 %type<e xpr> type_parameters_opt type_list array_type_list491 %type<en> type_parameters_opt type_list array_type_list 511 492 512 493 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list … … 519 500 520 501 // initializers 521 %type<in it> initializer initializer_list_opt initializer_opt502 %type<in> initializer initializer_list_opt initializer_opt 522 503 523 504 // designators 524 %type<e xpr> designator designator_list designation505 %type<en> designator designator_list designation 525 506 526 507 … … 531 512 // Similar issues exit with the waitfor statement. 532 513 533 // Order of these lines matters (low-to-high precedence). THEN is left associative over W AND/WOR/TIMEOUT/ELSE, WAND/WOR534 // is leftassociative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.514 // Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left 515 // associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE. 535 516 %precedence THEN // rule precedence for IF/WAITFOR statement 536 %precedence ANDAND // token precedence for start of WAND in WAITFOR statement537 %precedence WAND // token precedence for start of WAND in WAITFOR statement538 %precedence OROR // token precedence for start of WOR in WAITFOR statement539 517 %precedence WOR // token precedence for start of WOR in WAITFOR statement 540 518 %precedence TIMEOUT // token precedence for start of TIMEOUT in WAITFOR statement … … 614 592 constant: 615 593 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant". 616 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( yylloc,*$1 ) ); }617 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( yylloc,*$1 ) ); }618 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( yylloc,*$1 ) ); }619 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( yylloc,*$1 ) ); }620 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( yylloc,*$1 ) ); }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 ) ); } 621 599 ; 622 600 623 601 quasi_keyword: // CFA 624 602 TIMEOUT 625 | WAND626 603 | WOR 627 604 | CATCH … … 644 621 645 622 string_literal: 646 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 )); }623 string_literal_list { $$ = build_constantStr( *$1 ); } 647 624 ; 648 625 … … 661 638 primary_expression: 662 639 IDENTIFIER // typedef name cannot be used as a variable name 663 { $$ = new ExpressionNode( build_varref( yylloc,$1 ) ); }640 { $$ = new ExpressionNode( build_varref( $1 ) ); } 664 641 | quasi_keyword 665 { $$ = new ExpressionNode( build_varref( yylloc,$1 ) ); }642 { $$ = new ExpressionNode( build_varref( $1 ) ); } 666 643 | TYPEDIMname // CFA, generic length argument 667 644 // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); } 668 645 // { $$ = new ExpressionNode( build_varref( $1 ) ); } 669 { $$ = new ExpressionNode( build_dimensionref( yylloc,$1 ) ); }646 { $$ = new ExpressionNode( build_dimensionref( $1 ) ); } 670 647 | tuple 671 648 | '(' comma_expression ')' 672 649 { $$ = $2; } 673 650 | '(' compound_statement ')' // GCC, lambda expression 674 { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2) ) ) ); }651 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); } 675 652 | type_name '.' identifier // CFA, nested type 676 { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc,$3 ) ) ); }653 { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); } 677 654 | type_name '.' '[' field_name_list ']' // CFA, nested type / tuple field selector 678 655 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; } … … 680 657 { 681 658 // add the missing control expression to the GenericExpr and return it 682 $5->control = maybeMoveBuild ( $3 );659 $5->control = maybeMoveBuild<Expression>( $3 ); 683 660 $$ = new ExpressionNode( $5 ); 684 661 } … … 706 683 { 707 684 // steal the association node from the singleton and delete the wrapper 708 assert( 1 == $3->associations.size() ); 709 $1->associations.push_back( $3->associations.front() ); 685 $1->associations.splice($1->associations.end(), $3->associations); 710 686 delete $3; 711 687 $$ = $1; … … 717 693 { 718 694 // create a GenericExpr wrapper with one association pair 719 $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );695 $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } ); 720 696 } 721 697 | DEFAULT ':' assignment_expression 722 { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }698 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); } 723 699 ; 724 700 … … 729 705 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts. 730 706 // Current: Commas in subscripts make tuples. 731 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc,(ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }707 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); } 732 708 | postfix_expression '[' assignment_expression ']' 733 709 // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a … … 735 711 // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is 736 712 // equivalent to the old x[i,j]. 737 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Index, $1, $3 ) ); }713 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 738 714 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a] 739 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Index, $1, $3 ) ); }715 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 740 716 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }717 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); } 742 718 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 743 719 { 744 720 Token fn; 745 721 fn.str = new std::string( "?{}" ); // location undefined - use location of '{'? 746 $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc,fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );722 $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) ); 747 723 } 748 724 | postfix_expression '(' argument_expression_list_opt ')' 749 { $$ = new ExpressionNode( build_func( yylloc,$1, $3 ) ); }725 { $$ = new ExpressionNode( build_func( $1, $3 ) ); } 750 726 | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')' 751 727 // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; } 752 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc,new string( "__builtin_va_arg") ) ),728 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__builtin_va_arg") ) ), 753 729 (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); } 754 730 | postfix_expression '`' identifier // CFA, postfix call 755 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc,build_postfix_name( $3 ) ) ), $1 ) ); }731 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); } 756 732 | constant '`' identifier // CFA, postfix call 757 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc,build_postfix_name( $3 ) ) ), $1 ) ); }733 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); } 758 734 | string_literal '`' identifier // CFA, postfix call 759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1) ); }735 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); } 760 736 | postfix_expression '.' identifier 761 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc,$3 ) ) ); }737 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); } 762 738 | postfix_expression '.' INTEGERconstant // CFA, tuple index 763 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc,*$3 ) ) ); }739 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); } 764 740 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index 765 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc,*$2 ) ) ); }741 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); } 766 742 | postfix_expression '.' '[' field_name_list ']' // CFA, tuple field selector 767 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc,$4 ) ) ); }743 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); } 768 744 | postfix_expression '.' aggregate_control 769 { $$ = new ExpressionNode( build_keyword_cast( yylloc,$3, $1 ) ); }745 { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); } 770 746 | postfix_expression ARROW identifier 771 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc,$3 ) ) ); }747 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); } 772 748 | postfix_expression ARROW INTEGERconstant // CFA, tuple index 773 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc,*$3 ) ) ); }749 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); } 774 750 | postfix_expression ARROW '[' field_name_list ']' // CFA, tuple field selector 775 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc,$4 ) ) ); }751 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); } 776 752 | postfix_expression ICR 777 { $$ = new ExpressionNode( build_unary_val( yylloc,OperKinds::IncrPost, $1 ) ); }753 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); } 778 754 | postfix_expression DECR 779 { $$ = new ExpressionNode( build_unary_val( yylloc,OperKinds::DecrPost, $1 ) ); }755 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, $1 ) ); } 780 756 | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal 781 { $$ = new ExpressionNode( build_compoundLiteral( yylloc,$2, new InitializerNode( $5, true ) ) ); }757 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); } 782 758 | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal 783 { $$ = new ExpressionNode( build_compoundLiteral( yylloc,$2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }759 { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); } 784 760 | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call 785 761 { 786 762 Token fn; 787 763 fn.str = new string( "^?{}" ); // location undefined 788 $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc,fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );764 $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) ); 789 765 } 790 766 ; … … 805 781 '@' // CFA, default parameter 806 782 { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; } 807 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }783 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); } 808 784 | assignment_expression 809 785 ; … … 817 793 field_name 818 794 | FLOATING_DECIMALconstant field 819 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }795 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); } 820 796 | FLOATING_DECIMALconstant '[' field_name_list ']' 821 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc,$3 ) ) ); }797 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); } 822 798 | field_name '.' field 823 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }799 { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); } 824 800 | field_name '.' '[' field_name_list ']' 825 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc,$4 ) ) ); }801 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); } 826 802 | field_name ARROW field 827 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }803 { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); } 828 804 | field_name ARROW '[' field_name_list ']' 829 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc,$4 ) ) ); }805 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); } 830 806 ; 831 807 832 808 field_name: 833 809 INTEGERconstant fraction_constants_opt 834 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc,*$1 ), $2 ) ); }810 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); } 835 811 | FLOATINGconstant fraction_constants_opt 836 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc,*$1 ), $2 ) ); }812 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); } 837 813 | identifier_at fraction_constants_opt // CFA, allow anonymous fields 838 814 { 839 $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc,$1 ), $2 ) );815 $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) ); 840 816 } 841 817 ; … … 846 822 | fraction_constants_opt FLOATING_FRACTIONconstant 847 823 { 848 ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc,*$2 );849 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1,constant ) ) : new ExpressionNode( constant );824 Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 ); 825 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1, constant ) ) : new ExpressionNode( constant ); 850 826 } 851 827 ; … … 857 833 | constant 858 834 | string_literal 859 { $$ = $1; }835 { $$ = new ExpressionNode( $1 ); } 860 836 | EXTENSION cast_expression // GCC 861 837 { $$ = $2->set_extension( true ); } … … 866 842 { 867 843 switch ( $1 ) { 868 case OperKinds::AddressOf:869 $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );844 case OperKinds::AddressOf: 845 $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ); 870 846 break; 871 case OperKinds::PointTo:872 $$ = new ExpressionNode( build_unary_val( yylloc,$1, $2 ) );847 case OperKinds::PointTo: 848 $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); 873 849 break; 874 case OperKinds::And:875 $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );850 case OperKinds::And: 851 $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) ); 876 852 break; 877 default:853 default: 878 854 assert( false ); 879 855 } 880 856 } 881 857 | unary_operator cast_expression 882 { $$ = new ExpressionNode( build_unary_val( yylloc,$1, $2 ) ); }858 { $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); } 883 859 | ICR unary_expression 884 { $$ = new ExpressionNode( build_unary_val( yylloc,OperKinds::Incr, $2 ) ); }860 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Incr, $2 ) ); } 885 861 | DECR unary_expression 886 { $$ = new ExpressionNode( build_unary_val( yylloc,OperKinds::Decr, $2 ) ); }862 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Decr, $2 ) ); } 887 863 | SIZEOF unary_expression 888 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }864 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); } 889 865 | SIZEOF '(' type_no_function ')' 890 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc,maybeMoveBuildType( $3 ) ) ); }866 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuildType( $3 ) ) ); } 891 867 | ALIGNOF unary_expression // GCC, variable alignment 892 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }868 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); } 893 869 | ALIGNOF '(' type_no_function ')' // GCC, type alignment 894 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc,maybeMoveBuildType( $3 ) ) ); }870 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); } 895 871 | OFFSETOF '(' type_no_function ',' identifier ')' 896 { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc,$5 ) ) ); }872 { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); } 897 873 | TYPEID '(' type_no_function ')' 898 874 { … … 919 895 unary_expression 920 896 | '(' type_no_function ')' cast_expression 921 { $$ = new ExpressionNode( build_cast( yylloc,$2, $4 ) ); }897 { $$ = new ExpressionNode( build_cast( $2, $4 ) ); } 922 898 | '(' aggregate_control '&' ')' cast_expression // CFA 923 { $$ = new ExpressionNode( build_keyword_cast( yylloc,$2, $5 ) ); }899 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); } 924 900 | '(' aggregate_control '*' ')' cast_expression // CFA 925 { $$ = new ExpressionNode( build_keyword_cast( yylloc,$2, $5 ) ); }901 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); } 926 902 | '(' VIRTUAL ')' cast_expression // CFA 927 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }903 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); } 928 904 | '(' VIRTUAL type_no_function ')' cast_expression // CFA 929 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }905 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); } 930 906 | '(' RETURN type_no_function ')' cast_expression // CFA 931 907 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; } … … 935 911 { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; } 936 912 // | '(' type_no_function ')' tuple 937 // { $$ = new ast::ExpressionNode( build_cast( yylloc,$2, $4 ) ); }913 // { $$ = new ExpressionNode( build_cast( $2, $4 ) ); } 938 914 ; 939 915 … … 953 929 cast_expression 954 930 | exponential_expression '\\' cast_expression 955 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Exp, $1, $3 ) ); }931 { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); } 956 932 ; 957 933 … … 959 935 exponential_expression 960 936 | multiplicative_expression '*' exponential_expression 961 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Mul, $1, $3 ) ); }937 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); } 962 938 | multiplicative_expression '/' exponential_expression 963 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Div, $1, $3 ) ); }939 { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); } 964 940 | multiplicative_expression '%' exponential_expression 965 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Mod, $1, $3 ) ); }941 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); } 966 942 ; 967 943 … … 969 945 multiplicative_expression 970 946 | additive_expression '+' multiplicative_expression 971 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Plus, $1, $3 ) ); }947 { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); } 972 948 | additive_expression '-' multiplicative_expression 973 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Minus, $1, $3 ) ); }949 { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); } 974 950 ; 975 951 … … 977 953 additive_expression 978 954 | shift_expression LS additive_expression 979 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::LShift, $1, $3 ) ); }955 { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); } 980 956 | shift_expression RS additive_expression 981 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::RShift, $1, $3 ) ); }957 { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); } 982 958 ; 983 959 … … 985 961 shift_expression 986 962 | relational_expression '<' shift_expression 987 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::LThan, $1, $3 ) ); }963 { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); } 988 964 | relational_expression '>' shift_expression 989 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::GThan, $1, $3 ) ); }965 { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); } 990 966 | relational_expression LE shift_expression 991 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::LEThan, $1, $3 ) ); }967 { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); } 992 968 | relational_expression GE shift_expression 993 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::GEThan, $1, $3 ) ); }969 { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); } 994 970 ; 995 971 … … 997 973 relational_expression 998 974 | equality_expression EQ relational_expression 999 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Eq, $1, $3 ) ); }975 { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); } 1000 976 | equality_expression NE relational_expression 1001 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Neq, $1, $3 ) ); }977 { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); } 1002 978 ; 1003 979 … … 1005 981 equality_expression 1006 982 | AND_expression '&' equality_expression 1007 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::BitAnd, $1, $3 ) ); }983 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); } 1008 984 ; 1009 985 … … 1011 987 AND_expression 1012 988 | exclusive_OR_expression '^' AND_expression 1013 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::Xor, $1, $3 ) ); }989 { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); } 1014 990 ; 1015 991 … … 1017 993 exclusive_OR_expression 1018 994 | inclusive_OR_expression '|' exclusive_OR_expression 1019 { $$ = new ExpressionNode( build_binary_val( yylloc,OperKinds::BitOr, $1, $3 ) ); }995 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); } 1020 996 ; 1021 997 … … 1023 999 inclusive_OR_expression 1024 1000 | logical_AND_expression ANDAND inclusive_OR_expression 1025 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr) ); }1001 { $$ = new ExpressionNode( build_and_or( $1, $3, true ) ); } 1026 1002 ; 1027 1003 … … 1029 1005 logical_AND_expression 1030 1006 | logical_OR_expression OROR logical_AND_expression 1031 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr) ); }1007 { $$ = new ExpressionNode( build_and_or( $1, $3, false ) ); } 1032 1008 ; 1033 1009 … … 1035 1011 logical_OR_expression 1036 1012 | logical_OR_expression '?' comma_expression ':' conditional_expression 1037 { $$ = new ExpressionNode( build_cond( yylloc,$1, $3, $5 ) ); }1013 { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); } 1038 1014 // FIX ME: computes $1 twice 1039 1015 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand 1040 { $$ = new ExpressionNode( build_cond( yylloc,$1, $1, $4 ) ); }1016 { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); } 1041 1017 ; 1042 1018 … … 1053 1029 // SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr; 1054 1030 // } else { 1055 $$ = new ExpressionNode( build_binary_val( yylloc,$2, $1, $3 ) );1031 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); 1056 1032 // } // if 1057 1033 } … … 1098 1074 // { $$ = new ExpressionNode( build_tuple( $3 ) ); } 1099 1075 '[' ',' tuple_expression_list ']' 1100 { $$ = new ExpressionNode( build_tuple( yylloc,(ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }1076 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); } 1101 1077 | '[' push assignment_expression pop ',' tuple_expression_list ']' 1102 { $$ = new ExpressionNode( build_tuple( yylloc,(ExpressionNode *)($3->set_last( $6 ) ) )); }1078 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); } 1103 1079 ; 1104 1080 … … 1116 1092 assignment_expression 1117 1093 | comma_expression ',' assignment_expression 1118 { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }1094 { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); } 1119 1095 ; 1120 1096 … … 1137 1113 | mutex_statement 1138 1114 | waitfor_statement 1139 | waituntil_statement1140 1115 | exception_statement 1141 1116 | enable_disable_statement … … 1143 1118 | asm_statement 1144 1119 | DIRECTIVE 1145 { $$ = new StatementNode( build_directive( yylloc,$1 ) ); }1120 { $$ = new StatementNode( build_directive( $1 ) ); } 1146 1121 ; 1147 1122 … … 1149 1124 // labels cannot be identifiers 0 or 1 1150 1125 identifier_or_type_name ':' attribute_list_opt statement 1151 { $$ = $4->add_label( yylloc,$1, $3 ); }1126 { $$ = $4->add_label( $1, $3 ); } 1152 1127 | identifier_or_type_name ':' attribute_list_opt error // syntax error 1153 1128 { … … 1161 1136 compound_statement: 1162 1137 '{' '}' 1163 { $$ = new StatementNode( build_compound( yylloc,(StatementNode *)0 ) ); }1138 { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); } 1164 1139 | '{' push 1165 1140 local_label_declaration_opt // GCC, local labels appear at start of block 1166 1141 statement_decl_list // C99, intermix declarations and statements 1167 1142 pop '}' 1168 { $$ = new StatementNode( build_compound( yylloc,$4 ) ); }1143 { $$ = new StatementNode( build_compound( $4 ) ); } 1169 1144 ; 1170 1145 … … 1197 1172 expression_statement: 1198 1173 comma_expression_opt ';' 1199 { $$ = new StatementNode( build_expr( yylloc, $1 ) ); } 1174 { $$ = new StatementNode( build_expr( $1 ) ); } 1175 | MUTEX '(' ')' comma_expression ';' 1176 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); } 1200 1177 ; 1201 1178 … … 1206 1183 { $$ = $2; } 1207 1184 | SWITCH '(' comma_expression ')' case_clause 1208 { $$ = new StatementNode( build_switch( yylloc,true, $3, $5 ) ); }1185 { $$ = new StatementNode( build_switch( true, $3, $5 ) ); } 1209 1186 | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1210 1187 { 1211 StatementNode *sw = new StatementNode( build_switch( yylloc,true, $3, $8 ) );1188 StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) ); 1212 1189 // The semantics of the declaration list is changed to include associated initialization, which is performed 1213 1190 // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound … … 1215 1192 // therefore, are removed from the grammar even though C allows it. The change also applies to choose 1216 1193 // statement. 1217 $$ = $7 ? new StatementNode( build_compound( yylloc,(StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;1194 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1218 1195 } 1219 1196 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntax error 1220 1197 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1221 1198 | CHOOSE '(' comma_expression ')' case_clause // CFA 1222 { $$ = new StatementNode( build_switch( yylloc,false, $3, $5 ) ); }1199 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); } 1223 1200 | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1224 1201 { 1225 StatementNode *sw = new StatementNode( build_switch( yylloc,false, $3, $8 ) );1226 $$ = $7 ? new StatementNode( build_compound( yylloc,(StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;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 1204 } 1228 1205 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error … … 1233 1210 IF '(' conditional_declaration ')' statement %prec THEN 1234 1211 // explicitly deal with the shift/reduce conflict on if/else 1235 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc,$5 ), nullptr ) ); }1212 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); } 1236 1213 | IF '(' conditional_declaration ')' statement ELSE statement 1237 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc,$7 ) ) ); }1214 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); } 1238 1215 ; 1239 1216 … … 1247 1224 | declaration comma_expression // semi-colon separated 1248 1225 { $$ = new CondCtl( $1, $2 ); } 1249 ;1226 ; 1250 1227 1251 1228 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case … … 1255 1232 constant_expression { $$ = $1; } 1256 1233 | constant_expression ELLIPSIS constant_expression // GCC, subrange 1257 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }1234 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); } 1258 1235 | subrange // CFA, subrange 1259 1236 ; 1260 1237 1261 1238 case_value_list: // CFA 1262 case_value { $$ = new ClauseNode( build_case( yylloc,$1 ) ); }1239 case_value { $$ = new StatementNode( build_case( $1 ) ); } 1263 1240 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5" 1264 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3) ) ); }1241 | case_value_list ',' case_value { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 ) ) ) ); } 1265 1242 ; 1266 1243 … … 1271 1248 | CASE case_value_list error // syntax error 1272 1249 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1273 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc) ); }1250 | DEFAULT ':' { $$ = new StatementNode( build_default() ); } 1274 1251 // A semantic check is required to ensure only one default clause per switch/choose statement. 1275 1252 | DEFAULT error // syntax error … … 1279 1256 case_label_list: // CFA 1280 1257 case_label 1281 | case_label_list case_label { $$ = $1->set_last( $2); }1258 | case_label_list case_label { $$ = (StatementNode *)( $1->set_last( $2 )); } 1282 1259 ; 1283 1260 1284 1261 case_clause: // CFA 1285 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( yylloc,$2 ) ); }1262 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); } 1286 1263 ; 1287 1264 … … 1294 1271 switch_clause_list: // CFA 1295 1272 case_label_list statement_list_nodecl 1296 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc,$2 ) ) ); }1273 { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); } 1297 1274 | switch_clause_list case_label_list statement_list_nodecl 1298 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3) ) ) ); }1275 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 ) ) ) ) ); } 1299 1276 ; 1300 1277 1301 1278 iteration_statement: 1302 1279 WHILE '(' ')' statement %prec THEN // CFA => while ( 1 ) 1303 { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc,$4 ) ) ); }1280 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); } 1304 1281 | WHILE '(' ')' statement ELSE statement // CFA 1305 1282 { 1306 $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc,$4 ) ) );1307 SemanticWarning( yylloc, Warning::SuperfluousElse );1283 $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); 1284 SemanticWarning( yylloc, Warning::SuperfluousElse, "" ); 1308 1285 } 1309 1286 | WHILE '(' conditional_declaration ')' statement %prec THEN 1310 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc,$5 ) ) ); }1287 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); } 1311 1288 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1312 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc,$5 ), $7 ) ); }1289 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); } 1313 1290 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) 1314 { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc,$2 ) ) ); }1291 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); } 1315 1292 | DO statement WHILE '(' ')' ELSE statement // CFA 1316 1293 { 1317 $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc,$2 ) ) );1318 SemanticWarning( yylloc, Warning::SuperfluousElse );1294 $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); 1295 SemanticWarning( yylloc, Warning::SuperfluousElse, "" ); 1319 1296 } 1320 1297 | DO statement WHILE '(' comma_expression ')' ';' 1321 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc,$2 ) ) ); }1298 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); } 1322 1299 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1323 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc,$2 ), $8 ) ); }1300 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); } 1324 1301 | FOR '(' ')' statement %prec THEN // CFA => for ( ;; ) 1325 { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc,$4 ) ) ); }1302 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); } 1326 1303 | FOR '(' ')' statement ELSE statement // CFA 1327 1304 { 1328 $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc,$4 ) ) );1329 SemanticWarning( yylloc, Warning::SuperfluousElse );1305 $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); 1306 SemanticWarning( yylloc, Warning::SuperfluousElse, "" ); 1330 1307 } 1331 1308 | FOR '(' for_control_expression_list ')' statement %prec THEN 1332 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc,$5 ) ) ); }1309 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); } 1333 1310 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1334 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc,$5 ), $7 ) ); }1311 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); } 1335 1312 ; 1336 1313 … … 1346 1323 if ( $1->condition ) { 1347 1324 if ( $3->condition ) { 1348 $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr) );1325 $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) ); 1349 1326 } // if 1350 1327 } else $1->condition = $3->condition; 1351 1328 if ( $1->change ) { 1352 1329 if ( $3->change ) { 1353 $1->change->expr.reset( new ast::CommaExpr( yylloc,$1->change->expr.release(), $3->change->expr.release() ) );1330 $1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) ); 1354 1331 } // if 1355 1332 } else $1->change = $3->change; … … 1360 1337 for_control_expression: 1361 1338 ';' comma_expression_opt ';' comma_expression_opt 1362 { $$ = new ForCtrl( nullptr, $2, $4 ); }1339 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); } 1363 1340 | comma_expression ';' comma_expression_opt ';' comma_expression_opt 1364 { 1365 StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr; 1366 $$ = new ForCtrl( init, $3, $5 ); 1367 } 1341 { $$ = new ForCtrl( $1, $3, $5 ); } 1368 1342 | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';' 1369 { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); }1343 { $$ = new ForCtrl( $1, $2, $4 ); } 1370 1344 1371 1345 | '@' ';' comma_expression // CFA, empty loop-index 1372 { $$ = new ForCtrl( nullptr, $3, nullptr ); }1346 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); } 1373 1347 | '@' ';' comma_expression ';' comma_expression // CFA, empty loop-index 1374 { $$ = new ForCtrl( nullptr, $3, $5 ); }1348 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); } 1375 1349 1376 1350 | comma_expression // CFA, anonymous loop-index 1377 { $$ = forCtrl( yylloc,$1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }1351 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); } 1378 1352 | downupdowneq comma_expression // CFA, anonymous loop-index 1379 { $$ = forCtrl( yylloc,$2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }1353 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); } 1380 1354 1381 1355 | comma_expression updowneq comma_expression // CFA, anonymous loop-index 1382 { $$ = forCtrl( yylloc,$1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }1356 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); } 1383 1357 | '@' updowneq comma_expression // CFA, anonymous loop-index 1384 1358 { 1385 1359 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1386 else $$ = forCtrl( yylloc,$3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );1360 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE ); 1387 1361 } 1388 1362 | comma_expression updowneq '@' // CFA, anonymous loop-index … … 1392 1366 } 1393 1367 | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1394 { $$ = forCtrl( yylloc,$1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }1368 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); } 1395 1369 | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1396 1370 { 1397 1371 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1398 else $$ = forCtrl( yylloc,$3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );1372 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 ); 1399 1373 } 1400 1374 | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index … … 1415 1389 1416 1390 | comma_expression ';' comma_expression // CFA 1417 { $$ = forCtrl( yylloc,$3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }1391 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); } 1418 1392 | comma_expression ';' downupdowneq comma_expression // CFA 1419 { $$ = forCtrl( yylloc,$4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }1393 { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); } 1420 1394 1421 1395 | comma_expression ';' comma_expression updowneq comma_expression // CFA 1422 { $$ = forCtrl( yylloc,$3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }1396 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); } 1423 1397 | comma_expression ';' '@' updowneq comma_expression // CFA 1424 1398 { 1425 1399 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1426 else $$ = forCtrl( yylloc,$5, $1, $5->clone(), $4, nullptr, NEW_ONE );1400 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE ); 1427 1401 } 1428 1402 | comma_expression ';' comma_expression updowneq '@' // CFA … … 1430 1404 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1431 1405 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1432 else $$ = forCtrl( yylloc,$3, $1, $3->clone(), $4, nullptr, NEW_ONE );1406 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE ); 1433 1407 } 1434 1408 | comma_expression ';' '@' updowneq '@' // CFA, error … … 1436 1410 1437 1411 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA 1438 { $$ = forCtrl( yylloc,$3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }1412 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); } 1439 1413 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error 1440 1414 { 1441 1415 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1442 else $$ = forCtrl( yylloc,$5, $1, $5->clone(), $4, nullptr, $7 );1416 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 ); 1443 1417 } 1444 1418 | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA … … 1446 1420 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1447 1421 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1448 else $$ = forCtrl( yylloc,$3, $1, $3->clone(), $4, nullptr, $7 );1422 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 ); 1449 1423 } 1450 1424 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA 1451 { $$ = forCtrl( yylloc,$3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }1425 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); } 1452 1426 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error 1453 1427 { 1454 1428 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1455 else $$ = forCtrl( yylloc,$5, $1, $5->clone(), $4, nullptr, nullptr );1429 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr ); 1456 1430 } 1457 1431 | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA … … 1459 1433 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1460 1434 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1461 else $$ = forCtrl( yylloc,$3, $1, $3->clone(), $4, nullptr, nullptr );1435 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr ); 1462 1436 } 1463 1437 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA … … 1465 1439 1466 1440 | declaration comma_expression // CFA 1467 { $$ = forCtrl( yylloc,$1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }1441 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); } 1468 1442 | declaration downupdowneq comma_expression // CFA 1469 { $$ = forCtrl( yylloc,$1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }1443 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); } 1470 1444 1471 1445 | declaration comma_expression updowneq comma_expression // CFA 1472 { $$ = forCtrl( yylloc,$1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }1446 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); } 1473 1447 | declaration '@' updowneq comma_expression // CFA 1474 1448 { 1475 1449 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1476 else $$ = forCtrl( yylloc,$1, $4, $3, nullptr, NEW_ONE );1450 else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE ); 1477 1451 } 1478 1452 | declaration comma_expression updowneq '@' // CFA … … 1480 1454 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1481 1455 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1482 else $$ = forCtrl( yylloc,$1, $2, $3, nullptr, NEW_ONE );1456 else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE ); 1483 1457 } 1484 1458 1485 1459 | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA 1486 { $$ = forCtrl( yylloc,$1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }1460 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); } 1487 1461 | declaration '@' updowneq comma_expression '~' comma_expression // CFA 1488 1462 { 1489 1463 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1490 else $$ = forCtrl( yylloc,$1, $4, $3, nullptr, $6 );1464 else $$ = forCtrl( $1, $4, $3, nullptr, $6 ); 1491 1465 } 1492 1466 | declaration comma_expression updowneq '@' '~' comma_expression // CFA … … 1494 1468 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1495 1469 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1496 else $$ = forCtrl( yylloc,$1, $2, $3, nullptr, $6 );1470 else $$ = forCtrl( $1, $2, $3, nullptr, $6 ); 1497 1471 } 1498 1472 | declaration comma_expression updowneq comma_expression '~' '@' // CFA 1499 { $$ = forCtrl( yylloc,$1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }1473 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); } 1500 1474 | declaration '@' updowneq comma_expression '~' '@' // CFA 1501 1475 { 1502 1476 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1503 else $$ = forCtrl( yylloc,$1, $4, $3, nullptr, nullptr );1477 else $$ = forCtrl( $1, $4, $3, nullptr, nullptr ); 1504 1478 } 1505 1479 | declaration comma_expression updowneq '@' '~' '@' // CFA … … 1507 1481 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1508 1482 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1509 else $$ = forCtrl( yylloc,$1, $2, $3, nullptr, nullptr );1483 else $$ = forCtrl( $1, $2, $3, nullptr, nullptr ); 1510 1484 } 1511 1485 | declaration '@' updowneq '@' '~' '@' // CFA, error … … 1522 1496 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1523 1497 } 1524 ;1498 ; 1525 1499 1526 1500 downupdowneq: … … 1531 1505 | ErangeDownEq 1532 1506 { $$ = OperKinds::GEThan; } 1533 ;1507 ; 1534 1508 1535 1509 updown: … … 1538 1512 | ErangeDown 1539 1513 { $$ = OperKinds::GThan; } 1540 ;1514 ; 1541 1515 1542 1516 updowneq: … … 1546 1520 | ErangeDownEq 1547 1521 { $$ = OperKinds::GEThan; } 1548 ;1522 ; 1549 1523 1550 1524 jump_statement: 1551 1525 GOTO identifier_or_type_name ';' 1552 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }1526 { $$ = new StatementNode( build_branch( $2, BranchStmt::Goto ) ); } 1553 1527 | GOTO '*' comma_expression ';' // GCC, computed goto 1554 1528 // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3); … … 1557 1531 // A semantic check is required to ensure fallthru appears only in the body of a choose statement. 1558 1532 | fall_through_name ';' // CFA 1559 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }1533 { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); } 1560 1534 | fall_through_name identifier_or_type_name ';' // CFA 1561 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }1535 { $$ = new StatementNode( build_branch( $2, BranchStmt::FallThrough ) ); } 1562 1536 | fall_through_name DEFAULT ';' // CFA 1563 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }1537 { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); } 1564 1538 | CONTINUE ';' 1565 1539 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1566 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }1540 { $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); } 1567 1541 | CONTINUE identifier_or_type_name ';' // CFA, multi-level continue 1568 1542 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1569 1543 // the target of the transfer appears only at the start of an iteration statement. 1570 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }1544 { $$ = new StatementNode( build_branch( $2, BranchStmt::Continue ) ); } 1571 1545 | BREAK ';' 1572 1546 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1573 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }1547 { $$ = new StatementNode( build_branch( BranchStmt::Break ) ); } 1574 1548 | BREAK identifier_or_type_name ';' // CFA, multi-level exit 1575 1549 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1576 1550 // the target of the transfer appears only at the start of an iteration statement. 1577 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }1551 { $$ = new StatementNode( build_branch( $2, BranchStmt::Break ) ); } 1578 1552 | RETURN comma_expression_opt ';' 1579 { $$ = new StatementNode( build_return( yylloc,$2 ) ); }1553 { $$ = new StatementNode( build_return( $2 ) ); } 1580 1554 | RETURN '{' initializer_list_opt comma_opt '}' ';' 1581 1555 { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; } 1582 1556 | SUSPEND ';' 1583 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None) ); }1557 { $$ = new StatementNode( build_suspend( nullptr ) ); } 1584 1558 | SUSPEND compound_statement 1585 { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None) ); }1559 { $$ = new StatementNode( build_suspend( $2 ) ); } 1586 1560 | SUSPEND COROUTINE ';' 1587 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }1561 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); } 1588 1562 | SUSPEND COROUTINE compound_statement 1589 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }1563 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); } 1590 1564 | SUSPEND GENERATOR ';' 1591 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }1565 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); } 1592 1566 | SUSPEND GENERATOR compound_statement 1593 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }1567 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); } 1594 1568 | THROW assignment_expression_opt ';' // handles rethrow 1595 { $$ = new StatementNode( build_throw( yylloc,$2 ) ); }1569 { $$ = new StatementNode( build_throw( $2 ) ); } 1596 1570 | THROWRESUME assignment_expression_opt ';' // handles reresume 1597 { $$ = new StatementNode( build_resume( yylloc,$2 ) ); }1571 { $$ = new StatementNode( build_resume( $2 ) ); } 1598 1572 | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume 1599 1573 { $$ = new StatementNode( build_resume_at( $2, $4 ) ); } … … 1607 1581 with_statement: 1608 1582 WITH '(' tuple_expression_list ')' statement 1609 { $$ = new StatementNode( build_with( yylloc,$3, $5 ) ); }1610 ; 1611 1612 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possiblychange syntax to "with mutex".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". 1613 1587 mutex_statement: 1614 MUTEX '(' argument_expression_list_opt ')' statement 1615 { 1616 if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; } 1617 $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) ); 1618 } 1588 MUTEX '(' argument_expression_list ')' statement 1589 { $$ = new StatementNode( build_mutex( $3, $5 ) ); } 1619 1590 ; 1620 1591 … … 1627 1598 { $$ = nullptr; } 1628 1599 | 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 )); } 1629 1609 ; 1630 1610 … … 1637 1617 1638 1618 timeout: 1639 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1640 ; 1641 1642 wor: 1643 OROR 1644 | WOR 1645 1646 waitfor: 1647 WAITFOR '(' cast_expression ')' 1648 { $$ = $3; } 1649 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')' 1650 { $$ = (ExpressionNode *)($3->set_last( $5 )); } 1651 ; 1652 1653 wor_waitfor_clause: 1619 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1620 ; 1621 1622 waitfor_clause: 1654 1623 when_clause_opt waitfor statement %prec THEN 1655 // Called first: create header for WaitForStmt. 1656 { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); } 1657 | wor_waitfor_clause wor when_clause_opt waitfor statement 1658 { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1659 | wor_waitfor_clause wor when_clause_opt ELSE statement 1660 { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); } 1661 | wor_waitfor_clause wor when_clause_opt timeout statement %prec THEN 1662 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 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 ); } 1663 1631 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1664 | w or_waitfor_clause wor when_clause_opt timeout statement worELSE statement // syntax error1632 | when_clause_opt timeout statement WOR ELSE statement // syntax error 1665 1633 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1666 | w or_waitfor_clause wor when_clause_opt timeout statement worwhen_clause ELSE statement1667 { $$ = build_waitfor_ else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 )); }1634 | when_clause_opt timeout statement WOR when_clause ELSE statement 1635 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); } 1668 1636 ; 1669 1637 1670 1638 waitfor_statement: 1671 wor_waitfor_clause %prec THEN 1672 { $$ = new StatementNode( $1 ); } 1673 ; 1674 1675 wand: 1676 ANDAND 1677 | WAND 1678 ; 1679 1680 waituntil: 1681 WAITUNTIL '(' cast_expression ')' 1682 { $$ = $3; } 1683 ; 1684 1685 waituntil_clause: 1686 when_clause_opt waituntil statement 1687 { printf( "waituntil_clause 1\n" ); $$ = nullptr; } 1688 | '(' wor_waituntil_clause ')' 1689 { printf( "waituntil_clause 2\n" ); $$ = nullptr; } 1690 ; 1691 1692 wand_waituntil_clause: 1693 waituntil_clause %prec THEN 1694 { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; } 1695 | waituntil_clause wand wand_waituntil_clause 1696 { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; } 1697 ; 1698 1699 wor_waituntil_clause: 1700 wand_waituntil_clause 1701 { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; } 1702 | wor_waituntil_clause wor wand_waituntil_clause 1703 { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; } 1704 | wor_waituntil_clause wor when_clause_opt ELSE statement 1705 { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; } 1706 | wor_waituntil_clause wor when_clause_opt timeout statement %prec THEN 1707 { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; } 1708 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1709 | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error 1710 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1711 | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1712 { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; } 1713 ; 1714 1715 waituntil_statement: 1716 wor_waituntil_clause %prec THEN 1717 // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement. 1718 { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); } 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 ) ); } 1719 1643 ; 1720 1644 1721 1645 exception_statement: 1722 TRY compound_statement handler_clause %prec THEN1723 { $$ = new StatementNode( build_try( yylloc,$2, $3, nullptr ) ); }1646 TRY compound_statement handler_clause %prec THEN 1647 { $$ = new StatementNode( build_try( $2, $3, nullptr ) ); } 1724 1648 | TRY compound_statement finally_clause 1725 { $$ = new StatementNode( build_try( yylloc,$2, nullptr, $3 ) ); }1649 { $$ = new StatementNode( build_try( $2, nullptr, $3 ) ); } 1726 1650 | TRY compound_statement handler_clause finally_clause 1727 { $$ = new StatementNode( build_try( yylloc,$2, $3, $4 ) ); }1651 { $$ = new StatementNode( build_try( $2, $3, $4 ) ); } 1728 1652 ; 1729 1653 1730 1654 handler_clause: 1731 1655 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1732 { $$ = new ClauseNode( build_catch( yylloc,$1, $4, $6, $8 ) ); }1656 { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); } 1733 1657 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1734 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc,$2, $5, $7, $9 ) ) ); }1658 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); } 1735 1659 ; 1736 1660 … … 1742 1666 1743 1667 handler_key: 1744 CATCH { $$ = ast::Terminate; }1745 | RECOVER { $$ = ast::Terminate; }1746 | CATCHRESUME { $$ = ast::Resume; }1747 | FIXUP { $$ = ast::Resume; }1668 CATCH { $$ = CatchStmt::Terminate; } 1669 | RECOVER { $$ = CatchStmt::Terminate; } 1670 | CATCHRESUME { $$ = CatchStmt::Resume; } 1671 | FIXUP { $$ = CatchStmt::Resume; } 1748 1672 ; 1749 1673 1750 1674 finally_clause: 1751 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc,$2 ) ); }1675 FINALLY compound_statement { $$ = new StatementNode( build_finally( $2 ) ); } 1752 1676 ; 1753 1677 … … 1775 1699 asm_statement: 1776 1700 ASM asm_volatile_opt '(' string_literal ')' ';' 1777 { $$ = new StatementNode( build_asm( yylloc,$2, $4, nullptr ) ); }1701 { $$ = new StatementNode( build_asm( $2, $4, nullptr ) ); } 1778 1702 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC 1779 { $$ = new StatementNode( build_asm( yylloc,$2, $4, $6 ) ); }1703 { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); } 1780 1704 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';' 1781 { $$ = new StatementNode( build_asm( yylloc,$2, $4, $6, $8 ) ); }1705 { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); } 1782 1706 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';' 1783 { $$ = new StatementNode( build_asm( yylloc,$2, $4, $6, $8, $10 ) ); }1707 { $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); } 1784 1708 | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';' 1785 { $$ = new StatementNode( build_asm( yylloc,$2, $5, nullptr, $8, $10, $12 ) ); }1709 { $$ = new StatementNode( build_asm( $2, $5, nullptr, $8, $10, $12 ) ); } 1786 1710 ; 1787 1711 … … 1807 1731 asm_operand: // GCC 1808 1732 string_literal '(' constant_expression ')' 1809 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }1733 { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); } 1810 1734 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')' 1811 { 1812 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) ); 1813 delete $2.str; 1814 } 1735 { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); } 1815 1736 ; 1816 1737 … … 1819 1740 { $$ = nullptr; } // use default argument 1820 1741 | string_literal 1821 { $$ = $1; }1742 { $$ = new ExpressionNode( $1 ); } 1822 1743 | asm_clobbers_list_opt ',' string_literal 1823 { $$ = (ExpressionNode *)( $1->set_last( $3 )); }1744 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( $3 ) )); } 1824 1745 ; 1825 1746 … … 1827 1748 identifier 1828 1749 { 1829 $$ = new LabelNode(); $$->labels. emplace_back( yylloc,*$1 );1750 $$ = new LabelNode(); $$->labels.push_back( *$1 ); 1830 1751 delete $1; // allocated by lexer 1831 1752 } 1832 1753 | label_list ',' identifier 1833 1754 { 1834 $$ = $1; $1->labels. emplace_back( yylloc,*$3 );1755 $$ = $1; $1->labels.push_back( *$3 ); 1835 1756 delete $3; // allocated by lexer 1836 1757 } … … 1883 1804 { 1884 1805 // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" ); 1885 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {1806 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 1886 1807 // printf( "\tattr %s\n", attr->name.c_str() ); 1887 1808 // } // for … … 1893 1814 static_assert: 1894 1815 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1895 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 )); }1816 { $$ = DeclarationNode::newStaticAssert( $3, $5 ); } 1896 1817 | STATICASSERT '(' constant_expression ')' ';' // CFA 1897 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc,*new string( "\"\"" ) ) ); }1818 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); } 1898 1819 1899 1820 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function … … 2018 1939 TYPEDEF type_specifier declarator 2019 1940 { 1941 // if type_specifier is an anon aggregate => name 2020 1942 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" ); 2021 if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) { 2022 SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr; 2023 } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3 1943 $$ = $3->addType( $2 )->addTypedef(); 2024 1944 } 2025 1945 | typedef_declaration pop ',' push declarator … … 2029 1949 } 2030 1950 | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 ) 2031 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1951 { 1952 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" ); 1953 $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef(); 1954 } 2032 1955 | type_specifier TYPEDEF declarator 2033 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1956 { 1957 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" ); 1958 $$ = $3->addType( $1 )->addTypedef(); 1959 } 2034 1960 | type_specifier TYPEDEF type_qualifier_list declarator 2035 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1961 { 1962 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" ); 1963 $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 ); 1964 } 2036 1965 ; 2037 1966 … … 2040 1969 TYPEDEF identifier '=' assignment_expression 2041 1970 { 2042 SemanticError( yylloc, "T YPEDEFexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;1971 SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 2043 1972 } 2044 1973 | typedef_expression pop ',' push identifier '=' assignment_expression 2045 1974 { 2046 SemanticError( yylloc, "T YPEDEFexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;1975 SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 2047 1976 } 2048 1977 ; … … 2054 1983 | typedef_expression // deprecated GCC, naming expression type 2055 1984 | sue_declaration_specifier 2056 {2057 assert( $1->type );2058 if ( $1->type->qualifiers.any() ) { // CV qualifiers ?2059 SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr;2060 }2061 // enums are never empty declarations because there must have at least one enumeration.2062 if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?2063 SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;2064 }2065 }2066 1985 ; 2067 1986 … … 2069 1988 // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static 2070 1989 // storage-class 2071 variable_declarator asm_name_opt initializer_opt1990 declarator asm_name_opt initializer_opt 2072 1991 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); } 2073 | variable_type_redeclarator asm_name_opt initializer_opt2074 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }2075 2076 | general_function_declarator asm_name_opt2077 { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); }2078 | general_function_declarator asm_name_opt '=' VOID2079 { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); }2080 2081 1992 | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt 2082 1993 { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); } 2083 ;2084 2085 general_function_declarator:2086 function_type_redeclarator2087 | function_declarator2088 1994 ; 2089 1995 … … 2094 2000 | sue_declaration_specifier invalid_types 2095 2001 { 2096 SemanticError( yylloc, ::toString( "Missing ';' after end of ", 2097 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ), 2098 " declaration" ) ); 2002 SemanticError( yylloc, 2003 ::toString( "Missing ';' after end of ", 2004 $1->type->enumeration.name ? "enum" : AggregateDecl::aggrString( $1->type->aggregate.kind ), 2005 " declaration" ) ); 2099 2006 $$ = nullptr; 2100 2007 } … … 2121 2028 basic_type_specifier 2122 2029 | sue_type_specifier 2030 { 2031 // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2032 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2033 // printf( "\tattr %s\n", attr->name.c_str() ); 2034 // } // for 2035 } 2123 2036 | type_type_specifier 2124 2037 ; … … 2329 2242 { $$ = DeclarationNode::newTypeof( $3 ); } 2330 2243 | BASETYPEOF '(' type ')' // CFA: basetypeof( x ) y; 2331 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $3 ) ) ), true ); }2244 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); } 2332 2245 | BASETYPEOF '(' comma_expression ')' // CFA: basetypeof( a+b ) y; 2333 2246 { $$ = DeclarationNode::newTypeof( $3, true ); } … … 2342 2255 { 2343 2256 // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2344 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2257 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2345 2258 // printf( "\tattr %s\n", attr->name.c_str() ); 2346 2259 // } // for … … 2358 2271 { 2359 2272 // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2360 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2273 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2361 2274 // printf( "\tattr %s\n", attr->name.c_str() ); 2362 2275 // } // for … … 2436 2349 { 2437 2350 // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2438 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2351 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2439 2352 // printf( "\tattr %s\n", attr->name.c_str() ); 2440 2353 // } // for … … 2460 2373 '{' field_declaration_list_opt '}' type_parameters_opt 2461 2374 { 2375 // printf( "aggregate_type1 %s\n", $3.str->c_str() ); 2376 // if ( $2 ) 2377 // for ( Attribute * attr: reverseIterate( $2->attributes ) ) { 2378 // printf( "copySpecifiers12 %s\n", attr->name.c_str() ); 2379 // } // for 2462 2380 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); 2381 // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2382 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2383 // printf( "aggregate_type3 %s\n", attr->name.c_str() ); 2384 // } // for 2463 2385 } 2464 2386 | aggregate_key attribute_list_opt TYPEDEFname // unqualified type name … … 2469 2391 '{' field_declaration_list_opt '}' type_parameters_opt 2470 2392 { 2393 // printf( "AGG3\n" ); 2471 2394 DeclarationNode::newFromTypedef( $3 ); 2472 2395 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2479 2402 '{' field_declaration_list_opt '}' type_parameters_opt 2480 2403 { 2404 // printf( "AGG4\n" ); 2481 2405 DeclarationNode::newFromTypeGen( $3, nullptr ); 2482 2406 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2505 2429 // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and 2506 2430 // delete newFromTypeGen. 2507 if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) { 2508 $$ = $3->addQualifiers( $2 ); 2509 } else { 2510 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2511 $3->type->symbolic.name = nullptr; // copied to $$ 2512 $3->type->symbolic.actuals = nullptr; 2513 delete $3; 2514 } 2431 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2432 $3->type->symbolic.name = nullptr; 2433 $3->type->symbolic.actuals = nullptr; 2434 delete $3; 2515 2435 } 2516 2436 ; … … 2523 2443 aggregate_data: 2524 2444 STRUCT vtable_opt 2525 { $$ = ast::AggregateDecl::Struct; }2445 { $$ = AggregateDecl::Struct; } 2526 2446 | UNION 2527 { $$ = ast::AggregateDecl::Union; }2447 { $$ = AggregateDecl::Union; } 2528 2448 | EXCEPTION // CFA 2529 { $$ = ast::AggregateDecl::Exception; }2530 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }2449 { $$ = AggregateDecl::Exception; } 2450 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2531 2451 ; 2532 2452 2533 2453 aggregate_control: // CFA 2534 2454 MONITOR 2535 { $$ = ast::AggregateDecl::Monitor; }2455 { $$ = AggregateDecl::Monitor; } 2536 2456 | MUTEX STRUCT 2537 { $$ = ast::AggregateDecl::Monitor; }2457 { $$ = AggregateDecl::Monitor; } 2538 2458 | GENERATOR 2539 { $$ = ast::AggregateDecl::Generator; }2459 { $$ = AggregateDecl::Generator; } 2540 2460 | MUTEX GENERATOR 2541 { 2542 SemanticError( yylloc, "monitor generator is currently unimplemented." ); 2543 $$ = ast::AggregateDecl::NoAggregate; 2544 } 2461 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2545 2462 | COROUTINE 2546 { $$ = ast::AggregateDecl::Coroutine; }2463 { $$ = AggregateDecl::Coroutine; } 2547 2464 | MUTEX COROUTINE 2548 { 2549 SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); 2550 $$ = ast::AggregateDecl::NoAggregate; 2551 } 2465 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2552 2466 | THREAD 2553 { $$ = ast::AggregateDecl::Thread; }2467 { $$ = AggregateDecl::Thread; } 2554 2468 | MUTEX THREAD 2555 { 2556 SemanticError( yylloc, "monitor thread is currently unimplemented." ); 2557 $$ = ast::AggregateDecl::NoAggregate; 2558 } 2469 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2559 2470 ; 2560 2471 … … 2572 2483 $$ = fieldDecl( $1, $2 ); 2573 2484 // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2574 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2485 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2575 2486 // printf( "\tattr %s\n", attr->name.c_str() ); 2576 2487 // } // for … … 2579 2490 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); } 2580 2491 | STATIC type_specifier field_declaring_list_opt ';' // CFA 2581 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }2492 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; } 2582 2493 | INLINE type_specifier field_abstract_list_opt ';' // CFA 2583 2494 { … … 2590 2501 } 2591 2502 | INLINE aggregate_control ';' // CFA 2592 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }2503 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; } 2593 2504 | typedef_declaration ';' // CFA 2594 2505 | cfa_field_declaring_list ';' // CFA, new style field declaration … … 2616 2527 { $$ = $1->addBitfield( $2 ); } 2617 2528 | variable_type_redeclarator bit_subrange_size_opt 2618 // A semantic check is required to ensure bit_subrange only appears on integral types.2619 { $$ = $1->addBitfield( $2 ); }2620 | function_type_redeclarator bit_subrange_size_opt2621 2529 // A semantic check is required to ensure bit_subrange only appears on integral types. 2622 2530 { $$ = $1->addBitfield( $2 ); } … … 2673 2581 { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); } 2674 2582 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2675 {2676 if ( $3->storageClasses.val != 0 || $3->type->qualifiers. any())2583 { 2584 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) 2677 2585 { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2678 2586 … … 2681 2589 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt 2682 2590 { 2683 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." ); }2591 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." ); } 2684 2592 typedefTable.makeTypedef( *$6 ); 2685 2593 } … … 2849 2757 type_no_function: // sizeof, alignof, cast (constructor) 2850 2758 cfa_abstract_declarator_tuple // CFA 2851 | type_specifier // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing2759 | type_specifier 2852 2760 | type_specifier abstract_declarator 2853 2761 { $$ = $2->addType( $1 ); } … … 2894 2802 designator_list ':' // C99, CFA uses ":" instead of "=" 2895 2803 | identifier_at ':' // GCC, field name 2896 { $$ = new ExpressionNode( build_varref( yylloc,$1 ) ); }2804 { $$ = new ExpressionNode( build_varref( $1 ) ); } 2897 2805 ; 2898 2806 … … 2906 2814 designator: 2907 2815 '.' identifier_at // C99, field name 2908 { $$ = new ExpressionNode( build_varref( yylloc,$2 ) ); }2816 { $$ = new ExpressionNode( build_varref( $2 ) ); } 2909 2817 | '[' push assignment_expression pop ']' // C99, single array element 2910 2818 // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple. … … 2913 2821 { $$ = $3; } 2914 2822 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements 2915 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }2823 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); } 2916 2824 | '.' '[' push field_name_list pop ']' // CFA, tuple field selector 2917 2825 { $$ = $4; } … … 2953 2861 { 2954 2862 typedefTable.addToScope( *$2, TYPEDEFname, "9" ); 2955 if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }2956 if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }2957 if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }2863 if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); } 2864 if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); } 2865 if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); } 2958 2866 } 2959 2867 type_initializer_opt assertion_list_opt … … 2966 2874 { 2967 2875 typedefTable.addToScope( *$2, TYPEDIMname, "9" ); 2968 $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );2876 $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 ); 2969 2877 } 2970 2878 // | type_specifier identifier_parameter_declarator 2971 2879 | assertion_list 2972 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }2880 { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); } 2973 2881 ; 2974 2882 2975 2883 new_type_class: // CFA 2976 2884 // empty 2977 { $$ = ast::TypeDecl::Otype; }2885 { $$ = TypeDecl::Otype; } 2978 2886 | '&' 2979 { $$ = ast::TypeDecl::Dtype; }2887 { $$ = TypeDecl::Dtype; } 2980 2888 | '*' 2981 { $$ = ast::TypeDecl::DStype; } // dtype + sized2889 { $$ = TypeDecl::DStype; } // dtype + sized 2982 2890 // | '(' '*' ')' 2983 // { $$ = ast::TypeDecl::Ftype; }2891 // { $$ = TypeDecl::Ftype; } 2984 2892 | ELLIPSIS 2985 { $$ = ast::TypeDecl::Ttype; }2893 { $$ = TypeDecl::Ttype; } 2986 2894 ; 2987 2895 2988 2896 type_class: // CFA 2989 2897 OTYPE 2990 { $$ = ast::TypeDecl::Otype; }2898 { $$ = TypeDecl::Otype; } 2991 2899 | DTYPE 2992 { $$ = ast::TypeDecl::Dtype; }2900 { $$ = TypeDecl::Dtype; } 2993 2901 | FTYPE 2994 { $$ = ast::TypeDecl::Ftype; }2902 { $$ = TypeDecl::Ftype; } 2995 2903 | TTYPE 2996 { $$ = ast::TypeDecl::Ttype; }2904 { $$ = TypeDecl::Ttype; } 2997 2905 ; 2998 2906 … … 3020 2928 type_list: // CFA 3021 2929 type 3022 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $1 ) ) ); }2930 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); } 3023 2931 | assignment_expression 3024 2932 | type_list ',' type 3025 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $3 ) ) ) )); }2933 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); } 3026 2934 | type_list ',' assignment_expression 3027 2935 { $$ = (ExpressionNode *)( $1->set_last( $3 )); } … … 3060 2968 TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}' 3061 2969 { 3062 SemanticWarning( yylloc, Warning::DeprecTraitSyntax );2970 SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" ); 3063 2971 $$ = DeclarationNode::newTrait( $2, $4, nullptr ); 3064 2972 } … … 3067 2975 | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}' 3068 2976 { 3069 SemanticWarning( yylloc, Warning::DeprecTraitSyntax );2977 SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" ); 3070 2978 $$ = DeclarationNode::newTrait( $2, $4, $8 ); 3071 2979 } … … 3130 3038 external_definition: 3131 3039 DIRECTIVE 3132 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc,$1 ) ) ); }3040 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); } 3133 3041 | declaration 3134 {3135 // Variable declarations of anonymous types requires creating a unique type-name across multiple translation3136 // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is3137 // disallowed at the moment.3138 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {3139 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {3140 SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;3141 } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union3142 SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr;3143 }3144 }3145 }3146 3042 | IDENTIFIER IDENTIFIER 3147 3043 { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; } … … 3163 3059 } 3164 3060 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 3165 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc,false, $3, nullptr ) ) ); }3061 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, nullptr ) ) ); } 3166 3062 | EXTERN STRINGliteral 3167 3063 { 3168 3064 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3169 linkage = ast::Linkage::update( yylloc, linkage, $2 );3065 linkage = LinkageSpec::update( yylloc, linkage, $2 ); 3170 3066 } 3171 3067 up external_definition down … … 3178 3074 { 3179 3075 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3180 linkage = ast::Linkage::update( yylloc, linkage, $2 );3076 linkage = LinkageSpec::update( yylloc, linkage, $2 ); 3181 3077 } 3182 3078 '{' up external_definition_list_opt down '}' … … 3189 3085 | type_qualifier_list 3190 3086 { 3191 if ( $1->type->qualifiers. any()) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3087 if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3192 3088 if ( $1->type->forall ) forall = true; // remember generic type 3193 3089 } … … 3195 3091 { 3196 3092 distQual( $5, $1 ); 3197 forall = false;3093 forall = false; 3198 3094 $$ = $5; 3199 3095 } 3200 3096 | declaration_qualifier_list 3201 3097 { 3202 if ( $1->type && $1->type->qualifiers. any()) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3098 if ( $1->type && $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3203 3099 if ( $1->type && $1->type->forall ) forall = true; // remember generic type 3204 3100 } … … 3206 3102 { 3207 3103 distQual( $5, $1 ); 3208 forall = false;3104 forall = false; 3209 3105 $$ = $5; 3210 3106 } 3211 3107 | declaration_qualifier_list type_qualifier_list 3212 3108 { 3213 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." ); }3109 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." ); } 3214 3110 if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type 3215 3111 } … … 3217 3113 { 3218 3114 distQual( $6, $1->addQualifiers( $2 ) ); 3219 forall = false;3115 forall = false; 3220 3116 $$ = $6; 3221 3117 } … … 3261 3157 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 ); 3262 3158 } 3263 | declaration_specifier function_type_redeclarator with_clause_opt compound_statement3159 | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement 3264 3160 { 3265 3161 rebindForall( $1, $2 ); … … 3297 3193 | variable_type_redeclarator 3298 3194 | function_declarator 3299 | function_type_redeclarator3300 3195 ; 3301 3196 3302 3197 subrange: 3303 3198 constant_expression '~' constant_expression // CFA, integer subrange 3304 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }3199 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); } 3305 3200 ; 3306 3201 … … 3311 3206 { 3312 3207 DeclarationNode * name = new DeclarationNode(); 3313 name->asmName = maybeMoveBuild( $3 );3208 name->asmName = $3; 3314 3209 $$ = name->addQualifiers( $5 ); 3315 3210 } … … 3424 3319 | '(' attribute_list variable_ptr ')' array_dimension 3425 3320 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3426 | '(' variable_array ')' multi_array_dimension // redundant parenthesis3321 | '(' variable_array ')' multi_array_dimension // redundant parenthesis 3427 3322 { $$ = $2->addArray( $4 ); } 3428 3323 | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis … … 3548 3443 ; 3549 3444 3550 // This pattern parses a declaration for a variable that redefines a type name, e.g.:3445 // This pattern parses a declaration for a variable or function prototype that redefines a type name, e.g.: 3551 3446 // 3552 3447 // typedef int foo; … … 3554 3449 // int foo; // redefine typedef name in new scope 3555 3450 // } 3451 // 3452 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays 3453 // and functions versus pointers to arrays and functions. 3556 3454 3557 3455 paren_type: … … 3568 3466 paren_type attribute_list_opt 3569 3467 { $$ = $1->addQualifiers( $2 ); } 3570 | variable_type_ptr3571 | variable_type_array attribute_list_opt3468 | type_ptr 3469 | type_array attribute_list_opt 3572 3470 { $$ = $1->addQualifiers( $2 ); } 3573 | variable_type_function attribute_list_opt3471 | type_function attribute_list_opt 3574 3472 { $$ = $1->addQualifiers( $2 ); } 3575 3473 ; 3576 3474 3577 variable_type_ptr:3475 type_ptr: 3578 3476 ptrref_operator variable_type_redeclarator 3579 3477 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3580 3478 | ptrref_operator type_qualifier_list variable_type_redeclarator 3581 3479 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3582 | '(' variable_type_ptr ')' attribute_list_opt// redundant parenthesis3480 | '(' type_ptr ')' attribute_list_opt // redundant parenthesis 3583 3481 { $$ = $2->addQualifiers( $4 ); } 3584 | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis3482 | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis 3585 3483 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3586 3484 ; 3587 3485 3588 variable_type_array:3486 type_array: 3589 3487 paren_type array_dimension 3590 3488 { $$ = $1->addArray( $2 ); } 3591 | '(' variable_type_ptr ')' array_dimension3489 | '(' type_ptr ')' array_dimension 3592 3490 { $$ = $2->addArray( $4 ); } 3593 | '(' attribute_list variable_type_ptr ')' array_dimension3491 | '(' attribute_list type_ptr ')' array_dimension 3594 3492 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3595 | '(' variable_type_array ')' multi_array_dimension// redundant parenthesis3493 | '(' type_array ')' multi_array_dimension // redundant parenthesis 3596 3494 { $$ = $2->addArray( $4 ); } 3597 | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis3495 | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis 3598 3496 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3599 | '(' variable_type_array ')'// redundant parenthesis3497 | '(' type_array ')' // redundant parenthesis 3600 3498 { $$ = $2; } 3601 | '(' attribute_list variable_type_array ')'// redundant parenthesis3499 | '(' attribute_list type_array ')' // redundant parenthesis 3602 3500 { $$ = $3->addQualifiers( $2 ); } 3603 3501 ; 3604 3502 3605 variable_type_function: 3606 '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3607 { $$ = $2->addParamList( $6 ); } 3608 | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3609 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3610 | '(' variable_type_function ')' // redundant parenthesis 3611 { $$ = $2; } 3612 | '(' attribute_list variable_type_function ')' // redundant parenthesis 3613 { $$ = $3->addQualifiers( $2 ); } 3614 ; 3615 3616 // This pattern parses a declaration for a function prototype that redefines a type name. It precludes declaring an 3617 // array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to 3618 // arrays and functions. 3619 3620 function_type_redeclarator: 3621 function_type_no_ptr attribute_list_opt 3622 { $$ = $1->addQualifiers( $2 ); } 3623 | function_type_ptr 3624 | function_type_array attribute_list_opt 3625 { $$ = $1->addQualifiers( $2 ); } 3626 ; 3627 3628 function_type_no_ptr: 3503 type_function: 3629 3504 paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3630 3505 { $$ = $1->addParamList( $4 ); } 3631 | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')'3506 | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3632 3507 { $$ = $2->addParamList( $6 ); } 3633 | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')'3508 | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3634 3509 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3635 | '(' function_type_no_ptr ')'// redundant parenthesis3510 | '(' type_function ')' // redundant parenthesis 3636 3511 { $$ = $2; } 3637 | '(' attribute_list function_type_no_ptr ')' // redundant parenthesis 3638 { $$ = $3->addQualifiers( $2 ); } 3639 ; 3640 3641 function_type_ptr: 3642 ptrref_operator function_type_redeclarator 3643 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3644 | ptrref_operator type_qualifier_list function_type_redeclarator 3645 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3646 | '(' function_type_ptr ')' attribute_list_opt 3647 { $$ = $2->addQualifiers( $4 ); } 3648 | '(' attribute_list function_type_ptr ')' attribute_list_opt 3649 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3650 ; 3651 3652 function_type_array: 3653 '(' function_type_ptr ')' array_dimension 3654 { $$ = $2->addArray( $4 ); } 3655 | '(' attribute_list function_type_ptr ')' array_dimension 3656 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3657 | '(' function_type_array ')' multi_array_dimension // redundant parenthesis 3658 { $$ = $2->addArray( $4 ); } 3659 | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis 3660 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3661 | '(' function_type_array ')' // redundant parenthesis 3662 { $$ = $2; } 3663 | '(' attribute_list function_type_array ')' // redundant parenthesis 3512 | '(' attribute_list type_function ')' // redundant parenthesis 3664 3513 { $$ = $3->addQualifiers( $2 ); } 3665 3514 ; … … 3831 3680 array_type_list: 3832 3681 basic_type_name 3833 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $1 ) ) ); }3682 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); } 3834 3683 | type_name 3835 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $1 ) ) ); }3684 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); } 3836 3685 | assignment_expression upupeq assignment_expression 3837 3686 | array_type_list ',' basic_type_name 3838 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $3 ) ) ) )); }3839 | array_type_list ',' type_name 3840 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc,maybeMoveBuildType( $3 ) ) ) )); }3687 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); } 3688 | array_type_list ',' type_name 3689 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); } 3841 3690 | array_type_list ',' assignment_expression upupeq assignment_expression 3842 3691 ; … … 3847 3696 | ErangeUpEq 3848 3697 { $$ = OperKinds::LEThan; } 3849 ;3698 ; 3850 3699 3851 3700 multi_array_dimension: -
src/Parser/parserutility.cc
rb110bcc r2ed94a9 10 10 // Created On : Sat May 16 15:30:39 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 1 10:42:00 202313 // Update Count : 912 // Last Modified On : Tus Jul 18 10:12:00 2017 13 // Update Count : 8 14 14 // 15 15 … … 19 19 #include <string> // for string 20 20 21 #include "AST/Expr.hpp" // for UntypedExpr, CastExpr, ConstantExpr 22 #include "AST/Type.hpp" // for BasicType, ZeroType, BasicType::Kind... 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... 23 24 24 25 // rewrite … … 27 28 // if ( (int)(x != 0) ) ... 28 29 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 ); 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 ) ); 44 36 } 45 37 -
src/Parser/parserutility.h
rb110bcc r2ed94a9 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // parserutility.h -- Collected utilities for the parser.7 // parserutility.h -- 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:31:46 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 4 14:03:00 202313 // Update Count : 711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:32:58 2017 13 // Update Count : 4 14 14 // 15 15 16 16 #pragma once 17 17 18 #include "AST/Copy.hpp" // for shallowCopy 19 namespace ast { 20 class Expr; 21 } 18 class Expression; 22 19 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 } 20 Expression *notZeroExpr( Expression *orig ); 41 21 42 22 // Local Variables: // -
src/ResolvExpr/Candidate.cpp
rb110bcc r2ed94a9 17 17 18 18 #include <iostream> 19 #include <sstream>20 19 21 20 #include "AST/Print.hpp" … … 45 44 sorted.reserve(cands.size()); 46 45 for(const auto & c : cands) { 47 std:: ostringstream ss;46 std::stringstream ss; 48 47 print( ss, *c, indent ); 49 48 sorted.push_back(ss.str()); -
src/ResolvExpr/CandidateFinder.cpp
rb110bcc r2ed94a9 55 55 namespace ResolvExpr { 56 56 57 /// Unique identifier for matching expression resolutions to their requesting expression58 UniqueId globalResnSlot = 0;59 60 namespace {61 /// First index is which argument, second is which alternative, third is which exploded element62 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;63 64 /// Returns a list of alternatives with the minimum cost in the given list65 CandidateList findMinCost( const CandidateList & candidates ) {66 CandidateList out;67 Cost minCost = Cost::infinity;68 for ( const CandidateRef & r : candidates ) {69 if ( r->cost < minCost ) {70 minCost = r->cost;71 out.clear();72 out.emplace_back( r );73 } else if ( r->cost == minCost ) {74 out.emplace_back( r );75 }76 }77 return out;78 }79 80 /// Computes conversion cost for a given expression to a given type81 const ast::Expr * computeExpressionConversionCost(82 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost83 ) {84 Cost convCost = computeConversionCost(85 arg->result, paramType, arg->get_lvalue(), symtab, env );86 outCost += convCost;87 88 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires89 // conversion. Ignore poly cost for now, since this requires resolution of the cast to90 // infer parameters and this does not currently work for the reason stated below91 Cost tmpCost = convCost;92 tmpCost.incPoly( -tmpCost.get_polyCost() );93 if ( tmpCost != Cost::zero ) {94 ast::ptr< ast::Type > newType = paramType;95 env.apply( newType );96 return new ast::CastExpr{ arg, newType };97 98 // xxx - *should* be able to resolve this cast, but at the moment pointers are not99 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,100 // once this is fixed it should be possible to resolve the cast.101 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,102 // but it shouldn't be because this makes the conversion from DT* to DT* since103 // commontype(zero_t, DT*) is DT*, rather than nothing104 105 // CandidateFinder finder{ symtab, env };106 // finder.find( arg, ResolvMode::withAdjustment() );107 // assertf( finder.candidates.size() > 0,108 // "Somehow castable expression failed to find alternatives." );109 // assertf( finder.candidates.size() == 1,110 // "Somehow got multiple alternatives for known cast expression." );111 // return finder.candidates.front()->expr;112 }113 114 return arg;115 }116 117 /// Computes conversion cost for a given candidate118 Cost computeApplicationConversionCost(119 CandidateRef cand, const ast::SymbolTable & symtab120 ) {121 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();122 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();123 auto function = pointer->base.strict_as< ast::FunctionType >();124 125 Cost convCost = Cost::zero;126 const auto & params = function->params;127 auto param = params.begin();128 auto & args = appExpr->args;129 130 for ( unsigned i = 0; i < args.size(); ++i ) {131 const ast::Type * argType = args[i]->result;132 PRINT(133 std::cerr << "arg expression:" << std::endl;134 ast::print( std::cerr, args[i], 2 );135 std::cerr << "--- results are" << std::endl;136 ast::print( std::cerr, argType, 2 );137 )138 139 if ( param == params.end() ) {140 if ( function->isVarArgs ) {141 convCost.incUnsafe();142 PRINT( std::cerr << "end of params with varargs function: inc unsafe: "143 << convCost << std::endl; ; )144 // convert reference-typed expressions into value-typed expressions145 cand->expr = ast::mutate_field_index(146 appExpr, &ast::ApplicationExpr::args, i,147 referenceToRvalueConversion( args[i], convCost ) );148 continue;149 } else return Cost::infinity;150 }151 152 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) {153 // Default arguments should be free - don't include conversion cost.154 // Unwrap them here because they are not relevant to the rest of the system155 cand->expr = ast::mutate_field_index(156 appExpr, &ast::ApplicationExpr::args, i, def->expr );157 ++param;158 continue;159 }160 161 // mark conversion cost and also specialization cost of param type162 // const ast::Type * paramType = (*param)->get_type();163 cand->expr = ast::mutate_field_index(164 appExpr, &ast::ApplicationExpr::args, i,165 computeExpressionConversionCost(166 args[i], *param, symtab, cand->env, convCost ) );167 convCost.decSpec( specCost( *param ) );168 ++param; // can't be in for-loop update because of the continue169 }170 171 if ( param != params.end() ) return Cost::infinity;172 173 // specialization cost of return types can't be accounted for directly, it disables174 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:175 //176 // forall(otype OS) {177 // void ?|?(OS&, int); // with newline178 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization179 // }180 181 // mark type variable and specialization cost of forall clause182 convCost.incVar( function->forall.size() );183 convCost.decSpec( function->assertions.size() );184 185 return convCost;186 }187 188 void makeUnifiableVars(189 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,190 ast::AssertionSet & need191 ) {192 for ( auto & tyvar : type->forall ) {193 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base };194 }195 for ( auto & assn : type->assertions ) {196 need[ assn ].isUsed = true;197 }198 }199 200 /// Gets a default value from an initializer, nullptr if not present201 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) {202 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) {203 if ( auto ce = si->value.as< ast::CastExpr >() ) {204 return ce->arg.as< ast::ConstantExpr >();205 } else {206 return si->value.as< ast::ConstantExpr >();207 }208 }209 return nullptr;210 }211 212 /// State to iteratively build a match of parameter expressions to arguments213 struct ArgPack {214 std::size_t parent; ///< Index of parent pack215 ast::ptr< ast::Expr > expr; ///< The argument stored here216 Cost cost; ///< The cost of this argument217 ast::TypeEnvironment env; ///< Environment for this pack218 ast::AssertionSet need; ///< Assertions outstanding for this pack219 ast::AssertionSet have; ///< Assertions found for this pack220 ast::OpenVarSet open; ///< Open variables for this pack221 unsigned nextArg; ///< Index of next argument in arguments list222 unsigned tupleStart; ///< Number of tuples that start at this index223 unsigned nextExpl; ///< Index of next exploded element224 unsigned explAlt; ///< Index of alternative for nextExpl > 0225 226 ArgPack()227 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),228 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}229 230 ArgPack(231 const ast::TypeEnvironment & env, const ast::AssertionSet & need,232 const ast::AssertionSet & have, const ast::OpenVarSet & open )233 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),234 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}235 236 ArgPack(237 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,238 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,239 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,240 unsigned nextExpl = 0, unsigned explAlt = 0 )241 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),242 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),243 nextExpl( nextExpl ), explAlt( explAlt ) {}244 245 ArgPack(246 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,247 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )248 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),249 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),250 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}251 252 /// true if this pack is in the middle of an exploded argument253 bool hasExpl() const { return nextExpl > 0; }254 255 /// Gets the list of exploded candidates for this pack256 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {257 return args[ nextArg-1 ][ explAlt ];258 }259 260 /// Ends a tuple expression, consolidating the appropriate args261 void endTuple( const std::vector< ArgPack > & packs ) {262 // add all expressions in tuple to list, summing cost263 std::deque< const ast::Expr * > exprs;264 const ArgPack * pack = this;265 if ( expr ) { exprs.emplace_front( expr ); }266 while ( pack->tupleStart == 0 ) {267 pack = &packs[pack->parent];268 exprs.emplace_front( pack->expr );269 cost += pack->cost;270 }271 // reset pack to appropriate tuple272 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );273 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };274 tupleStart = pack->tupleStart - 1;275 parent = pack->parent;276 }277 };278 279 /// Instantiates an argument to match a parameter, returns false if no matching results left280 bool instantiateArgument(281 const CodeLocation & location,282 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,283 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,284 unsigned nTuples = 0285 ) {286 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {287 // paramType is a TupleType -- group args into a TupleExpr288 ++nTuples;289 for ( const ast::Type * type : *tupleType ) {290 // xxx - dropping initializer changes behaviour from previous, but seems correct291 // ^^^ need to handle the case where a tuple has a default argument292 if ( ! instantiateArgument( location,293 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;294 nTuples = 0;295 }296 // re-constitute tuples for final generation297 for ( auto i = genStart; i < results.size(); ++i ) {298 results[i].endTuple( results );299 }300 return true;301 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {302 // paramType is a ttype, consumes all remaining arguments303 304 // completed tuples; will be spliced to end of results to finish305 std::vector< ArgPack > finalResults{};306 307 // iterate until all results completed308 std::size_t genEnd;309 ++nTuples;310 do {311 genEnd = results.size();312 313 // add another argument to results314 for ( std::size_t i = genStart; i < genEnd; ++i ) {315 unsigned nextArg = results[i].nextArg;316 317 // use next element of exploded tuple if present318 if ( results[i].hasExpl() ) {319 const ExplodedArg & expl = results[i].getExpl( args );320 321 unsigned nextExpl = results[i].nextExpl + 1;322 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }323 324 results.emplace_back(325 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),326 copy( results[i].need ), copy( results[i].have ),327 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,328 results[i].explAlt );329 330 continue;331 }332 333 // finish result when out of arguments334 if ( nextArg >= args.size() ) {335 ArgPack newResult{336 results[i].env, results[i].need, results[i].have, results[i].open };337 newResult.nextArg = nextArg;338 const ast::Type * argType = nullptr;339 340 if ( nTuples > 0 || ! results[i].expr ) {341 // first iteration or no expression to clone,342 // push empty tuple expression343 newResult.parent = i;344 newResult.expr = new ast::TupleExpr( location, {} );345 argType = newResult.expr->result;346 } else {347 // clone result to collect tuple348 newResult.parent = results[i].parent;349 newResult.cost = results[i].cost;350 newResult.tupleStart = results[i].tupleStart;351 newResult.expr = results[i].expr;352 argType = newResult.expr->result;353 354 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {355 // the case where a ttype value is passed directly is special,356 // e.g. for argument forwarding purposes357 // xxx - what if passing multiple arguments, last of which is358 // ttype?359 // xxx - what would happen if unify was changed so that unifying360 // tuple361 // types flattened both before unifying lists? then pass in362 // TupleType (ttype) below.363 --newResult.tupleStart;364 } else {365 // collapse leftover arguments into tuple366 newResult.endTuple( results );367 argType = newResult.expr->result;368 }369 }370 371 // check unification for ttype before adding to final372 if (373 unify(374 ttype, argType, newResult.env, newResult.need, newResult.have,375 newResult.open, symtab )376 ) {377 finalResults.emplace_back( std::move( newResult ) );378 }379 380 continue;381 }382 383 // add each possible next argument384 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {385 const ExplodedArg & expl = args[nextArg][j];386 387 // fresh copies of parent parameters for this iteration388 ast::TypeEnvironment env = results[i].env;389 ast::OpenVarSet open = results[i].open;390 391 env.addActual( expl.env, open );392 393 // skip empty tuple arguments by (nearly) cloning parent into next gen394 if ( expl.exprs.empty() ) {395 results.emplace_back(396 results[i], std::move( env ), copy( results[i].need ),397 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );398 399 continue;400 }401 402 // add new result403 results.emplace_back(404 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),405 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,406 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );407 }408 }409 410 // reset for next round411 genStart = genEnd;412 nTuples = 0;413 } while ( genEnd != results.size() );414 415 // splice final results onto results416 for ( std::size_t i = 0; i < finalResults.size(); ++i ) {417 results.emplace_back( std::move( finalResults[i] ) );418 }419 return ! finalResults.empty();420 }421 422 // iterate each current subresult423 std::size_t genEnd = results.size();424 for ( std::size_t i = genStart; i < genEnd; ++i ) {425 unsigned nextArg = results[i].nextArg;426 427 // use remainder of exploded tuple if present428 if ( results[i].hasExpl() ) {429 const ExplodedArg & expl = results[i].getExpl( args );430 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ];431 432 ast::TypeEnvironment env = results[i].env;433 ast::AssertionSet need = results[i].need, have = results[i].have;434 ast::OpenVarSet open = results[i].open;435 436 const ast::Type * argType = expr->result;437 438 PRINT(439 std::cerr << "param type is ";440 ast::print( std::cerr, paramType );441 std::cerr << std::endl << "arg type is ";442 ast::print( std::cerr, argType );443 std::cerr << std::endl;444 )445 446 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {447 unsigned nextExpl = results[i].nextExpl + 1;448 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }449 450 results.emplace_back(451 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,452 nTuples, Cost::zero, nextExpl, results[i].explAlt );453 }454 455 continue;456 }457 458 // use default initializers if out of arguments459 if ( nextArg >= args.size() ) {460 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) {461 ast::TypeEnvironment env = results[i].env;462 ast::AssertionSet need = results[i].need, have = results[i].have;463 ast::OpenVarSet open = results[i].open;464 465 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {466 results.emplace_back(467 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),468 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );469 }470 }471 472 continue;473 }474 475 // Check each possible next argument476 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {477 const ExplodedArg & expl = args[nextArg][j];478 479 // fresh copies of parent parameters for this iteration480 ast::TypeEnvironment env = results[i].env;481 ast::AssertionSet need = results[i].need, have = results[i].have;482 ast::OpenVarSet open = results[i].open;483 484 env.addActual( expl.env, open );485 486 // skip empty tuple arguments by (nearly) cloning parent into next gen487 if ( expl.exprs.empty() ) {488 results.emplace_back(489 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),490 nextArg + 1, expl.cost );491 492 continue;493 }494 495 // consider only first exploded arg496 const ast::Expr * expr = expl.exprs.front();497 const ast::Type * argType = expr->result;498 499 PRINT(500 std::cerr << "param type is ";501 ast::print( std::cerr, paramType );502 std::cerr << std::endl << "arg type is ";503 ast::print( std::cerr, argType );504 std::cerr << std::endl;505 )506 507 // attempt to unify types508 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {509 // add new result510 results.emplace_back(511 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),512 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );513 }514 }515 }516 517 // reset for next parameter518 genStart = genEnd;519 520 return genEnd != results.size(); // were any new results added?521 }522 523 /// Generate a cast expression from `arg` to `toType`524 const ast::Expr * restructureCast(525 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast526 ) {527 if (528 arg->result->size() > 1529 && ! toType->isVoid()530 && ! dynamic_cast< const ast::ReferenceType * >( toType )531 ) {532 // Argument is a tuple and the target type is neither void nor a reference. Cast each533 // member of the tuple to its corresponding target type, producing the tuple of those534 // cast expressions. If there are more components of the tuple than components in the535 // target type, then excess components do not come out in the result expression (but536 // UniqueExpr ensures that the side effects will still be produced)537 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {538 // expressions which may contain side effects require a single unique instance of539 // the expression540 arg = new ast::UniqueExpr{ arg->location, arg };541 }542 std::vector< ast::ptr< ast::Expr > > components;543 for ( unsigned i = 0; i < toType->size(); ++i ) {544 // cast each component545 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };546 components.emplace_back(547 restructureCast( idx, toType->getComponent( i ), isGenerated ) );548 }549 return new ast::TupleExpr{ arg->location, std::move( components ) };550 } else {551 // handle normally552 return new ast::CastExpr{ arg->location, arg, toType, isGenerated };553 }554 }555 556 /// Gets the name from an untyped member expression (must be NameExpr)557 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {558 if ( memberExpr->member.as< ast::ConstantExpr >() ) {559 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );560 }561 562 return memberExpr->member.strict_as< ast::NameExpr >()->name;563 }564 565 /// Actually visits expressions to find their candidate interpretations566 class Finder final : public ast::WithShortCircuiting {567 const ResolveContext & context;568 const ast::SymbolTable & symtab;569 public:570 // static size_t traceId;571 CandidateFinder & selfFinder;572 CandidateList & candidates;573 const ast::TypeEnvironment & tenv;574 ast::ptr< ast::Type > & targetType;575 576 enum Errors {577 NotFound,578 NoMatch,579 ArgsToFew,580 ArgsToMany,581 RetsToFew,582 RetsToMany,583 NoReason584 };585 586 struct {587 Errors code = NotFound;588 } reason;589 590 Finder( CandidateFinder & f )591 : context( f.context ), symtab( context.symtab ), selfFinder( f ),592 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}593 594 void previsit( const ast::Node * ) { visit_children = false; }595 596 /// Convenience to add candidate to list597 template<typename... Args>598 void addCandidate( Args &&... args ) {599 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );600 reason.code = NoReason;601 }602 603 void postvisit( const ast::ApplicationExpr * applicationExpr ) {604 addCandidate( applicationExpr, tenv );605 }606 607 /// Set up candidate assertions for inference608 void inferParameters( CandidateRef & newCand, CandidateList & out );609 610 /// Completes a function candidate with arguments located611 void validateFunctionCandidate(612 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,613 CandidateList & out );614 615 /// Builds a list of candidates for a function, storing them in out616 void makeFunctionCandidates(617 const CodeLocation & location,618 const CandidateRef & func, const ast::FunctionType * funcType,619 const ExplodedArgs_new & args, CandidateList & out );620 621 /// Adds implicit struct-conversions to the alternative list622 void addAnonConversions( const CandidateRef & cand );623 624 /// Adds aggregate member interpretations625 void addAggMembers(626 const ast::BaseInstType * aggrInst, const ast::Expr * expr,627 const Candidate & cand, const Cost & addedCost, const std::string & name628 );629 630 /// Adds tuple member interpretations631 void addTupleMembers(632 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,633 const Cost & addedCost, const ast::Expr * member634 );635 636 /// true if expression is an lvalue637 static bool isLvalue( const ast::Expr * x ) {638 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );639 }640 641 void postvisit( const ast::UntypedExpr * untypedExpr );642 void postvisit( const ast::VariableExpr * variableExpr );643 void postvisit( const ast::ConstantExpr * constantExpr );644 void postvisit( const ast::SizeofExpr * sizeofExpr );645 void postvisit( const ast::AlignofExpr * alignofExpr );646 void postvisit( const ast::AddressExpr * addressExpr );647 void postvisit( const ast::LabelAddressExpr * labelExpr );648 void postvisit( const ast::CastExpr * castExpr );649 void postvisit( const ast::VirtualCastExpr * castExpr );650 void postvisit( const ast::KeywordCastExpr * castExpr );651 void postvisit( const ast::UntypedMemberExpr * memberExpr );652 void postvisit( const ast::MemberExpr * memberExpr );653 void postvisit( const ast::NameExpr * nameExpr );654 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr );655 void postvisit( const ast::OffsetofExpr * offsetofExpr );656 void postvisit( const ast::OffsetPackExpr * offsetPackExpr );657 void postvisit( const ast::LogicalExpr * logicalExpr );658 void postvisit( const ast::ConditionalExpr * conditionalExpr );659 void postvisit( const ast::CommaExpr * commaExpr );660 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr );661 void postvisit( const ast::ConstructorExpr * ctorExpr );662 void postvisit( const ast::RangeExpr * rangeExpr );663 void postvisit( const ast::UntypedTupleExpr * tupleExpr );664 void postvisit( const ast::TupleExpr * tupleExpr );665 void postvisit( const ast::TupleIndexExpr * tupleExpr );666 void postvisit( const ast::TupleAssignExpr * tupleExpr );667 void postvisit( const ast::UniqueExpr * unqExpr );668 void postvisit( const ast::StmtExpr * stmtExpr );669 void postvisit( const ast::UntypedInitExpr * initExpr );670 671 void postvisit( const ast::InitExpr * ) {672 assertf( false, "CandidateFinder should never see a resolved InitExpr." );673 }674 675 void postvisit( const ast::DeletedExpr * ) {676 assertf( false, "CandidateFinder should never see a DeletedExpr." );677 }678 679 void postvisit( const ast::GenericExpr * ) {680 assertf( false, "_Generic is not yet supported." );681 }682 };683 684 /// Set up candidate assertions for inference685 void Finder::inferParameters( CandidateRef & newCand, CandidateList & out ) {686 // Set need bindings for any unbound assertions687 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions688 for ( auto & assn : newCand->need ) {689 // skip already-matched assertions690 if ( assn.second.resnSlot != 0 ) continue;691 // assign slot for expression if needed692 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }693 // fix slot to assertion694 assn.second.resnSlot = crntResnSlot;695 }696 // pair slot to expression697 if ( crntResnSlot != 0 ) {698 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );699 }700 701 // add to output list; assertion satisfaction will occur later702 out.emplace_back( newCand );703 }704 705 /// Completes a function candidate with arguments located706 void Finder::validateFunctionCandidate(707 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,708 CandidateList & out709 ) {710 ast::ApplicationExpr * appExpr =711 new ast::ApplicationExpr{ func->expr->location, func->expr };712 // sum cost and accumulate arguments713 std::deque< const ast::Expr * > args;714 Cost cost = func->cost;715 const ArgPack * pack = &result;716 while ( pack->expr ) {717 args.emplace_front( pack->expr );718 cost += pack->cost;719 pack = &results[pack->parent];720 }721 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );722 appExpr->args = std::move( vargs );723 // build and validate new candidate724 auto newCand =725 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );726 PRINT(727 std::cerr << "instantiate function success: " << appExpr << std::endl;728 std::cerr << "need assertions:" << std::endl;729 ast::print( std::cerr, result.need, 2 );730 )731 inferParameters( newCand, out );732 }733 734 /// Builds a list of candidates for a function, storing them in out735 void Finder::makeFunctionCandidates(736 const CodeLocation & location,737 const CandidateRef & func, const ast::FunctionType * funcType,738 const ExplodedArgs_new & args, CandidateList & out739 ) {740 ast::OpenVarSet funcOpen;741 ast::AssertionSet funcNeed, funcHave;742 ast::TypeEnvironment funcEnv{ func->env };743 makeUnifiableVars( funcType, funcOpen, funcNeed );744 // add all type variables as open variables now so that those not used in the745 // parameter list are still considered open746 funcEnv.add( funcType->forall );747 748 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {749 // attempt to narrow based on expected target type750 const ast::Type * returnType = funcType->returns.front();751 if ( ! unify(752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )753 ) {754 // unification failed, do not pursue this candidate755 return;756 }757 }758 759 // iteratively build matches, one parameter at a time760 std::vector< ArgPack > results;761 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen );762 std::size_t genStart = 0;763 764 // xxx - how to handle default arg after change to ftype representation?765 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {766 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {767 // function may have default args only if directly calling by name768 // must use types on candidate however, due to RenameVars substitution769 auto nParams = funcType->params.size();770 771 for (size_t i=0; i<nParams; ++i) {772 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();773 if (!instantiateArgument( location,774 funcType->params[i], obj->init, args, results, genStart, symtab)) return;775 }776 goto endMatch;777 }778 }779 for ( const auto & param : funcType->params ) {780 // Try adding the arguments corresponding to the current parameter to the existing781 // matches782 // no default args for indirect calls783 if ( ! instantiateArgument( location,784 param, nullptr, args, results, genStart, symtab ) ) return;785 }786 787 endMatch:788 if ( funcType->isVarArgs ) {789 // append any unused arguments to vararg pack790 std::size_t genEnd;791 do {792 genEnd = results.size();793 794 // iterate results795 for ( std::size_t i = genStart; i < genEnd; ++i ) {796 unsigned nextArg = results[i].nextArg;797 798 // use remainder of exploded tuple if present799 if ( results[i].hasExpl() ) {800 const ExplodedArg & expl = results[i].getExpl( args );801 802 unsigned nextExpl = results[i].nextExpl + 1;803 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }804 805 results.emplace_back(806 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),807 copy( results[i].need ), copy( results[i].have ),808 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl,809 results[i].explAlt );810 811 continue;812 }813 814 // finish result when out of arguments815 if ( nextArg >= args.size() ) {816 validateFunctionCandidate( func, results[i], results, out );817 818 continue;819 }820 821 // add each possible next argument822 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {823 const ExplodedArg & expl = args[nextArg][j];824 825 // fresh copies of parent parameters for this iteration826 ast::TypeEnvironment env = results[i].env;827 ast::OpenVarSet open = results[i].open;828 829 env.addActual( expl.env, open );830 831 // skip empty tuple arguments by (nearly) cloning parent into next gen832 if ( expl.exprs.empty() ) {833 results.emplace_back(834 results[i], std::move( env ), copy( results[i].need ),835 copy( results[i].have ), std::move( open ), nextArg + 1,836 expl.cost );837 838 continue;839 }840 841 // add new result842 results.emplace_back(843 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),844 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,845 expl.exprs.size() == 1 ? 0 : 1, j );846 }847 }848 849 genStart = genEnd;850 } while( genEnd != results.size() );851 } else {852 // filter out the results that don't use all the arguments853 for ( std::size_t i = genStart; i < results.size(); ++i ) {854 ArgPack & result = results[i];855 if ( ! result.hasExpl() && result.nextArg >= args.size() ) {856 validateFunctionCandidate( func, result, results, out );857 }858 }859 }860 }861 862 /// Adds implicit struct-conversions to the alternative list863 void Finder::addAnonConversions( const CandidateRef & cand ) {864 // adds anonymous member interpretations whenever an aggregate value type is seen.865 // it's okay for the aggregate expression to have reference type -- cast it to the866 // base type to treat the aggregate as the referenced value867 ast::ptr< ast::Expr > aggrExpr( cand->expr );868 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;869 cand->env.apply( aggrType );870 871 if ( aggrType.as< ast::ReferenceType >() ) {872 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };873 }874 875 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {876 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );877 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {878 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );879 }880 }881 882 /// Adds aggregate member interpretations883 void Finder::addAggMembers(884 const ast::BaseInstType * aggrInst, const ast::Expr * expr,885 const Candidate & cand, const Cost & addedCost, const std::string & name886 ) {887 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {888 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );889 CandidateRef newCand = std::make_shared<Candidate>(890 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );891 // add anonymous member interpretations whenever an aggregate value type is seen892 // as a member expression893 addAnonConversions( newCand );894 candidates.emplace_back( std::move( newCand ) );895 }896 }897 898 /// Adds tuple member interpretations899 void Finder::addTupleMembers(900 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,901 const Cost & addedCost, const ast::Expr * member902 ) {903 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {904 // get the value of the constant expression as an int, must be between 0 and the905 // length of the tuple to have meaning906 long long val = constantExpr->intValue();907 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {908 addCandidate(909 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },910 addedCost );911 }912 }913 }914 915 void Finder::postvisit( const ast::UntypedExpr * untypedExpr ) {916 std::vector< CandidateFinder > argCandidates =917 selfFinder.findSubExprs( untypedExpr->args );918 919 // take care of possible tuple assignments920 // if not tuple assignment, handled as normal function call921 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );922 923 CandidateFinder funcFinder( context, tenv );924 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {925 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);926 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {927 assertf(!argCandidates.empty(), "special function call without argument");928 for (auto & firstArgCand: argCandidates[0]) {929 ast::ptr<ast::Type> argType = firstArgCand->expr->result;930 firstArgCand->env.apply(argType);931 // strip references932 // xxx - is this correct?933 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;934 935 // convert 1-tuple to plain type936 if (auto tuple = argType.as<ast::TupleType>()) {937 if (tuple->size() == 1) {938 argType = tuple->types[0];939 }940 }941 942 // if argType is an unbound type parameter, all special functions need to be searched.943 if (isUnboundType(argType)) {944 funcFinder.otypeKeys.clear();945 break;946 }947 948 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);949 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {950 // const ast::EnumDecl * enumDecl = enumInst->base; // Here951 // if ( const ast::Type* enumType = enumDecl->base ) {952 // // instance of enum (T) is a instance of type (T)953 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));954 // } else {955 // // instance of an untyped enum is techically int956 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));957 // }958 // }959 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));960 }961 }962 }963 // if candidates are already produced, do not fail964 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?965 // this means there exists ctor/assign functions with a tuple as first parameter.966 ResolvMode mode = {967 true, // adjust968 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name969 selfFinder.candidates.empty() // failfast if other options are not found970 };971 funcFinder.find( untypedExpr->func, mode );972 // short-circuit if no candidates973 // if ( funcFinder.candidates.empty() ) return;974 975 reason.code = NoMatch;976 977 // find function operators978 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}979 CandidateFinder opFinder( context, tenv );980 // okay if there aren't any function operations981 opFinder.find( opExpr, ResolvMode::withoutFailFast() );982 PRINT(983 std::cerr << "known function ops:" << std::endl;984 print( std::cerr, opFinder.candidates, 1 );985 )986 987 // pre-explode arguments988 ExplodedArgs_new argExpansions;989 for ( const CandidateFinder & args : argCandidates ) {990 argExpansions.emplace_back();991 auto & argE = argExpansions.back();992 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }993 }994 995 // Find function matches996 CandidateList found;997 SemanticErrorException errors;998 for ( CandidateRef & func : funcFinder ) {999 try {1000 PRINT(1001 std::cerr << "working on alternative:" << std::endl;1002 print( std::cerr, *func, 2 );1003 )1004 1005 // check if the type is a pointer to function1006 const ast::Type * funcResult = func->expr->result->stripReferences();1007 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {1008 if ( auto function = pointer->base.as< ast::FunctionType >() ) {1009 CandidateRef newFunc{ new Candidate{ *func } };1010 newFunc->expr =1011 referenceToRvalueConversion( newFunc->expr, newFunc->cost );1012 makeFunctionCandidates( untypedExpr->location,1013 newFunc, function, argExpansions, found );1014 }1015 } else if (1016 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )1017 ) {1018 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {1019 if ( auto function = clz->bound.as< ast::FunctionType >() ) {1020 CandidateRef newFunc{ new Candidate{ *func } };1021 newFunc->expr =1022 referenceToRvalueConversion( newFunc->expr, newFunc->cost );1023 makeFunctionCandidates( untypedExpr->location,1024 newFunc, function, argExpansions, found );1025 }1026 }1027 }1028 } catch ( SemanticErrorException & e ) { errors.append( e ); }1029 }1030 1031 // Find matches on function operators `?()`1032 if ( ! opFinder.candidates.empty() ) {1033 // add exploded function alternatives to front of argument list1034 std::vector< ExplodedArg > funcE;1035 funcE.reserve( funcFinder.candidates.size() );1036 for ( const CandidateRef & func : funcFinder ) {1037 funcE.emplace_back( *func, symtab );1038 }1039 argExpansions.emplace_front( std::move( funcE ) );1040 1041 for ( const CandidateRef & op : opFinder ) {1042 try {1043 // check if type is pointer-to-function1044 const ast::Type * opResult = op->expr->result->stripReferences();1045 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {1046 if ( auto function = pointer->base.as< ast::FunctionType >() ) {1047 CandidateRef newOp{ new Candidate{ *op} };1048 newOp->expr =1049 referenceToRvalueConversion( newOp->expr, newOp->cost );1050 makeFunctionCandidates( untypedExpr->location,1051 newOp, function, argExpansions, found );1052 }1053 }1054 } catch ( SemanticErrorException & e ) { errors.append( e ); }1055 }1056 }1057 1058 // Implement SFINAE; resolution errors are only errors if there aren't any non-error1059 // candidates1060 if ( found.empty() && ! errors.isEmpty() ) { throw errors; }1061 1062 // Compute conversion costs1063 for ( CandidateRef & withFunc : found ) {1064 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );1065 1066 PRINT(1067 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();1068 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();1069 auto function = pointer->base.strict_as< ast::FunctionType >();1070 1071 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;1072 std::cerr << "parameters are:" << std::endl;1073 ast::printAll( std::cerr, function->params, 2 );1074 std::cerr << "arguments are:" << std::endl;1075 ast::printAll( std::cerr, appExpr->args, 2 );1076 std::cerr << "bindings are:" << std::endl;1077 ast::print( std::cerr, withFunc->env, 2 );1078 std::cerr << "cost is: " << withFunc->cost << std::endl;1079 std::cerr << "cost of conversion is:" << cvtCost << std::endl;1080 )1081 1082 if ( cvtCost != Cost::infinity ) {1083 withFunc->cvtCost = cvtCost;1084 candidates.emplace_back( std::move( withFunc ) );1085 }1086 }1087 found = std::move( candidates );1088 1089 // use a new list so that candidates are not examined by addAnonConversions twice1090 CandidateList winners = findMinCost( found );1091 promoteCvtCost( winners );1092 1093 // function may return a struct/union value, in which case we need to add candidates1094 // for implicit conversions to each of the anonymous members, which must happen after1095 // `findMinCost`, since anon conversions are never the cheapest1096 for ( const CandidateRef & c : winners ) {1097 addAnonConversions( c );1098 }1099 spliceBegin( candidates, winners );1100 1101 if ( candidates.empty() && targetType && ! targetType->isVoid() ) {1102 // If resolution is unsuccessful with a target type, try again without, since it1103 // will sometimes succeed when it wouldn't with a target type binding.1104 // For example:1105 // forall( otype T ) T & ?[]( T *, ptrdiff_t );1106 // const char * x = "hello world";1107 // unsigned char ch = x[0];1108 // Fails with simple return type binding (xxx -- check this!) as follows:1109 // * T is bound to unsigned char1110 // * (x: const char *) is unified with unsigned char *, which fails1111 // xxx -- fix this better1112 targetType = nullptr;1113 postvisit( untypedExpr );1114 }1115 }1116 1117 void Finder::postvisit( const ast::AddressExpr * addressExpr ) {1118 CandidateFinder finder( context, tenv );1119 finder.find( addressExpr->arg );1120 1121 if ( finder.candidates.empty() ) return;1122 1123 reason.code = NoMatch;1124 1125 for ( CandidateRef & r : finder.candidates ) {1126 if ( ! isLvalue( r->expr ) ) continue;1127 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );1128 }1129 }1130 1131 void Finder::postvisit( const ast::LabelAddressExpr * labelExpr ) {1132 addCandidate( labelExpr, tenv );1133 }1134 1135 void Finder::postvisit( const ast::CastExpr * castExpr ) {1136 ast::ptr< ast::Type > toType = castExpr->result;1137 assert( toType );1138 toType = resolveTypeof( toType, context );1139 toType = adjustExprType( toType, tenv, symtab );1140 1141 CandidateFinder finder( context, tenv, toType );1142 finder.find( castExpr->arg, ResolvMode::withAdjustment() );1143 1144 if ( !finder.candidates.empty() ) reason.code = NoMatch;1145 1146 CandidateList matches;1147 for ( CandidateRef & cand : finder.candidates ) {1148 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1149 ast::OpenVarSet open( cand->open );1150 1151 cand->env.extractOpenVars( open );1152 1153 // It is possible that a cast can throw away some values in a multiply-valued1154 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the1155 // subexpression results that are cast directly. The candidate is invalid if it1156 // has fewer results than there are types to cast to.1157 int discardedValues = cand->expr->result->size() - toType->size();1158 if ( discardedValues < 0 ) continue;1159 1160 // unification run for side-effects1161 unify( toType, cand->expr->result, cand->env, need, have, open, symtab );1162 Cost thisCost =1163 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)1164 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )1165 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );1166 1167 PRINT(1168 std::cerr << "working on cast with result: " << toType << std::endl;1169 std::cerr << "and expr type: " << cand->expr->result << std::endl;1170 std::cerr << "env: " << cand->env << std::endl;1171 )1172 if ( thisCost != Cost::infinity ) {1173 PRINT(1174 std::cerr << "has finite cost." << std::endl;1175 )1176 // count one safe conversion for each value that is thrown away1177 thisCost.incSafe( discardedValues );1178 CandidateRef newCand = std::make_shared<Candidate>(1179 restructureCast( cand->expr, toType, castExpr->isGenerated ),1180 copy( cand->env ), std::move( open ), std::move( need ), cand->cost,1181 cand->cost + thisCost );1182 inferParameters( newCand, matches );1183 }1184 }1185 1186 // select first on argument cost, then conversion cost1187 CandidateList minArgCost = findMinCost( matches );1188 promoteCvtCost( minArgCost );1189 candidates = findMinCost( minArgCost );1190 }1191 1192 void Finder::postvisit( const ast::VirtualCastExpr * castExpr ) {1193 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );1194 CandidateFinder finder( context, tenv );1195 // don't prune here, all alternatives guaranteed to have same type1196 finder.find( castExpr->arg, ResolvMode::withoutPrune() );1197 for ( CandidateRef & r : finder.candidates ) {1198 addCandidate(1199 *r,1200 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );1201 }1202 }1203 1204 void Finder::postvisit( const ast::KeywordCastExpr * castExpr ) {1205 const auto & loc = castExpr->location;1206 assertf( castExpr->result, "Cast target should have been set in Validate." );1207 auto ref = castExpr->result.strict_as<ast::ReferenceType>();1208 auto inst = ref->base.strict_as<ast::StructInstType>();1209 auto target = inst->base.get();1210 1211 CandidateFinder finder( context, tenv );1212 1213 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {1214 for (auto & cand : found) {1215 const ast::Type * expr = cand->expr->result.get();1216 if (expect_ref) {1217 auto res = dynamic_cast<const ast::ReferenceType*>(expr);1218 if (!res) { continue; }1219 expr = res->base.get();1220 }1221 1222 if (auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {1223 auto td = cand->env.lookup(*insttype);1224 if (!td) { continue; }1225 expr = td->bound.get();1226 }1227 1228 if (auto base = dynamic_cast<const ast::StructInstType*>(expr)) {1229 if (base->base == target) {1230 candidates.push_back( std::move(cand) );1231 reason.code = NoReason;1232 }1233 }1234 }1235 };1236 1237 try {1238 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd1239 // Clone is purely for memory management1240 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };1241 1242 // don't prune here, since it's guaranteed all alternatives will have the same type1243 finder.find( tech1.get(), ResolvMode::withoutPrune() );1244 pick_alternatives(finder.candidates, false);1245 1246 return;1247 } catch(SemanticErrorException & ) {}1248 1249 // Fallback : turn (thread&)X into (thread$&)get_thread(X)1250 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };1251 // don't prune here, since it's guaranteed all alternatives will have the same type1252 finder.find( fallback.get(), ResolvMode::withoutPrune() );1253 1254 pick_alternatives(finder.candidates, true);1255 1256 // Whatever happens here, we have no more fallbacks1257 }1258 1259 void Finder::postvisit( const ast::UntypedMemberExpr * memberExpr ) {1260 CandidateFinder aggFinder( context, tenv );1261 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );1262 for ( CandidateRef & agg : aggFinder.candidates ) {1263 // it's okay for the aggregate expression to have reference type -- cast it to the1264 // base type to treat the aggregate as the referenced value1265 Cost addedCost = Cost::zero;1266 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );1267 1268 // find member of the given type1269 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {1270 addAggMembers(1271 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1272 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {1273 addAggMembers(1274 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1275 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {1276 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );1277 }1278 }1279 }1280 1281 void Finder::postvisit( const ast::MemberExpr * memberExpr ) {1282 addCandidate( memberExpr, tenv );1283 }1284 1285 void Finder::postvisit( const ast::NameExpr * nameExpr ) {1286 std::vector< ast::SymbolTable::IdData > declList;1287 if (!selfFinder.otypeKeys.empty()) {1288 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);1289 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());1290 1291 for (auto & otypeKey: selfFinder.otypeKeys) {1292 auto result = symtab.specialLookupId(kind, otypeKey);1293 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));1294 }1295 } else {1296 declList = symtab.lookupId( nameExpr->name );1297 }1298 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )1299 1300 if ( declList.empty() ) return;1301 1302 reason.code = NoMatch;1303 1304 for ( auto & data : declList ) {1305 Cost cost = Cost::zero;1306 ast::Expr * newExpr = data.combine( nameExpr->location, cost );1307 1308 CandidateRef newCand = std::make_shared<Candidate>(1309 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1310 cost );1311 1312 if (newCand->expr->env) {1313 newCand->env.add(*newCand->expr->env);1314 auto mutExpr = newCand->expr.get_and_mutate();1315 mutExpr->env = nullptr;1316 newCand->expr = mutExpr;1317 }1318 1319 PRINT(1320 std::cerr << "decl is ";1321 ast::print( std::cerr, data.id );1322 std::cerr << std::endl;1323 std::cerr << "newExpr is ";1324 ast::print( std::cerr, newExpr );1325 std::cerr << std::endl;1326 )1327 newCand->expr = ast::mutate_field(1328 newCand->expr.get(), &ast::Expr::result,1329 renameTyVars( newCand->expr->result ) );1330 // add anonymous member interpretations whenever an aggregate value type is seen1331 // as a name expression1332 addAnonConversions( newCand );1333 candidates.emplace_back( std::move( newCand ) );1334 }1335 }1336 1337 void Finder::postvisit( const ast::VariableExpr * variableExpr ) {1338 // not sufficient to just pass `variableExpr` here, type might have changed since1339 // creation1340 addCandidate(1341 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );1342 }1343 1344 void Finder::postvisit( const ast::ConstantExpr * constantExpr ) {1345 addCandidate( constantExpr, tenv );1346 }1347 1348 void Finder::postvisit( const ast::SizeofExpr * sizeofExpr ) {1349 if ( sizeofExpr->type ) {1350 addCandidate(1351 new ast::SizeofExpr{1352 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },1353 tenv );1354 } else {1355 // find all candidates for the argument to sizeof1356 CandidateFinder finder( context, tenv );1357 finder.find( sizeofExpr->expr );1358 // find the lowest-cost candidate, otherwise ambiguous1359 CandidateList winners = findMinCost( finder.candidates );1360 if ( winners.size() != 1 ) {1361 SemanticError(1362 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );1363 }1364 // return the lowest-cost candidate1365 CandidateRef & choice = winners.front();1366 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1367 choice->cost = Cost::zero;1368 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );1369 }1370 }1371 1372 void Finder::postvisit( const ast::AlignofExpr * alignofExpr ) {1373 if ( alignofExpr->type ) {1374 addCandidate(1375 new ast::AlignofExpr{1376 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },1377 tenv );1378 } else {1379 // find all candidates for the argument to alignof1380 CandidateFinder finder( context, tenv );1381 finder.find( alignofExpr->expr );1382 // find the lowest-cost candidate, otherwise ambiguous1383 CandidateList winners = findMinCost( finder.candidates );1384 if ( winners.size() != 1 ) {1385 SemanticError(1386 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );1387 }1388 // return the lowest-cost candidate1389 CandidateRef & choice = winners.front();1390 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1391 choice->cost = Cost::zero;1392 addCandidate(1393 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );1394 }1395 }1396 1397 void Finder::postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {1398 const ast::BaseInstType * aggInst;1399 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;1400 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;1401 else return;1402 1403 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {1404 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );1405 addCandidate(1406 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );1407 }1408 }1409 1410 void Finder::postvisit( const ast::OffsetofExpr * offsetofExpr ) {1411 addCandidate( offsetofExpr, tenv );1412 }1413 1414 void Finder::postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {1415 addCandidate( offsetPackExpr, tenv );1416 }1417 1418 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) {1419 CandidateFinder finder1( context, tenv );1420 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );1421 if ( finder1.candidates.empty() ) return;1422 1423 CandidateFinder finder2( context, tenv );1424 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );1425 if ( finder2.candidates.empty() ) return;1426 1427 reason.code = NoMatch;1428 1429 for ( const CandidateRef & r1 : finder1.candidates ) {1430 for ( const CandidateRef & r2 : finder2.candidates ) {1431 ast::TypeEnvironment env{ r1->env };1432 env.simpleCombine( r2->env );1433 ast::OpenVarSet open{ r1->open };1434 mergeOpenVars( open, r2->open );1435 ast::AssertionSet need;1436 mergeAssertionSet( need, r1->need );1437 mergeAssertionSet( need, r2->need );1438 1439 addCandidate(1440 new ast::LogicalExpr{1441 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },1442 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );1443 }1444 }1445 }1446 1447 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) {1448 // candidates for condition1449 CandidateFinder finder1( context, tenv );1450 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );1451 if ( finder1.candidates.empty() ) return;1452 1453 // candidates for true result1454 CandidateFinder finder2( context, tenv );1455 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );1456 if ( finder2.candidates.empty() ) return;1457 1458 // candidates for false result1459 CandidateFinder finder3( context, tenv );1460 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );1461 if ( finder3.candidates.empty() ) return;1462 1463 reason.code = NoMatch;1464 1465 for ( const CandidateRef & r1 : finder1.candidates ) {1466 for ( const CandidateRef & r2 : finder2.candidates ) {1467 for ( const CandidateRef & r3 : finder3.candidates ) {1468 ast::TypeEnvironment env{ r1->env };1469 env.simpleCombine( r2->env );1470 env.simpleCombine( r3->env );1471 ast::OpenVarSet open{ r1->open };1472 mergeOpenVars( open, r2->open );1473 mergeOpenVars( open, r3->open );1474 ast::AssertionSet need;1475 mergeAssertionSet( need, r1->need );1476 mergeAssertionSet( need, r2->need );1477 mergeAssertionSet( need, r3->need );1478 ast::AssertionSet have;1479 1480 // unify true and false results, then infer parameters to produce new1481 // candidates1482 ast::ptr< ast::Type > common;1483 if (1484 unify(1485 r2->expr->result, r3->expr->result, env, need, have, open, symtab,1486 common )1487 ) {1488 // generate typed expression1489 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{1490 conditionalExpr->location, r1->expr, r2->expr, r3->expr };1491 newExpr->result = common ? common : r2->expr->result;1492 // convert both options to result type1493 Cost cost = r1->cost + r2->cost + r3->cost;1494 newExpr->arg2 = computeExpressionConversionCost(1495 newExpr->arg2, newExpr->result, symtab, env, cost );1496 newExpr->arg3 = computeExpressionConversionCost(1497 newExpr->arg3, newExpr->result, symtab, env, cost );1498 // output candidate1499 CandidateRef newCand = std::make_shared<Candidate>(1500 newExpr, std::move( env ), std::move( open ), std::move( need ), cost );1501 inferParameters( newCand, candidates );1502 }1503 }1504 }1505 }1506 }1507 1508 void Finder::postvisit( const ast::CommaExpr * commaExpr ) {1509 ast::TypeEnvironment env{ tenv };1510 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );1511 1512 CandidateFinder finder2( context, env );1513 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );1514 1515 for ( const CandidateRef & r2 : finder2.candidates ) {1516 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );1517 }1518 }1519 1520 void Finder::postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {1521 addCandidate( ctorExpr, tenv );1522 }1523 1524 void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) {1525 CandidateFinder finder( context, tenv );1526 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );1527 for ( CandidateRef & r : finder.candidates ) {1528 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );1529 }1530 }1531 1532 void Finder::postvisit( const ast::RangeExpr * rangeExpr ) {1533 // resolve low and high, accept candidates where low and high types unify1534 CandidateFinder finder1( context, tenv );1535 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );1536 if ( finder1.candidates.empty() ) return;1537 1538 CandidateFinder finder2( context, tenv );1539 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );1540 if ( finder2.candidates.empty() ) return;1541 1542 reason.code = NoMatch;1543 1544 for ( const CandidateRef & r1 : finder1.candidates ) {1545 for ( const CandidateRef & r2 : finder2.candidates ) {1546 ast::TypeEnvironment env{ r1->env };1547 env.simpleCombine( r2->env );1548 ast::OpenVarSet open{ r1->open };1549 mergeOpenVars( open, r2->open );1550 ast::AssertionSet need;1551 mergeAssertionSet( need, r1->need );1552 mergeAssertionSet( need, r2->need );1553 ast::AssertionSet have;1554 1555 ast::ptr< ast::Type > common;1556 if (1557 unify(1558 r1->expr->result, r2->expr->result, env, need, have, open, symtab,1559 common )1560 ) {1561 // generate new expression1562 ast::RangeExpr * newExpr =1563 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };1564 newExpr->result = common ? common : r1->expr->result;1565 // add candidate1566 CandidateRef newCand = std::make_shared<Candidate>(1567 newExpr, std::move( env ), std::move( open ), std::move( need ),1568 r1->cost + r2->cost );1569 inferParameters( newCand, candidates );1570 }1571 }1572 }1573 }1574 1575 void Finder::postvisit( const ast::UntypedTupleExpr * tupleExpr ) {1576 std::vector< CandidateFinder > subCandidates =1577 selfFinder.findSubExprs( tupleExpr->exprs );1578 std::vector< CandidateList > possibilities;1579 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );1580 1581 for ( const CandidateList & subs : possibilities ) {1582 std::vector< ast::ptr< ast::Expr > > exprs;1583 exprs.reserve( subs.size() );1584 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }1585 1586 ast::TypeEnvironment env;1587 ast::OpenVarSet open;1588 ast::AssertionSet need;1589 for ( const CandidateRef & sub : subs ) {1590 env.simpleCombine( sub->env );1591 mergeOpenVars( open, sub->open );1592 mergeAssertionSet( need, sub->need );1593 }1594 1595 addCandidate(1596 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },1597 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );1598 }1599 }1600 1601 void Finder::postvisit( const ast::TupleExpr * tupleExpr ) {1602 addCandidate( tupleExpr, tenv );1603 }1604 1605 void Finder::postvisit( const ast::TupleIndexExpr * tupleExpr ) {1606 addCandidate( tupleExpr, tenv );1607 }1608 1609 void Finder::postvisit( const ast::TupleAssignExpr * tupleExpr ) {1610 addCandidate( tupleExpr, tenv );1611 }1612 1613 void Finder::postvisit( const ast::UniqueExpr * unqExpr ) {1614 CandidateFinder finder( context, tenv );1615 finder.find( unqExpr->expr, ResolvMode::withAdjustment() );1616 for ( CandidateRef & r : finder.candidates ) {1617 // ensure that the the id is passed on so that the expressions are "linked"1618 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );1619 }1620 }1621 1622 void Finder::postvisit( const ast::StmtExpr * stmtExpr ) {1623 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );1624 }1625 1626 void Finder::postvisit( const ast::UntypedInitExpr * initExpr ) {1627 // handle each option like a cast1628 CandidateList matches;1629 PRINT(1630 std::cerr << "untyped init expr: " << initExpr << std::endl;1631 )1632 // O(n^2) checks of d-types with e-types1633 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {1634 // calculate target type1635 const ast::Type * toType = resolveTypeof( initAlt.type, context );1636 toType = adjustExprType( toType, tenv, symtab );1637 // The call to find must occur inside this loop, otherwise polymorphic return1638 // types are not bound to the initialization type, since return type variables are1639 // only open for the duration of resolving the UntypedExpr.1640 CandidateFinder finder( context, tenv, toType );1641 finder.find( initExpr->expr, ResolvMode::withAdjustment() );1642 for ( CandidateRef & cand : finder.candidates ) {1643 if (reason.code == NotFound) reason.code = NoMatch;1644 1645 ast::TypeEnvironment env{ cand->env };1646 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1647 ast::OpenVarSet open{ cand->open };1648 1649 PRINT(1650 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl;1651 )1652 1653 // It is possible that a cast can throw away some values in a multiply-valued1654 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of1655 // the subexpression results that are cast directly. The candidate is invalid1656 // if it has fewer results than there are types to cast to.1657 int discardedValues = cand->expr->result->size() - toType->size();1658 if ( discardedValues < 0 ) continue;1659 1660 // unification run for side-effects1661 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );1662 (void) canUnify;1663 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),1664 symtab, env );1665 PRINT(1666 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),1667 symtab, env );1668 std::cerr << "Considering initialization:";1669 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl;1670 std::cerr << std::endl << " TO: " << toType << std::endl;1671 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed");1672 std::cerr << std::endl << " Legacy cost " << legacyCost;1673 std::cerr << std::endl << " New cost " << thisCost;1674 std::cerr << std::endl;1675 )1676 if ( thisCost != Cost::infinity ) {1677 // count one safe conversion for each value that is thrown away1678 thisCost.incSafe( discardedValues );1679 CandidateRef newCand = std::make_shared<Candidate>(1680 new ast::InitExpr{1681 initExpr->location, restructureCast( cand->expr, toType ),1682 initAlt.designation },1683 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );1684 inferParameters( newCand, matches );1685 }1686 }1687 }1688 1689 // select first on argument cost, then conversion cost1690 CandidateList minArgCost = findMinCost( matches );1691 promoteCvtCost( minArgCost );1692 candidates = findMinCost( minArgCost );1693 }1694 1695 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");1696 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given1697 /// return type. Skips ambiguous candidates.1698 1699 } // anonymous namespace1700 1701 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {1702 struct PruneStruct {1703 CandidateRef candidate;1704 bool ambiguous;1705 1706 PruneStruct() = default;1707 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}1708 };1709 1710 // find lowest-cost candidate for each type1711 std::unordered_map< std::string, PruneStruct > selected;1712 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found1713 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});1714 for ( CandidateRef & candidate : candidates ) {1715 std::string mangleName;1716 {1717 ast::ptr< ast::Type > newType = candidate->expr->result;1718 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1719 candidate->env.apply( newType );1720 mangleName = Mangle::mangle( newType );1721 }1722 1723 auto found = selected.find( mangleName );1724 if (found != selected.end() && found->second.candidate->cost < candidate->cost) {1725 PRINT(1726 std::cerr << "cost " << candidate->cost << " loses to "1727 << found->second.candidate->cost << std::endl;1728 )1729 continue;1730 }1731 1732 // xxx - when do satisfyAssertions produce more than 1 result?1733 // this should only happen when initial result type contains1734 // unbound type parameters, then it should never be pruned by1735 // the previous step, since renameTyVars guarantees the mangled name1736 // is unique.1737 CandidateList satisfied;1738 bool needRecomputeKey = false;1739 if (candidate->need.empty()) {1740 satisfied.emplace_back(candidate);1741 }1742 else {1743 satisfyAssertions(candidate, context.symtab, satisfied, errors);1744 needRecomputeKey = true;1745 }1746 1747 for (auto & newCand : satisfied) {1748 // recomputes type key, if satisfyAssertions changed it1749 if (needRecomputeKey)1750 {1751 ast::ptr< ast::Type > newType = newCand->expr->result;1752 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());1753 newCand->env.apply( newType );1754 mangleName = Mangle::mangle( newType );1755 }1756 auto found = selected.find( mangleName );1757 if ( found != selected.end() ) {1758 if ( newCand->cost < found->second.candidate->cost ) {1759 PRINT(1760 std::cerr << "cost " << newCand->cost << " beats "1761 << found->second.candidate->cost << std::endl;1762 )1763 1764 found->second = PruneStruct{ newCand };1765 } else if ( newCand->cost == found->second.candidate->cost ) {1766 // if one of the candidates contains a deleted identifier, can pick the other,1767 // since deleted expressions should not be ambiguous if there is another option1768 // that is at least as good1769 if ( findDeletedExpr( newCand->expr ) ) {1770 // do nothing1771 PRINT( std::cerr << "candidate is deleted" << std::endl; )1772 } else if ( findDeletedExpr( found->second.candidate->expr ) ) {1773 PRINT( std::cerr << "current is deleted" << std::endl; )1774 found->second = PruneStruct{ newCand };1775 } else {1776 PRINT( std::cerr << "marking ambiguous" << std::endl; )1777 found->second.ambiguous = true;1778 }1779 } else {1780 // xxx - can satisfyAssertions increase the cost?1781 PRINT(1782 std::cerr << "cost " << newCand->cost << " loses to "1783 << found->second.candidate->cost << std::endl;1784 )1785 }1786 } else {1787 selected.emplace_hint( found, mangleName, newCand );1788 }1789 }1790 }1791 1792 // report unambiguous min-cost candidates1793 // CandidateList out;1794 for ( auto & target : selected ) {1795 if ( target.second.ambiguous ) continue;1796 1797 CandidateRef cand = target.second.candidate;1798 1799 ast::ptr< ast::Type > newResult = cand->expr->result;1800 cand->env.applyFree( newResult );1801 cand->expr = ast::mutate_field(1802 cand->expr.get(), &ast::Expr::result, std::move( newResult ) );1803 1804 out.emplace_back( cand );1805 }1806 // if everything is lost in satisfyAssertions, report the error1807 return !selected.empty();1808 }1809 1810 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {1811 // Find alternatives for expression1812 ast::Pass<Finder> finder{ *this };1813 expr->accept( finder );1814 1815 if ( mode.failFast && candidates.empty() ) {1816 switch(finder.core.reason.code) {1817 case Finder::NotFound:1818 { SemanticError( expr, "No alternatives for expression " ); break; }1819 case Finder::NoMatch:1820 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }1821 case Finder::ArgsToFew:1822 case Finder::ArgsToMany:1823 case Finder::RetsToFew:1824 case Finder::RetsToMany:1825 case Finder::NoReason:1826 default:1827 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }1828 }1829 }1830 1831 /*1832 if ( mode.satisfyAssns || mode.prune ) {1833 // trim candidates to just those where the assertions are satisfiable1834 // - necessary pre-requisite to pruning1835 CandidateList satisfied;1836 std::vector< std::string > errors;1837 for ( CandidateRef & candidate : candidates ) {1838 satisfyAssertions( candidate, localSyms, satisfied, errors );1839 }1840 1841 // fail early if none such1842 if ( mode.failFast && satisfied.empty() ) {1843 std::ostringstream stream;1844 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1845 for ( const auto& err : errors ) {1846 stream << err;1847 }1848 SemanticError( expr->location, stream.str() );1849 }1850 1851 // reset candidates1852 candidates = move( satisfied );1853 }1854 */1855 1856 if ( mode.prune ) {1857 // trim candidates to single best one1858 PRINT(1859 std::cerr << "alternatives before prune:" << std::endl;1860 print( std::cerr, candidates );1861 )1862 1863 CandidateList pruned;1864 std::vector<std::string> errors;1865 bool found = pruneCandidates( candidates, pruned, errors );1866 1867 if ( mode.failFast && pruned.empty() ) {1868 std::ostringstream stream;1869 if (found) {1870 CandidateList winners = findMinCost( candidates );1871 stream << "Cannot choose between " << winners.size() << " alternatives for "1872 "expression\n";1873 ast::print( stream, expr );1874 stream << " Alternatives are:\n";1875 print( stream, winners, 1 );1876 SemanticError( expr->location, stream.str() );1877 }1878 else {1879 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1880 for ( const auto& err : errors ) {1881 stream << err;1882 }1883 SemanticError( expr->location, stream.str() );1884 }1885 }1886 1887 auto oldsize = candidates.size();1888 candidates = std::move( pruned );1889 1890 PRINT(1891 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;1892 )1893 PRINT(1894 std::cerr << "there are " << candidates.size() << " alternatives after elimination"1895 << std::endl;1896 )1897 }1898 1899 // adjust types after pruning so that types substituted by pruneAlternatives are correctly1900 // adjusted1901 if ( mode.adjust ) {1902 for ( CandidateRef & r : candidates ) {1903 r->expr = ast::mutate_field(1904 r->expr.get(), &ast::Expr::result,1905 adjustExprType( r->expr->result, r->env, context.symtab ) );1906 }1907 }1908 1909 // Central location to handle gcc extension keyword, etc. for all expressions1910 for ( CandidateRef & r : candidates ) {1911 if ( r->expr->extension != expr->extension ) {1912 r->expr.get_and_mutate()->extension = expr->extension;1913 }1914 }1915 }1916 1917 std::vector< CandidateFinder > CandidateFinder::findSubExprs(1918 const std::vector< ast::ptr< ast::Expr > > & xs1919 ) {1920 std::vector< CandidateFinder > out;1921 1922 for ( const auto & x : xs ) {1923 out.emplace_back( context, env );1924 out.back().find( x, ResolvMode::withAdjustment() );1925 1926 PRINT(1927 std::cerr << "findSubExprs" << std::endl;1928 print( std::cerr, out.back().candidates );1929 )1930 }1931 1932 return out;1933 }1934 1935 57 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { 1936 58 if ( expr->result.as< ast::ReferenceType >() ) { … … 1942 64 return expr; 1943 65 } 66 67 /// Unique identifier for matching expression resolutions to their requesting expression 68 UniqueId globalResnSlot = 0; 1944 69 1945 70 Cost computeConversionCost( … … 1968 93 } 1969 94 95 namespace { 96 /// First index is which argument, second is which alternative, third is which exploded element 97 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; 98 99 /// Returns a list of alternatives with the minimum cost in the given list 100 CandidateList findMinCost( const CandidateList & candidates ) { 101 CandidateList out; 102 Cost minCost = Cost::infinity; 103 for ( const CandidateRef & r : candidates ) { 104 if ( r->cost < minCost ) { 105 minCost = r->cost; 106 out.clear(); 107 out.emplace_back( r ); 108 } else if ( r->cost == minCost ) { 109 out.emplace_back( r ); 110 } 111 } 112 return out; 113 } 114 115 /// Computes conversion cost for a given expression to a given type 116 const ast::Expr * computeExpressionConversionCost( 117 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 118 ) { 119 Cost convCost = computeConversionCost( 120 arg->result, paramType, arg->get_lvalue(), symtab, env ); 121 outCost += convCost; 122 123 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 124 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 125 // infer parameters and this does not currently work for the reason stated below 126 Cost tmpCost = convCost; 127 tmpCost.incPoly( -tmpCost.get_polyCost() ); 128 if ( tmpCost != Cost::zero ) { 129 ast::ptr< ast::Type > newType = paramType; 130 env.apply( newType ); 131 return new ast::CastExpr{ arg, newType }; 132 133 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 134 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 135 // once this is fixed it should be possible to resolve the cast. 136 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 137 // but it shouldn't be because this makes the conversion from DT* to DT* since 138 // commontype(zero_t, DT*) is DT*, rather than nothing 139 140 // CandidateFinder finder{ symtab, env }; 141 // finder.find( arg, ResolvMode::withAdjustment() ); 142 // assertf( finder.candidates.size() > 0, 143 // "Somehow castable expression failed to find alternatives." ); 144 // assertf( finder.candidates.size() == 1, 145 // "Somehow got multiple alternatives for known cast expression." ); 146 // return finder.candidates.front()->expr; 147 } 148 149 return arg; 150 } 151 152 /// Computes conversion cost for a given candidate 153 Cost computeApplicationConversionCost( 154 CandidateRef cand, const ast::SymbolTable & symtab 155 ) { 156 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); 157 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 158 auto function = pointer->base.strict_as< ast::FunctionType >(); 159 160 Cost convCost = Cost::zero; 161 const auto & params = function->params; 162 auto param = params.begin(); 163 auto & args = appExpr->args; 164 165 for ( unsigned i = 0; i < args.size(); ++i ) { 166 const ast::Type * argType = args[i]->result; 167 PRINT( 168 std::cerr << "arg expression:" << std::endl; 169 ast::print( std::cerr, args[i], 2 ); 170 std::cerr << "--- results are" << std::endl; 171 ast::print( std::cerr, argType, 2 ); 172 ) 173 174 if ( param == params.end() ) { 175 if ( function->isVarArgs ) { 176 convCost.incUnsafe(); 177 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 178 << convCost << std::endl; ; ) 179 // convert reference-typed expressions into value-typed expressions 180 cand->expr = ast::mutate_field_index( 181 appExpr, &ast::ApplicationExpr::args, i, 182 referenceToRvalueConversion( args[i], convCost ) ); 183 continue; 184 } else return Cost::infinity; 185 } 186 187 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) { 188 // Default arguments should be free - don't include conversion cost. 189 // Unwrap them here because they are not relevant to the rest of the system 190 cand->expr = ast::mutate_field_index( 191 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 192 ++param; 193 continue; 194 } 195 196 // mark conversion cost and also specialization cost of param type 197 // const ast::Type * paramType = (*param)->get_type(); 198 cand->expr = ast::mutate_field_index( 199 appExpr, &ast::ApplicationExpr::args, i, 200 computeExpressionConversionCost( 201 args[i], *param, symtab, cand->env, convCost ) ); 202 convCost.decSpec( specCost( *param ) ); 203 ++param; // can't be in for-loop update because of the continue 204 } 205 206 if ( param != params.end() ) return Cost::infinity; 207 208 // specialization cost of return types can't be accounted for directly, it disables 209 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 210 // 211 // forall(otype OS) { 212 // void ?|?(OS&, int); // with newline 213 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 214 // } 215 216 // mark type variable and specialization cost of forall clause 217 convCost.incVar( function->forall.size() ); 218 convCost.decSpec( function->assertions.size() ); 219 220 return convCost; 221 } 222 223 void makeUnifiableVars( 224 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars, 225 ast::AssertionSet & need 226 ) { 227 for ( auto & tyvar : type->forall ) { 228 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base }; 229 } 230 for ( auto & assn : type->assertions ) { 231 need[ assn ].isUsed = true; 232 } 233 } 234 235 /// Gets a default value from an initializer, nullptr if not present 236 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) { 237 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) { 238 if ( auto ce = si->value.as< ast::CastExpr >() ) { 239 return ce->arg.as< ast::ConstantExpr >(); 240 } else { 241 return si->value.as< ast::ConstantExpr >(); 242 } 243 } 244 return nullptr; 245 } 246 247 /// State to iteratively build a match of parameter expressions to arguments 248 struct ArgPack { 249 std::size_t parent; ///< Index of parent pack 250 ast::ptr< ast::Expr > expr; ///< The argument stored here 251 Cost cost; ///< The cost of this argument 252 ast::TypeEnvironment env; ///< Environment for this pack 253 ast::AssertionSet need; ///< Assertions outstanding for this pack 254 ast::AssertionSet have; ///< Assertions found for this pack 255 ast::OpenVarSet open; ///< Open variables for this pack 256 unsigned nextArg; ///< Index of next argument in arguments list 257 unsigned tupleStart; ///< Number of tuples that start at this index 258 unsigned nextExpl; ///< Index of next exploded element 259 unsigned explAlt; ///< Index of alternative for nextExpl > 0 260 261 ArgPack() 262 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 263 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 265 ArgPack( 266 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 267 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 268 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 269 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 270 271 ArgPack( 272 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 273 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 274 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 275 unsigned nextExpl = 0, unsigned explAlt = 0 ) 276 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ), 277 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 278 nextExpl( nextExpl ), explAlt( explAlt ) {} 279 280 ArgPack( 281 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 282 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 283 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ), 284 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), 285 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 286 287 /// true if this pack is in the middle of an exploded argument 288 bool hasExpl() const { return nextExpl > 0; } 289 290 /// Gets the list of exploded candidates for this pack 291 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const { 292 return args[ nextArg-1 ][ explAlt ]; 293 } 294 295 /// Ends a tuple expression, consolidating the appropriate args 296 void endTuple( const std::vector< ArgPack > & packs ) { 297 // add all expressions in tuple to list, summing cost 298 std::deque< const ast::Expr * > exprs; 299 const ArgPack * pack = this; 300 if ( expr ) { exprs.emplace_front( expr ); } 301 while ( pack->tupleStart == 0 ) { 302 pack = &packs[pack->parent]; 303 exprs.emplace_front( pack->expr ); 304 cost += pack->cost; 305 } 306 // reset pack to appropriate tuple 307 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() ); 308 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) }; 309 tupleStart = pack->tupleStart - 1; 310 parent = pack->parent; 311 } 312 }; 313 314 /// Instantiates an argument to match a parameter, returns false if no matching results left 315 bool instantiateArgument( 316 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 317 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 318 unsigned nTuples = 0 319 ) { 320 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { 321 // paramType is a TupleType -- group args into a TupleExpr 322 ++nTuples; 323 for ( const ast::Type * type : *tupleType ) { 324 // xxx - dropping initializer changes behaviour from previous, but seems correct 325 // ^^^ need to handle the case where a tuple has a default argument 326 if ( ! instantiateArgument( 327 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 328 nTuples = 0; 329 } 330 // re-constitute tuples for final generation 331 for ( auto i = genStart; i < results.size(); ++i ) { 332 results[i].endTuple( results ); 333 } 334 return true; 335 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 336 // paramType is a ttype, consumes all remaining arguments 337 338 // completed tuples; will be spliced to end of results to finish 339 std::vector< ArgPack > finalResults{}; 340 341 // iterate until all results completed 342 std::size_t genEnd; 343 ++nTuples; 344 do { 345 genEnd = results.size(); 346 347 // add another argument to results 348 for ( std::size_t i = genStart; i < genEnd; ++i ) { 349 unsigned nextArg = results[i].nextArg; 350 351 // use next element of exploded tuple if present 352 if ( results[i].hasExpl() ) { 353 const ExplodedArg & expl = results[i].getExpl( args ); 354 355 unsigned nextExpl = results[i].nextExpl + 1; 356 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 357 358 results.emplace_back( 359 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 360 copy( results[i].need ), copy( results[i].have ), 361 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 362 results[i].explAlt ); 363 364 continue; 365 } 366 367 // finish result when out of arguments 368 if ( nextArg >= args.size() ) { 369 ArgPack newResult{ 370 results[i].env, results[i].need, results[i].have, results[i].open }; 371 newResult.nextArg = nextArg; 372 const ast::Type * argType = nullptr; 373 374 if ( nTuples > 0 || ! results[i].expr ) { 375 // first iteration or no expression to clone, 376 // push empty tuple expression 377 newResult.parent = i; 378 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} }; 379 argType = newResult.expr->result; 380 } else { 381 // clone result to collect tuple 382 newResult.parent = results[i].parent; 383 newResult.cost = results[i].cost; 384 newResult.tupleStart = results[i].tupleStart; 385 newResult.expr = results[i].expr; 386 argType = newResult.expr->result; 387 388 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 389 // the case where a ttype value is passed directly is special, 390 // e.g. for argument forwarding purposes 391 // xxx - what if passing multiple arguments, last of which is 392 // ttype? 393 // xxx - what would happen if unify was changed so that unifying 394 // tuple 395 // types flattened both before unifying lists? then pass in 396 // TupleType (ttype) below. 397 --newResult.tupleStart; 398 } else { 399 // collapse leftover arguments into tuple 400 newResult.endTuple( results ); 401 argType = newResult.expr->result; 402 } 403 } 404 405 // check unification for ttype before adding to final 406 if ( 407 unify( 408 ttype, argType, newResult.env, newResult.need, newResult.have, 409 newResult.open, symtab ) 410 ) { 411 finalResults.emplace_back( std::move( newResult ) ); 412 } 413 414 continue; 415 } 416 417 // add each possible next argument 418 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 419 const ExplodedArg & expl = args[nextArg][j]; 420 421 // fresh copies of parent parameters for this iteration 422 ast::TypeEnvironment env = results[i].env; 423 ast::OpenVarSet open = results[i].open; 424 425 env.addActual( expl.env, open ); 426 427 // skip empty tuple arguments by (nearly) cloning parent into next gen 428 if ( expl.exprs.empty() ) { 429 results.emplace_back( 430 results[i], std::move( env ), copy( results[i].need ), 431 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost ); 432 433 continue; 434 } 435 436 // add new result 437 results.emplace_back( 438 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 439 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples, 440 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 441 } 442 } 443 444 // reset for next round 445 genStart = genEnd; 446 nTuples = 0; 447 } while ( genEnd != results.size() ); 448 449 // splice final results onto results 450 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 451 results.emplace_back( std::move( finalResults[i] ) ); 452 } 453 return ! finalResults.empty(); 454 } 455 456 // iterate each current subresult 457 std::size_t genEnd = results.size(); 458 for ( std::size_t i = genStart; i < genEnd; ++i ) { 459 unsigned nextArg = results[i].nextArg; 460 461 // use remainder of exploded tuple if present 462 if ( results[i].hasExpl() ) { 463 const ExplodedArg & expl = results[i].getExpl( args ); 464 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ]; 465 466 ast::TypeEnvironment env = results[i].env; 467 ast::AssertionSet need = results[i].need, have = results[i].have; 468 ast::OpenVarSet open = results[i].open; 469 470 const ast::Type * argType = expr->result; 471 472 PRINT( 473 std::cerr << "param type is "; 474 ast::print( std::cerr, paramType ); 475 std::cerr << std::endl << "arg type is "; 476 ast::print( std::cerr, argType ); 477 std::cerr << std::endl; 478 ) 479 480 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 481 unsigned nextExpl = results[i].nextExpl + 1; 482 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 483 484 results.emplace_back( 485 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg, 486 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 487 } 488 489 continue; 490 } 491 492 // use default initializers if out of arguments 493 if ( nextArg >= args.size() ) { 494 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) { 495 ast::TypeEnvironment env = results[i].env; 496 ast::AssertionSet need = results[i].need, have = results[i].have; 497 ast::OpenVarSet open = results[i].open; 498 499 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 500 results.emplace_back( 501 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ), 502 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples ); 503 } 504 } 505 506 continue; 507 } 508 509 // Check each possible next argument 510 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 511 const ExplodedArg & expl = args[nextArg][j]; 512 513 // fresh copies of parent parameters for this iteration 514 ast::TypeEnvironment env = results[i].env; 515 ast::AssertionSet need = results[i].need, have = results[i].have; 516 ast::OpenVarSet open = results[i].open; 517 518 env.addActual( expl.env, open ); 519 520 // skip empty tuple arguments by (nearly) cloning parent into next gen 521 if ( expl.exprs.empty() ) { 522 results.emplace_back( 523 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ), 524 nextArg + 1, expl.cost ); 525 526 continue; 527 } 528 529 // consider only first exploded arg 530 const ast::Expr * expr = expl.exprs.front(); 531 const ast::Type * argType = expr->result; 532 533 PRINT( 534 std::cerr << "param type is "; 535 ast::print( std::cerr, paramType ); 536 std::cerr << std::endl << "arg type is "; 537 ast::print( std::cerr, argType ); 538 std::cerr << std::endl; 539 ) 540 541 // attempt to unify types 542 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 543 // add new result 544 results.emplace_back( 545 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 546 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 547 } 548 } 549 } 550 551 // reset for next parameter 552 genStart = genEnd; 553 554 return genEnd != results.size(); // were any new results added? 555 } 556 557 /// Generate a cast expression from `arg` to `toType` 558 const ast::Expr * restructureCast( 559 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 560 ) { 561 if ( 562 arg->result->size() > 1 563 && ! toType->isVoid() 564 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 565 ) { 566 // Argument is a tuple and the target type is neither void nor a reference. Cast each 567 // member of the tuple to its corresponding target type, producing the tuple of those 568 // cast expressions. If there are more components of the tuple than components in the 569 // target type, then excess components do not come out in the result expression (but 570 // UniqueExpr ensures that the side effects will still be produced) 571 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 572 // expressions which may contain side effects require a single unique instance of 573 // the expression 574 arg = new ast::UniqueExpr{ arg->location, arg }; 575 } 576 std::vector< ast::ptr< ast::Expr > > components; 577 for ( unsigned i = 0; i < toType->size(); ++i ) { 578 // cast each component 579 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 580 components.emplace_back( 581 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 582 } 583 return new ast::TupleExpr{ arg->location, std::move( components ) }; 584 } else { 585 // handle normally 586 return new ast::CastExpr{ arg->location, arg, toType, isGenerated }; 587 } 588 } 589 590 /// Gets the name from an untyped member expression (must be NameExpr) 591 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) { 592 if ( memberExpr->member.as< ast::ConstantExpr >() ) { 593 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 594 } 595 596 return memberExpr->member.strict_as< ast::NameExpr >()->name; 597 } 598 599 /// Actually visits expressions to find their candidate interpretations 600 class Finder final : public ast::WithShortCircuiting { 601 const ResolveContext & context; 602 const ast::SymbolTable & symtab; 603 public: 604 // static size_t traceId; 605 CandidateFinder & selfFinder; 606 CandidateList & candidates; 607 const ast::TypeEnvironment & tenv; 608 ast::ptr< ast::Type > & targetType; 609 610 enum Errors { 611 NotFound, 612 NoMatch, 613 ArgsToFew, 614 ArgsToMany, 615 RetsToFew, 616 RetsToMany, 617 NoReason 618 }; 619 620 struct { 621 Errors code = NotFound; 622 } reason; 623 624 Finder( CandidateFinder & f ) 625 : context( f.context ), symtab( context.symtab ), selfFinder( f ), 626 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {} 627 628 void previsit( const ast::Node * ) { visit_children = false; } 629 630 /// Convenience to add candidate to list 631 template<typename... Args> 632 void addCandidate( Args &&... args ) { 633 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 634 reason.code = NoReason; 635 } 636 637 void postvisit( const ast::ApplicationExpr * applicationExpr ) { 638 addCandidate( applicationExpr, tenv ); 639 } 640 641 /// Set up candidate assertions for inference 642 void inferParameters( CandidateRef & newCand, CandidateList & out ) { 643 // Set need bindings for any unbound assertions 644 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 645 for ( auto & assn : newCand->need ) { 646 // skip already-matched assertions 647 if ( assn.second.resnSlot != 0 ) continue; 648 // assign slot for expression if needed 649 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 650 // fix slot to assertion 651 assn.second.resnSlot = crntResnSlot; 652 } 653 // pair slot to expression 654 if ( crntResnSlot != 0 ) { 655 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot ); 656 } 657 658 // add to output list; assertion satisfaction will occur later 659 out.emplace_back( newCand ); 660 } 661 662 /// Completes a function candidate with arguments located 663 void validateFunctionCandidate( 664 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 665 CandidateList & out 666 ) { 667 ast::ApplicationExpr * appExpr = 668 new ast::ApplicationExpr{ func->expr->location, func->expr }; 669 // sum cost and accumulate arguments 670 std::deque< const ast::Expr * > args; 671 Cost cost = func->cost; 672 const ArgPack * pack = &result; 673 while ( pack->expr ) { 674 args.emplace_front( pack->expr ); 675 cost += pack->cost; 676 pack = &results[pack->parent]; 677 } 678 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() ); 679 appExpr->args = std::move( vargs ); 680 // build and validate new candidate 681 auto newCand = 682 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 683 PRINT( 684 std::cerr << "instantiate function success: " << appExpr << std::endl; 685 std::cerr << "need assertions:" << std::endl; 686 ast::print( std::cerr, result.need, 2 ); 687 ) 688 inferParameters( newCand, out ); 689 } 690 691 /// Builds a list of candidates for a function, storing them in out 692 void makeFunctionCandidates( 693 const CandidateRef & func, const ast::FunctionType * funcType, 694 const ExplodedArgs_new & args, CandidateList & out 695 ) { 696 ast::OpenVarSet funcOpen; 697 ast::AssertionSet funcNeed, funcHave; 698 ast::TypeEnvironment funcEnv{ func->env }; 699 makeUnifiableVars( funcType, funcOpen, funcNeed ); 700 // add all type variables as open variables now so that those not used in the 701 // parameter list are still considered open 702 funcEnv.add( funcType->forall ); 703 704 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 705 // attempt to narrow based on expected target type 706 const ast::Type * returnType = funcType->returns.front(); 707 if ( ! unify( 708 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 709 ) { 710 // unification failed, do not pursue this candidate 711 return; 712 } 713 } 714 715 // iteratively build matches, one parameter at a time 716 std::vector< ArgPack > results; 717 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen ); 718 std::size_t genStart = 0; 719 720 // xxx - how to handle default arg after change to ftype representation? 721 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) { 722 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) { 723 // function may have default args only if directly calling by name 724 // must use types on candidate however, due to RenameVars substitution 725 auto nParams = funcType->params.size(); 726 727 for (size_t i=0; i<nParams; ++i) { 728 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 729 if (!instantiateArgument( 730 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 731 } 732 goto endMatch; 733 } 734 } 735 for ( const auto & param : funcType->params ) { 736 // Try adding the arguments corresponding to the current parameter to the existing 737 // matches 738 // no default args for indirect calls 739 if ( ! instantiateArgument( 740 param, nullptr, args, results, genStart, symtab ) ) return; 741 } 742 743 endMatch: 744 if ( funcType->isVarArgs ) { 745 // append any unused arguments to vararg pack 746 std::size_t genEnd; 747 do { 748 genEnd = results.size(); 749 750 // iterate results 751 for ( std::size_t i = genStart; i < genEnd; ++i ) { 752 unsigned nextArg = results[i].nextArg; 753 754 // use remainder of exploded tuple if present 755 if ( results[i].hasExpl() ) { 756 const ExplodedArg & expl = results[i].getExpl( args ); 757 758 unsigned nextExpl = results[i].nextExpl + 1; 759 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 760 761 results.emplace_back( 762 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 763 copy( results[i].need ), copy( results[i].have ), 764 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl, 765 results[i].explAlt ); 766 767 continue; 768 } 769 770 // finish result when out of arguments 771 if ( nextArg >= args.size() ) { 772 validateFunctionCandidate( func, results[i], results, out ); 773 774 continue; 775 } 776 777 // add each possible next argument 778 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 779 const ExplodedArg & expl = args[nextArg][j]; 780 781 // fresh copies of parent parameters for this iteration 782 ast::TypeEnvironment env = results[i].env; 783 ast::OpenVarSet open = results[i].open; 784 785 env.addActual( expl.env, open ); 786 787 // skip empty tuple arguments by (nearly) cloning parent into next gen 788 if ( expl.exprs.empty() ) { 789 results.emplace_back( 790 results[i], std::move( env ), copy( results[i].need ), 791 copy( results[i].have ), std::move( open ), nextArg + 1, 792 expl.cost ); 793 794 continue; 795 } 796 797 // add new result 798 results.emplace_back( 799 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 800 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost, 801 expl.exprs.size() == 1 ? 0 : 1, j ); 802 } 803 } 804 805 genStart = genEnd; 806 } while( genEnd != results.size() ); 807 } else { 808 // filter out the results that don't use all the arguments 809 for ( std::size_t i = genStart; i < results.size(); ++i ) { 810 ArgPack & result = results[i]; 811 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 812 validateFunctionCandidate( func, result, results, out ); 813 } 814 } 815 } 816 } 817 818 /// Adds implicit struct-conversions to the alternative list 819 void addAnonConversions( const CandidateRef & cand ) { 820 // adds anonymous member interpretations whenever an aggregate value type is seen. 821 // it's okay for the aggregate expression to have reference type -- cast it to the 822 // base type to treat the aggregate as the referenced value 823 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 824 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 825 cand->env.apply( aggrType ); 826 827 if ( aggrType.as< ast::ReferenceType >() ) { 828 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; 829 } 830 831 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 832 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" ); 833 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 834 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" ); 835 } 836 } 837 838 /// Adds aggregate member interpretations 839 void addAggMembers( 840 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 841 const Candidate & cand, const Cost & addedCost, const std::string & name 842 ) { 843 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 844 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 845 CandidateRef newCand = std::make_shared<Candidate>( 846 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 847 // add anonymous member interpretations whenever an aggregate value type is seen 848 // as a member expression 849 addAnonConversions( newCand ); 850 candidates.emplace_back( std::move( newCand ) ); 851 } 852 } 853 854 /// Adds tuple member interpretations 855 void addTupleMembers( 856 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 857 const Cost & addedCost, const ast::Expr * member 858 ) { 859 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 860 // get the value of the constant expression as an int, must be between 0 and the 861 // length of the tuple to have meaning 862 long long val = constantExpr->intValue(); 863 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 864 addCandidate( 865 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 866 addedCost ); 867 } 868 } 869 } 870 871 void postvisit( const ast::UntypedExpr * untypedExpr ) { 872 std::vector< CandidateFinder > argCandidates = 873 selfFinder.findSubExprs( untypedExpr->args ); 874 875 // take care of possible tuple assignments 876 // if not tuple assignment, handled as normal function call 877 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 878 879 CandidateFinder funcFinder( context, tenv ); 880 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 881 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 882 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 883 assertf(!argCandidates.empty(), "special function call without argument"); 884 for (auto & firstArgCand: argCandidates[0]) { 885 ast::ptr<ast::Type> argType = firstArgCand->expr->result; 886 firstArgCand->env.apply(argType); 887 // strip references 888 // xxx - is this correct? 889 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base; 890 891 // convert 1-tuple to plain type 892 if (auto tuple = argType.as<ast::TupleType>()) { 893 if (tuple->size() == 1) { 894 argType = tuple->types[0]; 895 } 896 } 897 898 // if argType is an unbound type parameter, all special functions need to be searched. 899 if (isUnboundType(argType)) { 900 funcFinder.otypeKeys.clear(); 901 break; 902 } 903 904 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 905 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) { 906 // const ast::EnumDecl * enumDecl = enumInst->base; // Here 907 // if ( const ast::Type* enumType = enumDecl->base ) { 908 // // instance of enum (T) is a instance of type (T) 909 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type)); 910 // } else { 911 // // instance of an untyped enum is techically int 912 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type)); 913 // } 914 // } 915 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type)); 916 } 917 } 918 } 919 // if candidates are already produced, do not fail 920 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates? 921 // this means there exists ctor/assign functions with a tuple as first parameter. 922 ResolvMode mode = { 923 true, // adjust 924 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name 925 selfFinder.candidates.empty() // failfast if other options are not found 926 }; 927 funcFinder.find( untypedExpr->func, mode ); 928 // short-circuit if no candidates 929 // if ( funcFinder.candidates.empty() ) return; 930 931 reason.code = NoMatch; 932 933 // find function operators 934 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{} 935 CandidateFinder opFinder( context, tenv ); 936 // okay if there aren't any function operations 937 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); 938 PRINT( 939 std::cerr << "known function ops:" << std::endl; 940 print( std::cerr, opFinder.candidates, 1 ); 941 ) 942 943 // pre-explode arguments 944 ExplodedArgs_new argExpansions; 945 for ( const CandidateFinder & args : argCandidates ) { 946 argExpansions.emplace_back(); 947 auto & argE = argExpansions.back(); 948 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); } 949 } 950 951 // Find function matches 952 CandidateList found; 953 SemanticErrorException errors; 954 for ( CandidateRef & func : funcFinder ) { 955 try { 956 PRINT( 957 std::cerr << "working on alternative:" << std::endl; 958 print( std::cerr, *func, 2 ); 959 ) 960 961 // check if the type is a pointer to function 962 const ast::Type * funcResult = func->expr->result->stripReferences(); 963 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 964 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 965 CandidateRef newFunc{ new Candidate{ *func } }; 966 newFunc->expr = 967 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 968 makeFunctionCandidates( newFunc, function, argExpansions, found ); 969 } 970 } else if ( 971 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 972 ) { 973 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 974 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 975 CandidateRef newFunc{ new Candidate{ *func } }; 976 newFunc->expr = 977 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 978 makeFunctionCandidates( newFunc, function, argExpansions, found ); 979 } 980 } 981 } 982 } catch ( SemanticErrorException & e ) { errors.append( e ); } 983 } 984 985 // Find matches on function operators `?()` 986 if ( ! opFinder.candidates.empty() ) { 987 // add exploded function alternatives to front of argument list 988 std::vector< ExplodedArg > funcE; 989 funcE.reserve( funcFinder.candidates.size() ); 990 for ( const CandidateRef & func : funcFinder ) { 991 funcE.emplace_back( *func, symtab ); 992 } 993 argExpansions.emplace_front( std::move( funcE ) ); 994 995 for ( const CandidateRef & op : opFinder ) { 996 try { 997 // check if type is pointer-to-function 998 const ast::Type * opResult = op->expr->result->stripReferences(); 999 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) { 1000 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1001 CandidateRef newOp{ new Candidate{ *op} }; 1002 newOp->expr = 1003 referenceToRvalueConversion( newOp->expr, newOp->cost ); 1004 makeFunctionCandidates( newOp, function, argExpansions, found ); 1005 } 1006 } 1007 } catch ( SemanticErrorException & e ) { errors.append( e ); } 1008 } 1009 } 1010 1011 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 1012 // candidates 1013 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1014 1015 // Compute conversion costs 1016 for ( CandidateRef & withFunc : found ) { 1017 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab ); 1018 1019 PRINT( 1020 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >(); 1021 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 1022 auto function = pointer->base.strict_as< ast::FunctionType >(); 1023 1024 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 1025 std::cerr << "parameters are:" << std::endl; 1026 ast::printAll( std::cerr, function->params, 2 ); 1027 std::cerr << "arguments are:" << std::endl; 1028 ast::printAll( std::cerr, appExpr->args, 2 ); 1029 std::cerr << "bindings are:" << std::endl; 1030 ast::print( std::cerr, withFunc->env, 2 ); 1031 std::cerr << "cost is: " << withFunc->cost << std::endl; 1032 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1033 ) 1034 1035 if ( cvtCost != Cost::infinity ) { 1036 withFunc->cvtCost = cvtCost; 1037 candidates.emplace_back( std::move( withFunc ) ); 1038 } 1039 } 1040 found = std::move( candidates ); 1041 1042 // use a new list so that candidates are not examined by addAnonConversions twice 1043 CandidateList winners = findMinCost( found ); 1044 promoteCvtCost( winners ); 1045 1046 // function may return a struct/union value, in which case we need to add candidates 1047 // for implicit conversions to each of the anonymous members, which must happen after 1048 // `findMinCost`, since anon conversions are never the cheapest 1049 for ( const CandidateRef & c : winners ) { 1050 addAnonConversions( c ); 1051 } 1052 spliceBegin( candidates, winners ); 1053 1054 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 1055 // If resolution is unsuccessful with a target type, try again without, since it 1056 // will sometimes succeed when it wouldn't with a target type binding. 1057 // For example: 1058 // forall( otype T ) T & ?[]( T *, ptrdiff_t ); 1059 // const char * x = "hello world"; 1060 // unsigned char ch = x[0]; 1061 // Fails with simple return type binding (xxx -- check this!) as follows: 1062 // * T is bound to unsigned char 1063 // * (x: const char *) is unified with unsigned char *, which fails 1064 // xxx -- fix this better 1065 targetType = nullptr; 1066 postvisit( untypedExpr ); 1067 } 1068 } 1069 1070 /// true if expression is an lvalue 1071 static bool isLvalue( const ast::Expr * x ) { 1072 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() ); 1073 } 1074 1075 void postvisit( const ast::AddressExpr * addressExpr ) { 1076 CandidateFinder finder( context, tenv ); 1077 finder.find( addressExpr->arg ); 1078 1079 if( finder.candidates.empty() ) return; 1080 1081 reason.code = NoMatch; 1082 1083 for ( CandidateRef & r : finder.candidates ) { 1084 if ( ! isLvalue( r->expr ) ) continue; 1085 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } ); 1086 } 1087 } 1088 1089 void postvisit( const ast::LabelAddressExpr * labelExpr ) { 1090 addCandidate( labelExpr, tenv ); 1091 } 1092 1093 void postvisit( const ast::CastExpr * castExpr ) { 1094 ast::ptr< ast::Type > toType = castExpr->result; 1095 assert( toType ); 1096 toType = resolveTypeof( toType, context ); 1097 toType = adjustExprType( toType, tenv, symtab ); 1098 1099 CandidateFinder finder( context, tenv, toType ); 1100 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1101 1102 if( !finder.candidates.empty() ) reason.code = NoMatch; 1103 1104 CandidateList matches; 1105 for ( CandidateRef & cand : finder.candidates ) { 1106 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1107 ast::OpenVarSet open( cand->open ); 1108 1109 cand->env.extractOpenVars( open ); 1110 1111 // It is possible that a cast can throw away some values in a multiply-valued 1112 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1113 // subexpression results that are cast directly. The candidate is invalid if it 1114 // has fewer results than there are types to cast to. 1115 int discardedValues = cand->expr->result->size() - toType->size(); 1116 if ( discardedValues < 0 ) continue; 1117 1118 // unification run for side-effects 1119 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1120 Cost thisCost = 1121 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) 1122 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1123 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1124 1125 PRINT( 1126 std::cerr << "working on cast with result: " << toType << std::endl; 1127 std::cerr << "and expr type: " << cand->expr->result << std::endl; 1128 std::cerr << "env: " << cand->env << std::endl; 1129 ) 1130 if ( thisCost != Cost::infinity ) { 1131 PRINT( 1132 std::cerr << "has finite cost." << std::endl; 1133 ) 1134 // count one safe conversion for each value that is thrown away 1135 thisCost.incSafe( discardedValues ); 1136 CandidateRef newCand = std::make_shared<Candidate>( 1137 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1138 copy( cand->env ), std::move( open ), std::move( need ), cand->cost, 1139 cand->cost + thisCost ); 1140 inferParameters( newCand, matches ); 1141 } 1142 } 1143 1144 // select first on argument cost, then conversion cost 1145 CandidateList minArgCost = findMinCost( matches ); 1146 promoteCvtCost( minArgCost ); 1147 candidates = findMinCost( minArgCost ); 1148 } 1149 1150 void postvisit( const ast::VirtualCastExpr * castExpr ) { 1151 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 1152 CandidateFinder finder( context, tenv ); 1153 // don't prune here, all alternatives guaranteed to have same type 1154 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1155 for ( CandidateRef & r : finder.candidates ) { 1156 addCandidate( 1157 *r, 1158 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1159 } 1160 } 1161 1162 void postvisit( const ast::KeywordCastExpr * castExpr ) { 1163 const auto & loc = castExpr->location; 1164 assertf( castExpr->result, "Cast target should have been set in Validate." ); 1165 auto ref = castExpr->result.strict_as<ast::ReferenceType>(); 1166 auto inst = ref->base.strict_as<ast::StructInstType>(); 1167 auto target = inst->base.get(); 1168 1169 CandidateFinder finder( context, tenv ); 1170 1171 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) { 1172 for(auto & cand : found) { 1173 const ast::Type * expr = cand->expr->result.get(); 1174 if(expect_ref) { 1175 auto res = dynamic_cast<const ast::ReferenceType*>(expr); 1176 if(!res) { continue; } 1177 expr = res->base.get(); 1178 } 1179 1180 if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) { 1181 auto td = cand->env.lookup(*insttype); 1182 if(!td) { continue; } 1183 expr = td->bound.get(); 1184 } 1185 1186 if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) { 1187 if(base->base == target) { 1188 candidates.push_back( std::move(cand) ); 1189 reason.code = NoReason; 1190 } 1191 } 1192 } 1193 }; 1194 1195 try { 1196 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd 1197 // Clone is purely for memory management 1198 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) }; 1199 1200 // don't prune here, since it's guaranteed all alternatives will have the same type 1201 finder.find( tech1.get(), ResolvMode::withoutPrune() ); 1202 pick_alternatives(finder.candidates, false); 1203 1204 return; 1205 } catch(SemanticErrorException & ) {} 1206 1207 // Fallback : turn (thread&)X into (thread$&)get_thread(X) 1208 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) }; 1209 // don't prune here, since it's guaranteed all alternatives will have the same type 1210 finder.find( fallback.get(), ResolvMode::withoutPrune() ); 1211 1212 pick_alternatives(finder.candidates, true); 1213 1214 // Whatever happens here, we have no more fallbacks 1215 } 1216 1217 void postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1218 CandidateFinder aggFinder( context, tenv ); 1219 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1220 for ( CandidateRef & agg : aggFinder.candidates ) { 1221 // it's okay for the aggregate expression to have reference type -- cast it to the 1222 // base type to treat the aggregate as the referenced value 1223 Cost addedCost = Cost::zero; 1224 agg->expr = referenceToRvalueConversion( agg->expr, addedCost ); 1225 1226 // find member of the given type 1227 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1228 addAggMembers( 1229 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1230 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1231 addAggMembers( 1232 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1233 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { 1234 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member ); 1235 } 1236 } 1237 } 1238 1239 void postvisit( const ast::MemberExpr * memberExpr ) { 1240 addCandidate( memberExpr, tenv ); 1241 } 1242 1243 void postvisit( const ast::NameExpr * nameExpr ) { 1244 std::vector< ast::SymbolTable::IdData > declList; 1245 if (!selfFinder.otypeKeys.empty()) { 1246 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 1247 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str()); 1248 1249 for (auto & otypeKey: selfFinder.otypeKeys) { 1250 auto result = symtab.specialLookupId(kind, otypeKey); 1251 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end())); 1252 } 1253 } 1254 else { 1255 declList = symtab.lookupId( nameExpr->name ); 1256 } 1257 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1258 1259 if( declList.empty() ) return; 1260 1261 reason.code = NoMatch; 1262 1263 for ( auto & data : declList ) { 1264 Cost cost = Cost::zero; 1265 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1266 1267 CandidateRef newCand = std::make_shared<Candidate>( 1268 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1269 cost ); 1270 1271 if (newCand->expr->env) { 1272 newCand->env.add(*newCand->expr->env); 1273 auto mutExpr = newCand->expr.get_and_mutate(); 1274 mutExpr->env = nullptr; 1275 newCand->expr = mutExpr; 1276 } 1277 1278 PRINT( 1279 std::cerr << "decl is "; 1280 ast::print( std::cerr, data.id ); 1281 std::cerr << std::endl; 1282 std::cerr << "newExpr is "; 1283 ast::print( std::cerr, newExpr ); 1284 std::cerr << std::endl; 1285 ) 1286 newCand->expr = ast::mutate_field( 1287 newCand->expr.get(), &ast::Expr::result, 1288 renameTyVars( newCand->expr->result ) ); 1289 // add anonymous member interpretations whenever an aggregate value type is seen 1290 // as a name expression 1291 addAnonConversions( newCand ); 1292 candidates.emplace_back( std::move( newCand ) ); 1293 } 1294 } 1295 1296 void postvisit( const ast::VariableExpr * variableExpr ) { 1297 // not sufficient to just pass `variableExpr` here, type might have changed since 1298 // creation 1299 addCandidate( 1300 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1301 } 1302 1303 void postvisit( const ast::ConstantExpr * constantExpr ) { 1304 addCandidate( constantExpr, tenv ); 1305 } 1306 1307 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1308 if ( sizeofExpr->type ) { 1309 addCandidate( 1310 new ast::SizeofExpr{ 1311 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) }, 1312 tenv ); 1313 } else { 1314 // find all candidates for the argument to sizeof 1315 CandidateFinder finder( context, tenv ); 1316 finder.find( sizeofExpr->expr ); 1317 // find the lowest-cost candidate, otherwise ambiguous 1318 CandidateList winners = findMinCost( finder.candidates ); 1319 if ( winners.size() != 1 ) { 1320 SemanticError( 1321 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1322 } 1323 // return the lowest-cost candidate 1324 CandidateRef & choice = winners.front(); 1325 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1326 choice->cost = Cost::zero; 1327 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } ); 1328 } 1329 } 1330 1331 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1332 if ( alignofExpr->type ) { 1333 addCandidate( 1334 new ast::AlignofExpr{ 1335 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) }, 1336 tenv ); 1337 } else { 1338 // find all candidates for the argument to alignof 1339 CandidateFinder finder( context, tenv ); 1340 finder.find( alignofExpr->expr ); 1341 // find the lowest-cost candidate, otherwise ambiguous 1342 CandidateList winners = findMinCost( finder.candidates ); 1343 if ( winners.size() != 1 ) { 1344 SemanticError( 1345 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1346 } 1347 // return the lowest-cost candidate 1348 CandidateRef & choice = winners.front(); 1349 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1350 choice->cost = Cost::zero; 1351 addCandidate( 1352 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1353 } 1354 } 1355 1356 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1357 const ast::BaseInstType * aggInst; 1358 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1359 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; 1360 else return; 1361 1362 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1363 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1364 addCandidate( 1365 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1366 } 1367 } 1368 1369 void postvisit( const ast::OffsetofExpr * offsetofExpr ) { 1370 addCandidate( offsetofExpr, tenv ); 1371 } 1372 1373 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) { 1374 addCandidate( offsetPackExpr, tenv ); 1375 } 1376 1377 void postvisit( const ast::LogicalExpr * logicalExpr ) { 1378 CandidateFinder finder1( context, tenv ); 1379 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 1380 if ( finder1.candidates.empty() ) return; 1381 1382 CandidateFinder finder2( context, tenv ); 1383 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1384 if ( finder2.candidates.empty() ) return; 1385 1386 reason.code = NoMatch; 1387 1388 for ( const CandidateRef & r1 : finder1.candidates ) { 1389 for ( const CandidateRef & r2 : finder2.candidates ) { 1390 ast::TypeEnvironment env{ r1->env }; 1391 env.simpleCombine( r2->env ); 1392 ast::OpenVarSet open{ r1->open }; 1393 mergeOpenVars( open, r2->open ); 1394 ast::AssertionSet need; 1395 mergeAssertionSet( need, r1->need ); 1396 mergeAssertionSet( need, r2->need ); 1397 1398 addCandidate( 1399 new ast::LogicalExpr{ 1400 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1401 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost ); 1402 } 1403 } 1404 } 1405 1406 void postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1407 // candidates for condition 1408 CandidateFinder finder1( context, tenv ); 1409 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1410 if ( finder1.candidates.empty() ) return; 1411 1412 // candidates for true result 1413 CandidateFinder finder2( context, tenv ); 1414 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1415 if ( finder2.candidates.empty() ) return; 1416 1417 // candidates for false result 1418 CandidateFinder finder3( context, tenv ); 1419 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1420 if ( finder3.candidates.empty() ) return; 1421 1422 reason.code = NoMatch; 1423 1424 for ( const CandidateRef & r1 : finder1.candidates ) { 1425 for ( const CandidateRef & r2 : finder2.candidates ) { 1426 for ( const CandidateRef & r3 : finder3.candidates ) { 1427 ast::TypeEnvironment env{ r1->env }; 1428 env.simpleCombine( r2->env ); 1429 env.simpleCombine( r3->env ); 1430 ast::OpenVarSet open{ r1->open }; 1431 mergeOpenVars( open, r2->open ); 1432 mergeOpenVars( open, r3->open ); 1433 ast::AssertionSet need; 1434 mergeAssertionSet( need, r1->need ); 1435 mergeAssertionSet( need, r2->need ); 1436 mergeAssertionSet( need, r3->need ); 1437 ast::AssertionSet have; 1438 1439 // unify true and false results, then infer parameters to produce new 1440 // candidates 1441 ast::ptr< ast::Type > common; 1442 if ( 1443 unify( 1444 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1445 common ) 1446 ) { 1447 // generate typed expression 1448 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1449 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1450 newExpr->result = common ? common : r2->expr->result; 1451 // convert both options to result type 1452 Cost cost = r1->cost + r2->cost + r3->cost; 1453 newExpr->arg2 = computeExpressionConversionCost( 1454 newExpr->arg2, newExpr->result, symtab, env, cost ); 1455 newExpr->arg3 = computeExpressionConversionCost( 1456 newExpr->arg3, newExpr->result, symtab, env, cost ); 1457 // output candidate 1458 CandidateRef newCand = std::make_shared<Candidate>( 1459 newExpr, std::move( env ), std::move( open ), std::move( need ), cost ); 1460 inferParameters( newCand, candidates ); 1461 } 1462 } 1463 } 1464 } 1465 } 1466 1467 void postvisit( const ast::CommaExpr * commaExpr ) { 1468 ast::TypeEnvironment env{ tenv }; 1469 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env ); 1470 1471 CandidateFinder finder2( context, env ); 1472 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 1473 1474 for ( const CandidateRef & r2 : finder2.candidates ) { 1475 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } ); 1476 } 1477 } 1478 1479 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) { 1480 addCandidate( ctorExpr, tenv ); 1481 } 1482 1483 void postvisit( const ast::ConstructorExpr * ctorExpr ) { 1484 CandidateFinder finder( context, tenv ); 1485 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1486 for ( CandidateRef & r : finder.candidates ) { 1487 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } ); 1488 } 1489 } 1490 1491 void postvisit( const ast::RangeExpr * rangeExpr ) { 1492 // resolve low and high, accept candidates where low and high types unify 1493 CandidateFinder finder1( context, tenv ); 1494 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 1495 if ( finder1.candidates.empty() ) return; 1496 1497 CandidateFinder finder2( context, tenv ); 1498 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1499 if ( finder2.candidates.empty() ) return; 1500 1501 reason.code = NoMatch; 1502 1503 for ( const CandidateRef & r1 : finder1.candidates ) { 1504 for ( const CandidateRef & r2 : finder2.candidates ) { 1505 ast::TypeEnvironment env{ r1->env }; 1506 env.simpleCombine( r2->env ); 1507 ast::OpenVarSet open{ r1->open }; 1508 mergeOpenVars( open, r2->open ); 1509 ast::AssertionSet need; 1510 mergeAssertionSet( need, r1->need ); 1511 mergeAssertionSet( need, r2->need ); 1512 ast::AssertionSet have; 1513 1514 ast::ptr< ast::Type > common; 1515 if ( 1516 unify( 1517 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1518 common ) 1519 ) { 1520 // generate new expression 1521 ast::RangeExpr * newExpr = 1522 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1523 newExpr->result = common ? common : r1->expr->result; 1524 // add candidate 1525 CandidateRef newCand = std::make_shared<Candidate>( 1526 newExpr, std::move( env ), std::move( open ), std::move( need ), 1527 r1->cost + r2->cost ); 1528 inferParameters( newCand, candidates ); 1529 } 1530 } 1531 } 1532 } 1533 1534 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1535 std::vector< CandidateFinder > subCandidates = 1536 selfFinder.findSubExprs( tupleExpr->exprs ); 1537 std::vector< CandidateList > possibilities; 1538 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) ); 1539 1540 for ( const CandidateList & subs : possibilities ) { 1541 std::vector< ast::ptr< ast::Expr > > exprs; 1542 exprs.reserve( subs.size() ); 1543 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); } 1544 1545 ast::TypeEnvironment env; 1546 ast::OpenVarSet open; 1547 ast::AssertionSet need; 1548 for ( const CandidateRef & sub : subs ) { 1549 env.simpleCombine( sub->env ); 1550 mergeOpenVars( open, sub->open ); 1551 mergeAssertionSet( need, sub->need ); 1552 } 1553 1554 addCandidate( 1555 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) }, 1556 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) ); 1557 } 1558 } 1559 1560 void postvisit( const ast::TupleExpr * tupleExpr ) { 1561 addCandidate( tupleExpr, tenv ); 1562 } 1563 1564 void postvisit( const ast::TupleIndexExpr * tupleExpr ) { 1565 addCandidate( tupleExpr, tenv ); 1566 } 1567 1568 void postvisit( const ast::TupleAssignExpr * tupleExpr ) { 1569 addCandidate( tupleExpr, tenv ); 1570 } 1571 1572 void postvisit( const ast::UniqueExpr * unqExpr ) { 1573 CandidateFinder finder( context, tenv ); 1574 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 1575 for ( CandidateRef & r : finder.candidates ) { 1576 // ensure that the the id is passed on so that the expressions are "linked" 1577 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } ); 1578 } 1579 } 1580 1581 void postvisit( const ast::StmtExpr * stmtExpr ) { 1582 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv ); 1583 } 1584 1585 void postvisit( const ast::UntypedInitExpr * initExpr ) { 1586 // handle each option like a cast 1587 CandidateList matches; 1588 PRINT( 1589 std::cerr << "untyped init expr: " << initExpr << std::endl; 1590 ) 1591 // O(n^2) checks of d-types with e-types 1592 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1593 // calculate target type 1594 const ast::Type * toType = resolveTypeof( initAlt.type, context ); 1595 toType = adjustExprType( toType, tenv, symtab ); 1596 // The call to find must occur inside this loop, otherwise polymorphic return 1597 // types are not bound to the initialization type, since return type variables are 1598 // only open for the duration of resolving the UntypedExpr. 1599 CandidateFinder finder( context, tenv, toType ); 1600 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1601 for ( CandidateRef & cand : finder.candidates ) { 1602 if(reason.code == NotFound) reason.code = NoMatch; 1603 1604 ast::TypeEnvironment env{ cand->env }; 1605 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1606 ast::OpenVarSet open{ cand->open }; 1607 1608 PRINT( 1609 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1610 ) 1611 1612 // It is possible that a cast can throw away some values in a multiply-valued 1613 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1614 // the subexpression results that are cast directly. The candidate is invalid 1615 // if it has fewer results than there are types to cast to. 1616 int discardedValues = cand->expr->result->size() - toType->size(); 1617 if ( discardedValues < 0 ) continue; 1618 1619 // unification run for side-effects 1620 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab ); 1621 (void) canUnify; 1622 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1623 symtab, env ); 1624 PRINT( 1625 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1626 symtab, env ); 1627 std::cerr << "Considering initialization:"; 1628 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl; 1629 std::cerr << std::endl << " TO: " << toType << std::endl; 1630 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed"); 1631 std::cerr << std::endl << " Legacy cost " << legacyCost; 1632 std::cerr << std::endl << " New cost " << thisCost; 1633 std::cerr << std::endl; 1634 ) 1635 if ( thisCost != Cost::infinity ) { 1636 // count one safe conversion for each value that is thrown away 1637 thisCost.incSafe( discardedValues ); 1638 CandidateRef newCand = std::make_shared<Candidate>( 1639 new ast::InitExpr{ 1640 initExpr->location, restructureCast( cand->expr, toType ), 1641 initAlt.designation }, 1642 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost ); 1643 inferParameters( newCand, matches ); 1644 } 1645 } 1646 1647 } 1648 1649 // select first on argument cost, then conversion cost 1650 CandidateList minArgCost = findMinCost( matches ); 1651 promoteCvtCost( minArgCost ); 1652 candidates = findMinCost( minArgCost ); 1653 } 1654 1655 void postvisit( const ast::InitExpr * ) { 1656 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); 1657 } 1658 1659 void postvisit( const ast::DeletedExpr * ) { 1660 assertf( false, "CandidateFinder should never see a DeletedExpr." ); 1661 } 1662 1663 void postvisit( const ast::GenericExpr * ) { 1664 assertf( false, "_Generic is not yet supported." ); 1665 } 1666 }; 1667 1668 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder"); 1669 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1670 /// return type. Skips ambiguous candidates. 1671 1672 } // anonymous namespace 1673 1674 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) { 1675 struct PruneStruct { 1676 CandidateRef candidate; 1677 bool ambiguous; 1678 1679 PruneStruct() = default; 1680 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {} 1681 }; 1682 1683 // find lowest-cost candidate for each type 1684 std::unordered_map< std::string, PruneStruct > selected; 1685 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found 1686 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;}); 1687 for ( CandidateRef & candidate : candidates ) { 1688 std::string mangleName; 1689 { 1690 ast::ptr< ast::Type > newType = candidate->expr->result; 1691 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get()); 1692 candidate->env.apply( newType ); 1693 mangleName = Mangle::mangle( newType ); 1694 } 1695 1696 auto found = selected.find( mangleName ); 1697 if (found != selected.end() && found->second.candidate->cost < candidate->cost) { 1698 PRINT( 1699 std::cerr << "cost " << candidate->cost << " loses to " 1700 << found->second.candidate->cost << std::endl; 1701 ) 1702 continue; 1703 } 1704 1705 // xxx - when do satisfyAssertions produce more than 1 result? 1706 // this should only happen when initial result type contains 1707 // unbound type parameters, then it should never be pruned by 1708 // the previous step, since renameTyVars guarantees the mangled name 1709 // is unique. 1710 CandidateList satisfied; 1711 bool needRecomputeKey = false; 1712 if (candidate->need.empty()) { 1713 satisfied.emplace_back(candidate); 1714 } 1715 else { 1716 satisfyAssertions(candidate, context.symtab, satisfied, errors); 1717 needRecomputeKey = true; 1718 } 1719 1720 for (auto & newCand : satisfied) { 1721 // recomputes type key, if satisfyAssertions changed it 1722 if (needRecomputeKey) 1723 { 1724 ast::ptr< ast::Type > newType = newCand->expr->result; 1725 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get()); 1726 newCand->env.apply( newType ); 1727 mangleName = Mangle::mangle( newType ); 1728 } 1729 auto found = selected.find( mangleName ); 1730 if ( found != selected.end() ) { 1731 if ( newCand->cost < found->second.candidate->cost ) { 1732 PRINT( 1733 std::cerr << "cost " << newCand->cost << " beats " 1734 << found->second.candidate->cost << std::endl; 1735 ) 1736 1737 found->second = PruneStruct{ newCand }; 1738 } else if ( newCand->cost == found->second.candidate->cost ) { 1739 // if one of the candidates contains a deleted identifier, can pick the other, 1740 // since deleted expressions should not be ambiguous if there is another option 1741 // that is at least as good 1742 if ( findDeletedExpr( newCand->expr ) ) { 1743 // do nothing 1744 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 1745 } else if ( findDeletedExpr( found->second.candidate->expr ) ) { 1746 PRINT( std::cerr << "current is deleted" << std::endl; ) 1747 found->second = PruneStruct{ newCand }; 1748 } else { 1749 PRINT( std::cerr << "marking ambiguous" << std::endl; ) 1750 found->second.ambiguous = true; 1751 } 1752 } else { 1753 // xxx - can satisfyAssertions increase the cost? 1754 PRINT( 1755 std::cerr << "cost " << newCand->cost << " loses to " 1756 << found->second.candidate->cost << std::endl; 1757 ) 1758 } 1759 } else { 1760 selected.emplace_hint( found, mangleName, newCand ); 1761 } 1762 } 1763 } 1764 1765 // report unambiguous min-cost candidates 1766 // CandidateList out; 1767 for ( auto & target : selected ) { 1768 if ( target.second.ambiguous ) continue; 1769 1770 CandidateRef cand = target.second.candidate; 1771 1772 ast::ptr< ast::Type > newResult = cand->expr->result; 1773 cand->env.applyFree( newResult ); 1774 cand->expr = ast::mutate_field( 1775 cand->expr.get(), &ast::Expr::result, std::move( newResult ) ); 1776 1777 out.emplace_back( cand ); 1778 } 1779 // if everything is lost in satisfyAssertions, report the error 1780 return !selected.empty(); 1781 } 1782 1783 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 1784 // Find alternatives for expression 1785 ast::Pass<Finder> finder{ *this }; 1786 expr->accept( finder ); 1787 1788 if ( mode.failFast && candidates.empty() ) { 1789 switch(finder.core.reason.code) { 1790 case Finder::NotFound: 1791 { SemanticError( expr, "No alternatives for expression " ); break; } 1792 case Finder::NoMatch: 1793 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1794 case Finder::ArgsToFew: 1795 case Finder::ArgsToMany: 1796 case Finder::RetsToFew: 1797 case Finder::RetsToMany: 1798 case Finder::NoReason: 1799 default: 1800 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1801 } 1802 } 1803 1804 /* 1805 if ( mode.satisfyAssns || mode.prune ) { 1806 // trim candidates to just those where the assertions are satisfiable 1807 // - necessary pre-requisite to pruning 1808 CandidateList satisfied; 1809 std::vector< std::string > errors; 1810 for ( CandidateRef & candidate : candidates ) { 1811 satisfyAssertions( candidate, localSyms, satisfied, errors ); 1812 } 1813 1814 // fail early if none such 1815 if ( mode.failFast && satisfied.empty() ) { 1816 std::ostringstream stream; 1817 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1818 for ( const auto& err : errors ) { 1819 stream << err; 1820 } 1821 SemanticError( expr->location, stream.str() ); 1822 } 1823 1824 // reset candidates 1825 candidates = move( satisfied ); 1826 } 1827 */ 1828 1829 if ( mode.prune ) { 1830 // trim candidates to single best one 1831 PRINT( 1832 std::cerr << "alternatives before prune:" << std::endl; 1833 print( std::cerr, candidates ); 1834 ) 1835 1836 CandidateList pruned; 1837 std::vector<std::string> errors; 1838 bool found = pruneCandidates( candidates, pruned, errors ); 1839 1840 if ( mode.failFast && pruned.empty() ) { 1841 std::ostringstream stream; 1842 if (found) { 1843 CandidateList winners = findMinCost( candidates ); 1844 stream << "Cannot choose between " << winners.size() << " alternatives for " 1845 "expression\n"; 1846 ast::print( stream, expr ); 1847 stream << " Alternatives are:\n"; 1848 print( stream, winners, 1 ); 1849 SemanticError( expr->location, stream.str() ); 1850 } 1851 else { 1852 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1853 for ( const auto& err : errors ) { 1854 stream << err; 1855 } 1856 SemanticError( expr->location, stream.str() ); 1857 } 1858 } 1859 1860 auto oldsize = candidates.size(); 1861 candidates = std::move( pruned ); 1862 1863 PRINT( 1864 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 1865 ) 1866 PRINT( 1867 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1868 << std::endl; 1869 ) 1870 } 1871 1872 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1873 // adjusted 1874 if ( mode.adjust ) { 1875 for ( CandidateRef & r : candidates ) { 1876 r->expr = ast::mutate_field( 1877 r->expr.get(), &ast::Expr::result, 1878 adjustExprType( r->expr->result, r->env, context.symtab ) ); 1879 } 1880 } 1881 1882 // Central location to handle gcc extension keyword, etc. for all expressions 1883 for ( CandidateRef & r : candidates ) { 1884 if ( r->expr->extension != expr->extension ) { 1885 r->expr.get_and_mutate()->extension = expr->extension; 1886 } 1887 } 1888 } 1889 1890 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1891 const std::vector< ast::ptr< ast::Expr > > & xs 1892 ) { 1893 std::vector< CandidateFinder > out; 1894 1895 for ( const auto & x : xs ) { 1896 out.emplace_back( context, env ); 1897 out.back().find( x, ResolvMode::withAdjustment() ); 1898 1899 PRINT( 1900 std::cerr << "findSubExprs" << std::endl; 1901 print( std::cerr, out.back().candidates ); 1902 ) 1903 } 1904 1905 return out; 1906 } 1907 1970 1908 } // namespace ResolvExpr 1971 1909 -
src/ResolvExpr/CurrentObject.cc
rb110bcc r2ed94a9 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Mon Apr 10 9:40:00 202313 // Update Count : 1 811 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 09:16:01 2022 13 // Update Count : 15 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 eval31 30 #include "Common/Indenter.h" // for Indenter, operator<< 32 31 #include "Common/SemanticError.h" // for SemanticError … … 593 592 594 593 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 the611 /// 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 init630 /// alternative, but adding designators in operator* creates duplicates.631 virtual std::deque< InitAlternative > first() const = 0;632 };633 634 594 /// create a new MemberIterator that traverses a type correctly 635 595 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); … … 671 631 }; 672 632 673 /// Iterates over an indexed type: 674 class IndexIterator : public MemberIterator { 675 protected: 633 /// Iterates array types 634 class ArrayIterator final : public MemberIterator { 676 635 CodeLocation location; 636 const ArrayType * array = nullptr; 637 const Type * base = nullptr; 677 638 size_t index = 0; 678 639 size_t size = 0; 679 std::unique_ptr<MemberIterator> memberIter; 680 public: 681 IndexIterator( const CodeLocation & loc, size_t size ) : 682 location( loc ), size( size ) 683 {} 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 } 684 659 685 660 void setPosition( const Expr * expr ) { … … 690 665 auto arg = eval( expr ); 691 666 index = arg.first; 667 return; 692 668 693 669 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 707 683 708 684 void setPosition( 709 std::deque< ast::ptr<ast::Expr>>::const_iterator begin,710 std::deque< ast::ptr<ast::Expr>>::const_iterator end685 std::deque< ptr< Expr > >::const_iterator begin, 686 std::deque< ptr< Expr > >::const_iterator end 711 687 ) override { 712 688 if ( begin == end ) return; … … 719 695 720 696 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 }746 697 747 698 ArrayIterator & bigStep() override { … … 882 833 883 834 const Type * getNext() final { 884 bool hasMember = memberIter && *memberIter; 885 return hasMember ? memberIter->getType() : nullptr; 835 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 886 836 } 887 837 … … 947 897 }; 948 898 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() ) ); 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); 963 908 } 964 909 965 910 TupleIterator & bigStep() override { 966 ++index; 967 memberIter.reset( index < size ? 968 createMemberIterator( location, typeAtIndex() ) : nullptr ); 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 } 969 919 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 {};1004 920 } 1005 921 }; -
src/ResolvExpr/CurrentObject.h
rb110bcc r2ed94a9 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Jun 8 11:07:25 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thu Apr 6 16:14:00 202313 // Update Count : 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:36:48 2017 13 // Update Count : 3 14 14 // 15 15 … … 65 65 66 66 /// Iterates members of a type by initializer 67 class MemberIterator; 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 }; 68 104 69 105 /// Builds initializer lists in resolution -
src/ResolvExpr/ExplodedArg.hpp
rb110bcc r2ed94a9 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/ResolveAssertions.cc
rb110bcc r2ed94a9 30 30 #include "Common/FilterCombos.h" // for filterCombos 31 31 #include "Common/Indenter.h" // for Indenter 32 #include "Common/utility.h" // for sort_mins 32 33 #include "GenPoly/GenPoly.h" // for getFunctionType 33 34 #include "ResolvExpr/AlternativeFinder.h" // for computeConversionCost -
src/ResolvExpr/Resolver.cc
rb110bcc r2ed94a9 38 38 #include "AST/SymbolTable.hpp" 39 39 #include "AST/Type.hpp" 40 #include "Common/Eval.h" // for eval41 #include "Common/Iterate.hpp" // for group_iterate42 40 #include "Common/PassVisitor.h" // for PassVisitor 43 41 #include "Common/SemanticError.h" // for SemanticError 44 42 #include "Common/Stats/ResolveTime.h" // for ResolveTime::start(), ResolveTime::stop() 45 #include "Common/ ToString.hpp" // for toCString43 #include "Common/utility.h" // for ValueGuard, group_iterate 46 44 #include "InitTweak/GenInit.h" 47 45 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt -
src/ResolvExpr/Resolver.h
rb110bcc r2ed94a9 34 34 class Decl; 35 35 class DeletedExpr; 36 class Expr;37 36 class Init; 38 37 class StmtExpr; -
src/SymTab/Autogen.cc
rb110bcc r2ed94a9 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 14 15:03:00 202313 // Update Count : 6 412 // Last Modified On : Fri Apr 27 14:39:06 2018 13 // Update Count : 63 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 213 217 /// inserts a forward declaration for functionDecl into declsToAdd 214 218 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 230 234 } 231 235 236 // shallow copy the pointer list for return 237 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 232 247 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 233 248 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 241 256 ftype->parameters.push_back( dstParam ); 242 257 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); 243 266 } 244 267 -
src/SymTab/Autogen.h
rb110bcc r2ed94a9 9 9 // Author : Rob Schluntz 10 10 // Created On : Sun May 17 21:53:34 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Fri Apr 14 15:06:00 202313 // Update Count : 1 711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 16:38:06 2019 13 // Update Count : 16 14 14 // 15 15 … … 45 45 /// returns true if obj's name is the empty string and it has a bitfield width 46 46 bool isUnnamedBitfield( ObjectDecl * obj ); 47 bool isUnnamedBitfield( const ast::ObjectDecl * obj ); 47 48 48 49 /// generate the type of an assignment function for paramType. … … 54 55 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 55 56 57 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true); 58 56 59 /// generate the type of a copy constructor for paramType. 57 60 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic … … 64 67 template< typename OutputIterator > 65 68 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 ); 66 75 67 76 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. … … 112 121 113 122 *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 and 130 /// srcParam. Should only be called with non-array types. 131 /// optionally returns a statement which must be inserted prior to the containing loop, if 132 /// there is one 133 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 = nullptr 138 ) { 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 cast 143 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 of 150 // "?=?", "?{}", 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 and 155 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue 156 // is considered a qualifier - for AddressExpr to resolve, its argument must have an 157 // 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 addCast 160 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 arguments 171 ++srcParam; 172 173 // return if adding reference fails -- will happen on default ctor and dtor 174 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 }; 114 180 115 181 srcParam.clearArrayIndices(); … … 182 248 } 183 249 250 /// Store in out a loop which calls fname on each element of the array with srcParam and 251 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0 252 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 = LoopForward 258 ) { 259 static UniqueName indexName( "_index" ); 260 261 // for a flexible array member nothing is done -- user must define own assignment 262 if ( ! array->dimension ) return; 263 264 if ( addCast ) { 265 // peel off array layer from cast 266 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/or 302 // array list initializer 303 srcParam.addArrayIndex( indexVar, array->dimension ); 304 305 // for stmt's body, eventually containing call 306 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 variable 312 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 184 320 template< typename OutputIterator > 185 321 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { … … 189 325 } else { 190 326 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 forward 335 ) { 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 ); 191 344 } 192 345 } … … 226 379 } 227 380 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 = LoopForward 385 ) { 386 // unnamed bit fields are not copied as they cannot be accessed 387 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 are 405 // 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 } 228 414 } // namespace SymTab 229 415 -
src/SymTab/FixFunction.cc
rb110bcc r2ed94a9 21 21 #include "AST/Pass.hpp" 22 22 #include "AST/Type.hpp" 23 #include "Common/utility.h" // for copy23 #include "Common/utility.h" // for maybeClone, copy 24 24 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarati... 25 25 #include "SynTree/Expression.h" // for Expression -
src/SymTab/Mangler.cc
rb110bcc r2ed94a9 24 24 #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup 25 25 #include "Common/PassVisitor.h" 26 #include "Common/ToString.hpp" // for toCString27 26 #include "Common/SemanticError.h" // for SemanticError 27 #include "Common/utility.h" // for toString 28 28 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 29 29 #include "SynTree/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... -
src/SymTab/Validate.cc
rb110bcc r2ed94a9 55 55 #include "Common/ScopedMap.h" // for ScopedMap 56 56 #include "Common/SemanticError.h" // for SemanticError 57 #include "Common/ToString.hpp" // for toCString58 57 #include "Common/UniqueName.h" // for UniqueName 59 #include "Common/utility.h" // for cloneAll, deleteAll58 #include "Common/utility.h" // for operator+, cloneAll, deleteAll 60 59 #include "CompilationState.h" // skip some passes in new-ast build 61 60 #include "Concurrency/Keywords.h" // for applyKeywords -
src/SymTab/ValidateType.cc
rb110bcc r2ed94a9 18 18 #include "CodeGen/OperatorTable.h" 19 19 #include "Common/PassVisitor.h" 20 #include "Common/ToString.hpp"21 20 #include "SymTab/FixFunction.h" 22 21 #include "SynTree/Declaration.h" -
src/SymTab/module.mk
rb110bcc r2ed94a9 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/FixFunction.h \ 22 SymTab/GenImplicitCall.cpp \23 SymTab/GenImplicitCall.hpp \24 22 SymTab/Indexer.cc \ 25 23 SymTab/Indexer.h \ -
src/SynTree/AggregateDecl.cc
rb110bcc r2ed94a9 19 19 20 20 #include "Attribute.h" // for Attribute 21 #include "Common/Eval.h" // for eval22 21 #include "Common/utility.h" // for printAll, cloneAll, deleteAll 23 22 #include "Declaration.h" // for AggregateDecl, TypeDecl, Declaration -
src/SynTree/FunctionDecl.cc
rb110bcc r2ed94a9 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 95 89 if ( statements ) { 96 90 os << indent << "... with body" << endl << indent+1; -
src/SynTree/Type.cc
rb110bcc r2ed94a9 16 16 17 17 #include "Attribute.h" // for Attribute 18 #include "Common/ToString.hpp" // for toCString19 18 #include "Common/utility.h" // for cloneAll, deleteAll, printAll 20 19 #include "InitTweak/InitTweak.h" // for getPointerBase … … 106 105 int Type::referenceDepth() const { return 0; } 107 106 108 AggregateDecl * Type::getAggr() const {109 assertf( false, "Non-aggregate type: %s", toCString( this ) );110 }111 112 107 TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); } 113 108 -
src/SynTree/Type.h
rb110bcc r2ed94a9 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun Feb 19 22:37:10 202313 // Update Count : 17 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jul 14 15:40:00 2021 13 // Update Count : 171 14 14 // 15 15 … … 23 23 24 24 #include "BaseSyntaxNode.h" // for BaseSyntaxNode 25 #include "Common/ Iterate.hpp"// for operator+25 #include "Common/utility.h" // 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 ;187 virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); } 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 ); }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 272 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 273 273 bool isInteger() const; … … 279 279 280 280 // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] ) 281 Expression * dimension;281 Expression *dimension; 282 282 bool isVarLen; 283 283 bool isStatic; 284 284 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 * >() );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 * >() ); 287 287 PointerType( const PointerType& ); 288 288 virtual ~PointerType(); 289 289 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; }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; } 294 294 bool get_isVarLen() { return isVarLen; } 295 295 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 301 301 virtual bool isComplete() const override { return ! isVarLen; } 302 302 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 ); }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 ); } 307 307 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 308 308 }; … … 310 310 class ArrayType : public Type { 311 311 public: 312 Type * base;313 Expression * dimension;312 Type *base; 313 Expression *dimension; 314 314 bool isVarLen; 315 315 bool isStatic; 316 316 317 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 * >() ); 318 318 ArrayType( const ArrayType& ); 319 319 virtual ~ArrayType(); 320 320 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; }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; } 325 325 bool get_isVarLen() { return isVarLen; } 326 326 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 333 333 virtual bool isComplete() const override { return dimension || isVarLen; } 334 334 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 ); }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 ); } 339 339 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 340 340 }; … … 348 348 virtual ~QualifiedType(); 349 349 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 ); }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 ); } 354 354 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 355 355 }; … … 357 357 class ReferenceType : public Type { 358 358 public: 359 Type * base;360 361 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 * >() ); 362 362 ReferenceType( const ReferenceType & ); 363 363 virtual ~ReferenceType(); 364 364 365 Type * get_base() { return base; }366 void set_base( Type * newValue ) { base = newValue; }365 Type *get_base() { return base; } 366 void set_base( Type *newValue ) { base = newValue; } 367 367 368 368 virtual int referenceDepth() const override; … … 375 375 virtual TypeSubstitution genericSubstitution() const override; 376 376 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 ); }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 ); } 381 381 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 382 382 }; … … 405 405 bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; } 406 406 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 ); }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 ); } 411 411 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 412 412 }; … … 414 414 class ReferenceToType : public Type { 415 415 public: 416 std::list< Expression * > parameters;416 std::list< Expression* > parameters; 417 417 std::string name; 418 418 bool hoistType; … … 428 428 void set_hoistType( bool newValue ) { hoistType = newValue; } 429 429 430 virtual ReferenceToType * clone() const override = 0;430 virtual ReferenceToType *clone() const override = 0; 431 431 virtual void accept( Visitor & v ) override = 0; 432 virtual Type * acceptMutator( Mutator & m ) override = 0;432 virtual Type *acceptMutator( Mutator & m ) override = 0; 433 433 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 434 434 … … 443 443 // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree, 444 444 // where the structure used in this type is actually defined 445 StructDecl * baseStruct;445 StructDecl *baseStruct; 446 446 447 447 StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseStruct( 0 ) {} … … 449 449 StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {} 450 450 451 StructDecl * get_baseStruct() const { return baseStruct; }452 void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }451 StructDecl *get_baseStruct() const { return baseStruct; } 452 void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; } 453 453 454 454 /// Accesses generic parameters of base struct (NULL if none such) … … 466 466 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 467 467 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 ); }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 ); } 472 472 473 473 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 481 481 // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, 482 482 // where the union used in this type is actually defined 483 UnionDecl * baseUnion;483 UnionDecl *baseUnion; 484 484 485 485 UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseUnion( 0 ) {} … … 487 487 UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {} 488 488 489 UnionDecl * get_baseUnion() const { return baseUnion; }489 UnionDecl *get_baseUnion() const { return baseUnion; } 490 490 void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; } 491 491 … … 504 504 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 505 505 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 ); }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 ); } 510 510 511 511 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 519 519 // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree, 520 520 // where the enum used in this type is actually defined 521 EnumDecl * baseEnum = nullptr;521 EnumDecl *baseEnum = nullptr; 522 522 523 523 EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {} … … 525 525 EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {} 526 526 527 EnumDecl * get_baseEnum() const { return baseEnum; }528 void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }527 EnumDecl *get_baseEnum() const { return baseEnum; } 528 void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; } 529 529 530 530 virtual bool isComplete() const override; … … 532 532 virtual AggregateDecl * getAggr() const override; 533 533 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 ); }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 ); } 538 538 539 539 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 556 556 virtual bool isComplete() const override; 557 557 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 ); }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 ); } 562 562 private: 563 563 virtual std::string typeString() const override; … … 569 569 // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree, 570 570 // where the type used here is actually defined 571 TypeDecl * baseType;571 TypeDecl *baseType; 572 572 bool isFtype; 573 573 574 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 * >() ); 575 575 TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 576 576 TypeInstType( const TypeInstType & other ); 577 577 ~TypeInstType(); 578 578 579 TypeDecl * get_baseType() const { return baseType; }580 void set_baseType( TypeDecl * newValue );579 TypeDecl *get_baseType() const { return baseType; } 580 void set_baseType( TypeDecl *newValue ); 581 581 bool get_isFtype() const { return isFtype; } 582 582 void set_isFtype( bool newValue ) { isFtype = newValue; } … … 584 584 virtual bool isComplete() const override; 585 585 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 ); }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 ); } 590 590 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 591 591 private: … … 622 622 // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness 623 623 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 ); }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 ); } 628 628 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 629 629 }; … … 631 631 class TypeofType : public Type { 632 632 public: 633 Expression * expr;///< expression to take the type of634 bool is_basetypeof; ///< true iff is basetypeof type635 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,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, 638 638 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 639 639 TypeofType( const TypeofType& ); 640 640 virtual ~TypeofType(); 641 641 642 Expression * get_expr() const { return expr; }643 void set_expr( Expression * newValue ) { expr = newValue; }642 Expression *get_expr() const { return expr; } 643 void set_expr( Expression *newValue ) { expr = newValue; } 644 644 645 645 virtual bool isComplete() const override { assert( false ); return false; } 646 646 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 ); }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 ); } 651 651 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 652 652 }; … … 654 654 class VTableType : public Type { 655 655 public: 656 Type * base;657 658 VTableType( const Type::Qualifiers & tq, Type * base,656 Type *base; 657 658 VTableType( const Type::Qualifiers & tq, Type *base, 659 659 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 660 660 VTableType( const VTableType & ); 661 661 virtual ~VTableType(); 662 662 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 ); }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 ); } 670 670 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 671 671 }; … … 674 674 public: 675 675 std::string name; 676 Expression * expr;677 Type * type;676 Expression *expr; 677 Type *type; 678 678 bool isType; 679 679 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 * >() );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 * >() ); 682 682 AttrType( const AttrType& ); 683 683 virtual ~AttrType(); … … 685 685 const std::string & get_name() const { return name; } 686 686 void set_name( const std::string & newValue ) { name = 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; }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; } 691 691 bool get_isType() const { return isType; } 692 692 void set_isType( bool newValue ) { isType = newValue; } … … 694 694 virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here 695 695 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 ); }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 ); } 700 700 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 701 701 }; … … 709 709 virtual bool isComplete() const override{ return true; } // xxx - is this right? 710 710 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 ); }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 ); } 715 715 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 716 716 }; … … 722 722 ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 723 723 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 ); }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 ); } 728 728 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 729 729 }; … … 735 735 OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 736 736 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 ); }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 ); } 741 741 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 742 742 }; … … 746 746 GlobalScopeType(); 747 747 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 ); }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 ); } 752 752 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 753 753 }; -
src/Validate/Autogen.cpp
rb110bcc r2ed94a9 39 39 #include "InitTweak/GenInit.h" // for fixReturnStatements 40 40 #include "InitTweak/InitTweak.h" // for isAssignment, isCopyConstructor 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall42 41 #include "SymTab/Mangler.h" // for Mangler 43 42 #include "CompilationState.h" … … 424 423 for ( unsigned int index = 0 ; index < fields ; ++index ) { 425 424 auto member = aggr->members[index].strict_as<ast::DeclWithType>(); 426 if ( ast::isUnnamedBitfield(425 if ( SymTab::isUnnamedBitfield( 427 426 dynamic_cast<const ast::ObjectDecl *>( member ) ) ) { 428 427 if ( index == fields - 1 ) { … … 600 599 // Not sure why it could be null. 601 600 // Don't make a function for a parameter that is an unnamed bitfield. 602 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) {601 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) { 603 602 continue; 604 603 // Matching Parameter: Initialize the field by copy. -
src/Validate/FixQualifiedTypes.cpp
rb110bcc r2ed94a9 16 16 #include "Validate/FixQualifiedTypes.hpp" 17 17 18 #include "AST/LinkageSpec.hpp" // for Linkage19 18 #include "AST/Pass.hpp" 20 19 #include "AST/TranslationUnit.hpp" 21 #include "Common/ToString.hpp" // for toString22 #include "SymTab/Mangler.h" // for Mangler23 20 #include "Validate/NoIdSymbolTable.hpp" 21 #include "SymTab/Mangler.h" // for Mangler 22 #include "AST/LinkageSpec.hpp" // for Linkage 24 23 25 24 namespace Validate { -
src/Validate/ForallPointerDecay.cpp
rb110bcc r2ed94a9 22 22 #include "CodeGen/OperatorTable.h" 23 23 #include "Common/CodeLocation.h" 24 #include "Common/ToString.hpp"25 24 #include "SymTab/FixFunction.h" 26 25 -
src/Validate/HandleAttributes.cc
rb110bcc r2ed94a9 17 17 18 18 #include "CompilationState.h" 19 #include "Common/Eval.h"20 19 #include "Common/PassVisitor.h" 21 #include "Common/ToString.hpp"22 20 #include "Common/SemanticError.h" 23 21 #include "ResolvExpr/Resolver.h" -
src/Validate/HoistStruct.cpp
rb110bcc r2ed94a9 16 16 #include "Validate/HoistStruct.hpp" 17 17 18 #include <sstream>19 20 18 #include "AST/Pass.hpp" 21 19 #include "AST/TranslationUnit.hpp" 20 #include "Common/utility.h" 22 21 23 22 namespace Validate { -
src/Virtual/module.mk
rb110bcc r2ed94a9 19 19 Virtual/ExpandCasts.h \ 20 20 Virtual/Tables.cc \ 21 Virtual/Tables.h \ 22 Virtual/VirtualDtor.cpp \ 23 Virtual/VirtualDtor.hpp 21 Virtual/Tables.h -
src/include/cassert
rb110bcc r2ed94a9 20 20 #include_next <cassert> 21 21 22 #include "Common/ToString.hpp" 22 #include <string> 23 24 template < typename ... Params > 25 std::string toString( const Params & ... params ); 23 26 24 27 #ifdef NDEBUG -
src/main.cc
rb110bcc r2ed94a9 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 21:12:17 202313 // Update Count : 6 8211 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Oct 5 12:06:00 2022 13 // Update Count : 679 14 14 // 15 15 … … 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Util.hpp" // for checkInvariants35 34 #include "CompilationState.h" 36 35 #include "../config.h" // for CFA_LIBDIR … … 41 40 #include "CodeTools/TrackLoc.h" // for fillLocations 42 41 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 42 #include "Common/CompilerError.h" // for CompilerError 43 43 #include "Common/DeclStats.hpp" // for printDeclStats 44 44 #include "Common/ResolvProtoDump.hpp" // for dumpAsResolverProto 45 45 #include "Common/Stats.h" // for Stats 46 #include "Common/UnimplementedError.h" // for UnimplementedError 46 47 #include "Common/utility.h" // for deleteAll, filter, printAll 47 48 #include "Concurrency/Actors.hpp" // for implementActors … … 83 84 #include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign 84 85 #include "Virtual/ExpandCasts.h" // for expandCasts 85 #include "Virtual/VirtualDtor.hpp" // for implementVirtDtors86 86 87 87 static void NewPass( const char * const name ) { … … 102 102 } 103 103 104 // Helpers for checkInvariant: 105 void checkInvariants( std::list< Declaration * > & ) {} 106 using ast::checkInvariants; 107 108 #define PASS( name, pass, unit, ... ) \ 104 #define PASS( name, pass ) \ 109 105 if ( errorp ) { cerr << name << endl; } \ 110 106 NewPass(name); \ 111 107 Stats::Time::StartBlock(name); \ 112 pass(unit,##__VA_ARGS__); \ 113 Stats::Time::StopBlock(); \ 114 if ( invariant ) { \ 115 checkInvariants(unit); \ 116 } 117 118 #define DUMP( cond, unit ) \ 119 if ( cond ) { \ 120 dump(unit); \ 121 return EXIT_SUCCESS; \ 122 } 108 pass; \ 109 Stats::Time::StopBlock(); 123 110 124 111 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start … … 287 274 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" ); 288 275 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 289 parse( gcc_builtins, ast::Linkage::Compiler );276 parse( gcc_builtins, LinkageSpec::Compiler ); 290 277 291 278 // read the extra prelude in, if not generating the cfa library 292 279 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" ); 293 280 assertf( extras, "cannot open extras.cf\n" ); 294 parse( extras, ast::Linkage::BuiltinC );281 parse( extras, LinkageSpec::BuiltinC ); 295 282 296 283 if ( ! libcfap ) { … … 298 285 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" ); 299 286 assertf( prelude, "cannot open prelude.cfa\n" ); 300 parse( prelude, ast::Linkage::Intrinsic );287 parse( prelude, LinkageSpec::Intrinsic ); 301 288 302 289 // Read to cfa builtins, if not generating the cfa library 303 290 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" ); 304 291 assertf( builtins, "cannot open builtins.cf\n" ); 305 parse( builtins, ast::Linkage::BuiltinCFA );306 } // if 307 } // if 308 309 parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );292 parse( builtins, LinkageSpec::BuiltinCFA ); 293 } // if 294 } // if 295 296 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug ); 310 297 311 298 transUnit = buildUnit(); 312 299 313 DUMP( astp, std::move( transUnit ) ); 300 if ( astp ) { 301 dump( std::move( transUnit ) ); 302 return EXIT_SUCCESS; 303 } // if 314 304 315 305 Stats::Time::StopBlock(); … … 320 310 } 321 311 322 PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit ); 323 324 PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit ); 325 DUMP( exdeclp, std::move( transUnit ) ); 326 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit ); 327 PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit ); 328 PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit ); 329 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit ); 330 331 PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit ); 332 333 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit ); 334 PASS( "Hoist Struct", Validate::hoistStruct, transUnit ); 335 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit ); 336 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit ); 337 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit ); 338 PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit ); 339 PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit ); 340 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit ); 341 PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit ); 342 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit ); 343 344 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit ); 345 346 PASS( "Implement Actors", Concurrency::implementActors, transUnit ); 347 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit ); 348 PASS( "Implement Mutex", Concurrency::implementMutex, transUnit ); 349 PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit ); 350 PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit ); 351 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit ); 352 PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit ); 353 PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit ); 312 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) ); 313 // Hoist Type Decls pulls some declarations out of contexts where 314 // locations are not tracked. Perhaps they should be, but for now 315 // the full fill solves it. 316 forceFillCodeLocations( transUnit ); 317 318 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) ); 319 if ( exdeclp ) { 320 dump( std::move( transUnit ) ); 321 return EXIT_SUCCESS; 322 } 323 324 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) ); 325 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) ); 326 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) ); 327 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) ); 328 329 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) ); 330 331 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) ); 332 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) ); 333 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) ); 334 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) ); 335 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) ); 336 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) ); 337 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) ); 338 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 339 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 340 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) ); 341 342 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) ); 343 344 PASS( "Implement Actors", Concurrency::implementActors( transUnit ) ); 345 346 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 347 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); 348 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) ); 349 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) ); 350 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) ); 351 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) ); 354 352 355 353 if ( symtabp ) { … … 362 360 } // if 363 361 364 DUMP( validp, std::move( transUnit ) ); 365 366 PASS( "Translate Throws", ControlStruct::translateThrows, transUnit ); 367 PASS( "Fix Labels", ControlStruct::fixLabels, transUnit ); 368 PASS( "Fix Names", CodeGen::fixNames, transUnit ); 369 PASS( "Gen Init", InitTweak::genInit, transUnit ); 370 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit ); 362 if ( validp ) { 363 dump( std::move( transUnit ) ); 364 return EXIT_SUCCESS; 365 } // if 366 367 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) ); 368 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) ); 369 PASS( "Fix Names", CodeGen::fixNames( transUnit ) ); 370 PASS( "Gen Init", InitTweak::genInit( transUnit ) ); 371 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) ); 371 372 372 373 if ( libcfap ) { … … 380 381 } // if 381 382 382 DUMP( bresolvep, std::move( transUnit ) ); 383 if ( bresolvep ) { 384 dump( std::move( transUnit ) ); 385 return EXIT_SUCCESS; 386 } // if 383 387 384 388 if ( resolvprotop ) { … … 387 391 } // if 388 392 389 PASS( "Resolve", ResolvExpr::resolve, transUnit ); 390 DUMP( exprp, std::move( transUnit ) ); 391 392 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 393 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 394 if ( exprp ) { 395 dump( std::move( transUnit ) ); 396 return EXIT_SUCCESS; 397 } // if 398 399 forceFillCodeLocations( transUnit ); 400 401 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary())); 393 402 394 403 // fix ObjectDecl - replaces ConstructorInit nodes 395 DUMP( ctorinitp, std::move( transUnit ) ); 404 if ( ctorinitp ) { 405 dump( std::move( transUnit ) ); 406 return EXIT_SUCCESS; 407 } // if 396 408 397 409 // Currently not working due to unresolved issues with UniqueExpr 398 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 reused399 400 PASS( "Translate Tries", ControlStruct::translateTries , transUnit);401 PASS( "Gen Waitfor", Concurrency::generateWaitFor , transUnit);410 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 411 412 PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) ); 413 PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) ); 402 414 403 415 // Needs to happen before tuple types are expanded. 404 PASS( "Convert Specializations", GenPoly::convertSpecializations, transUnit ); 405 406 PASS( "Expand Tuples", Tuples::expandTuples, transUnit ); 407 DUMP( tuplep, std::move( transUnit ) ); 416 PASS( "Convert Specializations", GenPoly::convertSpecializations( transUnit ) ); 417 418 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 419 420 if ( tuplep ) { 421 dump( std::move( transUnit ) ); 422 return EXIT_SUCCESS; 423 } // if 408 424 409 425 // Must come after Translate Tries. 410 PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit ); 411 412 PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit ); 413 DUMP( genericsp, std::move( transUnit ) ); 414 415 PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit ); 426 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) ); 427 428 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) ); 429 if ( genericsp ) { 430 dump( std::move( transUnit ) ); 431 return EXIT_SUCCESS; 432 } // if 433 434 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) ); 416 435 417 436 translationUnit = convert( std::move( transUnit ) ); 418 437 419 DUMP( bboxp, translationUnit ); 420 PASS( "Box", GenPoly::box, translationUnit ); 421 422 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit ); 438 if ( bboxp ) { 439 dump( translationUnit ); 440 return EXIT_SUCCESS; 441 } // if 442 PASS( "Box", GenPoly::box( translationUnit ) ); 443 444 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) ); 423 445 424 446 // Code has been lowered to C, now we can start generation. 425 447 426 DUMP( bcodegenp, translationUnit ); 448 if ( bcodegenp ) { 449 dump( translationUnit ); 450 return EXIT_SUCCESS; 451 } // if 427 452 428 453 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 431 456 432 457 CodeTools::fillLocations( translationUnit ); 433 PASS( "Code Gen", CodeGen::generate , translationUnit, *output, ! genproto, prettycodegenp, true, linemarks);458 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) ); 434 459 435 460 CodeGen::FixMain::fix( translationUnit, *output, … … 451 476 } // if 452 477 e.print(); 478 if ( output != &cout ) { 479 delete output; 480 } // if 481 return EXIT_FAILURE; 482 } catch ( UnimplementedError & e ) { 483 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl; 484 if ( output != &cout ) { 485 delete output; 486 } // if 487 return EXIT_FAILURE; 488 } catch ( CompilerError & e ) { 489 cerr << "Compiler Error: " << e.get_what() << endl; 490 cerr << "(please report bugs to [REDACTED])" << endl; 453 491 if ( output != &cout ) { 454 492 delete output; … … 479 517 480 518 481 static const char optstring[] = ":c:gh ilLmNnpdP:S:twW:D:";519 static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:"; 482 520 483 521 enum { PreludeDir = 128 }; … … 486 524 { "gdb", no_argument, nullptr, 'g' }, 487 525 { "help", no_argument, nullptr, 'h' }, 488 { "invariant", no_argument, nullptr, 'i' },489 526 { "libcfa", no_argument, nullptr, 'l' }, 490 527 { "linemarks", no_argument, nullptr, 'L' }, 491 { "no-main", no_argument, nullptr, 'm' },528 { "no-main", no_argument, 0, 'm' }, 492 529 { "no-linemarks", no_argument, nullptr, 'N' }, 493 530 { "no-prelude", no_argument, nullptr, 'n' }, … … 508 545 "wait for gdb to attach", // -g 509 546 "print translator help message", // -h 510 "invariant checking during AST passes", // -i511 547 "generate libcfa.c", // -l 512 548 "generate line marks", // -L … … 602 638 usage( argv ); // no return 603 639 break; 604 case 'i': // invariant checking605 invariant = true;606 break;607 640 case 'l': // generate libcfa.c 608 641 libcfap = true; -
tests/.expect/PRNG.x64.txt
rb110bcc r2ed94a9 1 2 CFA xoshiro256pp3 1 4 2 PRNG() PRNG(5) PRNG(0,5) 5 13944458589275087071 3 26 129977468648444256 0 47 2357727400298891021 2 28 8855179187835660146 3 39 9957620185645882382 4 110 13396406983727409795 0 511 3342782395220265920 0 512 1707651271867677937 1013 1 6402561450140881681 0 114 1 7838519215740313729 4 215 7425936020594490136 4016 4174865704721714670 3517 16055269689200152092 0 218 1 5091270195803594018 1 519 11807315541476180798 1 120 1 0697186588988060306 4121 14665526411527044929 3 222 1 1289342279096164771 2 523 1 6126980828050300615 1 424 7821578301767524260 4 13 8464106481 4 4 4 5215204710507639537 1 2 5 1880401021892145483 0 4 6 12503840966285181348 2 5 7 801971300205459356 0 2 8 6123812066052045228 3 1 9 7691074772031490538 4 3 10 4793575011534070065 0 0 11 10647551928893428440 1 3 12 10865128702974868079 0 3 13 530720947131684825 3 0 14 10520125295812061287 1 5 15 7539957561855178679 4 4 16 13739826796006269835 0 2 17 4289714351582916365 3 2 18 16911914987551424434 2 1 19 5327155553462670435 4 0 20 16251986870929071204 4 4 21 13394433706240223001 0 3 22 4814982023332666924 4 0 25 23 seed 1009 26 24 27 25 Sequential 28 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%26 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 29 27 30 28 Concurrent 31 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%32 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%33 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%34 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%29 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 30 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 31 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 32 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 35 33 36 34 prng() prng(5) prng(0,5) 37 13944458589275087071 3 238 129977468648444256 0 439 2357727400298891021 2 240 8855179187835660146 3 341 9957620185645882382 4 142 13396406983727409795 0 543 3342782395220265920 0 544 1707651271867677937 1045 1 6402561450140881681 0 146 1 7838519215740313729 4 247 7425936020594490136 4048 4174865704721714670 3549 16055269689200152092 0 250 1 5091270195803594018 1 551 11807315541476180798 1 152 1 0697186588988060306 4153 14665526411527044929 3 254 1 1289342279096164771 2 555 1 6126980828050300615 1 456 7821578301767524260 4 135 8464106481 4 4 36 5215204710507639537 1 2 37 1880401021892145483 0 4 38 12503840966285181348 2 5 39 801971300205459356 0 2 40 6123812066052045228 3 1 41 7691074772031490538 4 3 42 4793575011534070065 0 0 43 10647551928893428440 1 3 44 10865128702974868079 0 3 45 530720947131684825 3 0 46 10520125295812061287 1 5 47 7539957561855178679 4 4 48 13739826796006269835 0 2 49 4289714351582916365 3 2 50 16911914987551424434 2 1 51 5327155553462670435 4 0 52 16251986870929071204 4 4 53 13394433706240223001 0 3 54 4814982023332666924 4 0 57 55 seed 1009 58 56 59 57 Sequential 60 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%58 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 61 59 62 60 Concurrent 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%61 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 62 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 63 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 64 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 67 65 68 66 prng(t) prng(t,5) prng(t,0,5) 69 13944458589275087071 3 270 129977468648444256 0 471 2357727400298891021 2 272 8855179187835660146 3 373 9957620185645882382 4 174 13396406983727409795 0 575 3342782395220265920 0 576 1707651271867677937 1077 1 6402561450140881681 0 178 1 7838519215740313729 4 279 7425936020594490136 4080 4174865704721714670 3581 16055269689200152092 0 282 1 5091270195803594018 1 583 11807315541476180798 1 184 1 0697186588988060306 4185 14665526411527044929 3 286 1 1289342279096164771 2 587 1 6126980828050300615 1 488 7821578301767524260 4 167 8464106481 4 4 68 5215204710507639537 1 2 69 1880401021892145483 0 4 70 12503840966285181348 2 5 71 801971300205459356 0 2 72 6123812066052045228 3 1 73 7691074772031490538 4 3 74 4793575011534070065 0 0 75 10647551928893428440 1 3 76 10865128702974868079 0 3 77 530720947131684825 3 0 78 10520125295812061287 1 5 79 7539957561855178679 4 4 80 13739826796006269835 0 2 81 4289714351582916365 3 2 82 16911914987551424434 2 1 83 5327155553462670435 4 0 84 16251986870929071204 4 4 85 13394433706240223001 0 3 86 4814982023332666924 4 0 89 87 seed 1009 90 88 91 89 Sequential 92 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%90 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 93 91 94 92 Concurrent 95 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%96 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%97 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%98 trials 100000000 buckets 100000 min 87 5 max 1146avg 1000.0 std 31.6 rstd 3.2%93 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 94 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 95 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% 96 trials 100000000 buckets 100000 min 871 max 1144 avg 1000.0 std 31.6 rstd 3.2% -
tests/.expect/PRNG.x86.txt
rb110bcc r2ed94a9 1 2 CFA xoshiro128pp3 1 4 2 PRNG() PRNG(5) PRNG(0,5) 5 2884683541 0 06 3465286746 2 47 3268922916 0 18 2396374907 3 09 2135076892 4 110 944377718 3111 2204845346 3312 3736609533 0 413 4063231336 0 214 1075394776 0 215 712844808 4 016 4246343110 3 117 3793873837 2 118 3690340337 1419 319207944 1420 18 15791072 3 521 2581617261 1 522 3873329448 1 323 832631329 4 024 651551615 3 53 130161 1 1 4 4074541490 0 0 5 927506267 0 3 6 1991273445 1 3 7 669918146 2 3 8 519546860 1 1 9 1136699882 4 3 10 2130185384 3 1 11 992239050 0 5 12 2250903111 0 1 13 1544429724 3 2 14 1591091660 3 3 15 2511657707 2 4 16 1065770984 2 4 17 2412763405 4 4 18 1834447239 4 2 19 360289337 0 4 20 2449452027 1 1 21 3370425396 2 1 22 3109103043 0 3 25 23 seed 1009 26 24 27 25 Sequential 28 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%26 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 29 27 30 28 Concurrent 31 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%32 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%33 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%34 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%29 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 30 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 31 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 32 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 35 33 36 34 prng() prng(5) prng(0,5) 37 2884683541 0 038 3465286746 2 439 3268922916 0 140 2396374907 3 041 2135076892 4 142 944377718 3143 2204845346 3344 3736609533 0 445 4063231336 0 246 1075394776 0 247 712844808 4 048 4246343110 3 149 3793873837 2 150 3690340337 1451 319207944 1452 18 15791072 3 553 2581617261 1 554 3873329448 1 355 832631329 4 056 651551615 3 535 130161 1 1 36 4074541490 0 0 37 927506267 0 3 38 1991273445 1 3 39 669918146 2 3 40 519546860 1 1 41 1136699882 4 3 42 2130185384 3 1 43 992239050 0 5 44 2250903111 0 1 45 1544429724 3 2 46 1591091660 3 3 47 2511657707 2 4 48 1065770984 2 4 49 2412763405 4 4 50 1834447239 4 2 51 360289337 0 4 52 2449452027 1 1 53 3370425396 2 1 54 3109103043 0 3 57 55 seed 1009 58 56 59 57 Sequential 60 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%58 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 61 59 62 60 Concurrent 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%61 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 62 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 63 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 64 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 67 65 68 66 prng(t) prng(t,5) prng(t,0,5) 69 2884683541 0 070 3465286746 2 471 3268922916 0 172 2396374907 3 073 2135076892 4 174 944377718 3175 2204845346 3376 3736609533 0 477 4063231336 0 278 1075394776 0 279 712844808 4 080 4246343110 3 181 3793873837 2 182 3690340337 1483 319207944 1484 18 15791072 3 585 2581617261 1 586 3873329448 1 387 832631329 4 088 651551615 3 567 130161 1 1 68 4074541490 0 0 69 927506267 0 3 70 1991273445 1 3 71 669918146 2 3 72 519546860 1 1 73 1136699882 4 3 74 2130185384 3 1 75 992239050 0 5 76 2250903111 0 1 77 1544429724 3 2 78 1591091660 3 3 79 2511657707 2 4 80 1065770984 2 4 81 2412763405 4 4 82 1834447239 4 2 83 360289337 0 4 84 2449452027 1 1 85 3370425396 2 1 86 3109103043 0 3 89 87 seed 1009 90 88 91 89 Sequential 92 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%90 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 93 91 94 92 Concurrent 95 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%96 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%97 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%98 trials 100000000 buckets 100000 min 8 58 max 1147 avg 1000.0 std 31.5rstd 3.2%93 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 94 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 95 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% 96 trials 100000000 buckets 100000 min 867 max 1135 avg 1000.0 std 31.7 rstd 3.2% -
tests/.expect/attributes.arm64.txt
rb110bcc r2ed94a9 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st atic struct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) 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)( __attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused))signed int __param_0));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)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/attributes.x64.txt
rb110bcc r2ed94a9 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st atic struct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) 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)( __attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused))signed int __param_0));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)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/attributes.x86.txt
rb110bcc r2ed94a9 26 26 return _X4_retS12__anonymous0_1; 27 27 } 28 __attribute__ ((unused)) st atic struct __anonymous0 _X5DummyS12__anonymous0_1;28 __attribute__ ((unused)) 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)( __attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused))signed int __param_0));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)); 1354 1354 struct Vad { 1355 1355 __attribute__ ((unused)) signed int :4; -
tests/.expect/declarationSpecifier.arm64.txt
rb110bcc r2ed94a9 51 51 52 52 } 53 staticvolatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 staticvolatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 staticvolatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 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; 324 369 volatile const signed short int _X3x20KVs_1; 325 370 static volatile const signed short int _X3x21KVs_1; … … 330 375 static volatile const signed short int _X3x26KVs_1; 331 376 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 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 3KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 4KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 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; 647 737 _Thread_local signed int _X3x37i_1; 648 738 __thread signed int _X3x38i_1; … … 663 753 static inline volatile const signed short int _X3f27Fs___1(); 664 754 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 3FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 4FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 5FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 6FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 7FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 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(); 1025 1115 static inline volatile const signed short int _X3f41Fs___1(); 1026 1116 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/declarationSpecifier.x64.txt
rb110bcc r2ed94a9 51 51 52 52 } 53 staticvolatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 staticvolatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 staticvolatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 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; 324 369 volatile const signed short int _X3x20KVs_1; 325 370 static volatile const signed short int _X3x21KVs_1; … … 330 375 static volatile const signed short int _X3x26KVs_1; 331 376 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 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 3KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 4KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 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; 647 737 _Thread_local signed int _X3x37i_1; 648 738 __thread signed int _X3x38i_1; … … 663 753 static inline volatile const signed short int _X3f27Fs___1(); 664 754 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 3FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 4FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 5FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 6FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 7FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 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(); 1025 1115 static inline volatile const signed short int _X3f41Fs___1(); 1026 1116 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/declarationSpecifier.x86.txt
rb110bcc r2ed94a9 51 51 52 52 } 53 staticvolatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;53 volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1; 54 54 struct __anonymous1 { 55 55 signed int _X1ii_1; … … 96 96 97 97 } 98 staticvolatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;98 volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1; 99 99 struct __anonymous2 { 100 100 signed int _X1ii_1; … … 141 141 142 142 } 143 staticvolatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;143 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; 324 369 volatile const signed short int _X3x20KVs_1; 325 370 static volatile const signed short int _X3x21KVs_1; … … 330 375 static volatile const signed short int _X3x26KVs_1; 331 376 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 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;421 volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1; 422 422 struct __anonymous9 { 423 423 signed short int _X1is_1; … … 464 464 465 465 } 466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;466 volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1; 467 467 struct __anonymous10 { 468 468 signed short int _X1is_1; … … 509 509 510 510 } 511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;511 volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1; 512 512 struct __anonymous11 { 513 513 signed short int _X1is_1; … … 554 554 555 555 } 556 static volatile const struct __anonymous11 _X3x3 3KVS13__anonymous11_1;556 static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1; 557 557 struct __anonymous12 { 558 558 signed short int _X1is_1; … … 599 599 600 600 } 601 static volatile const struct __anonymous12 _X3x3 4KVS13__anonymous12_1;601 static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1; 602 602 struct __anonymous13 { 603 603 signed short int _X1is_1; … … 644 644 645 645 } 646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1; 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; 647 737 _Thread_local signed int _X3x37i_1; 648 738 __thread signed int _X3x38i_1; … … 663 753 static inline volatile const signed short int _X3f27Fs___1(); 664 754 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 3FS13__anonymous16___1();799 static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1(); 800 800 struct __anonymous17 { 801 801 signed int _X1ii_1; … … 842 842 843 843 } 844 static inline volatile const struct __anonymous17 _X3f3 4FS13__anonymous17___1();844 static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1(); 845 845 struct __anonymous18 { 846 846 signed int _X1ii_1; … … 887 887 888 888 } 889 static inline volatile const struct __anonymous18 _X3f3 5FS13__anonymous18___1();889 static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1(); 890 890 struct __anonymous19 { 891 891 signed int _X1ii_1; … … 932 932 933 933 } 934 static inline volatile const struct __anonymous19 _X3f3 6FS13__anonymous19___1();934 static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1(); 935 935 struct __anonymous20 { 936 936 signed int _X1ii_1; … … 977 977 978 978 } 979 static inline volatile const struct __anonymous20 _X3f3 7FS13__anonymous20___1();979 static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1(); 980 980 struct __anonymous21 { 981 981 signed int _X1ii_1; … … 1022 1022 1023 1023 } 1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1(); 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(); 1025 1115 static inline volatile const signed short int _X3f41Fs___1(); 1026 1116 static inline volatile const signed short int _X3f42Fs___1(); -
tests/.expect/nested_function.x64.txt
rb110bcc r2ed94a9 1 total 1 451 total 155 -
tests/.expect/nested_function.x86.txt
rb110bcc r2ed94a9 1 total 2451 total 105 -
tests/Makefile.am
rb110bcc r2ed94a9 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Mon Apr 10 23:24:02202314 ## Update Count : 9 613 ## Last Modified On : Fri Feb 3 23:06:44 2023 14 ## Update Count : 94 15 15 ############################################################################### 16 16 … … 184 184 185 185 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator \ 186 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment concurrent/waitfor/parse186 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment 187 187 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN) 188 188 $(CFACOMPILE_SYNTAX) -
tests/PRNG.cfa
rb110bcc r2ed94a9 8 8 // Created On : Wed Dec 29 09:38:12 2021 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Sat Apr 15 16:44:31 202311 // Update Count : 4 1910 // Last Modified On : Wed Dec 21 20:39:59 2022 11 // Update Count : 406 12 12 // 13 13 … … 15 15 #include <stdlib.hfa> // PRNG 16 16 #include <clock.hfa> 17 #include <thread.hfa> 17 18 #include <limits.hfa> // MAX 18 19 #include <math.hfa> // sqrt 19 20 #include <malloc.h> // malloc_stats 20 21 #include <locale.h> // setlocale 21 #include <thread.hfa>22 22 #include <mutex_stmt.hfa> 23 23 24 #define xstr(s) str(s) 25 #define str(s) #s 26 27 #if defined( __x86_64__ ) || defined( __aarch64__ ) // 64-bit architecture 24 #ifdef __x86_64__ // 64-bit architecture 28 25 #define PRNG PRNG64 29 26 #else // 32-bit architecture 30 27 #define PRNG PRNG32 31 28 #endif // __x86_64__ 32 33 //#define TIME34 29 35 30 #ifdef TIME // use -O2 -nodebug … … 43 38 #endif // TIME 44 39 45 static void avgstd( size_t trials, size_t buckets[] ) {46 size_t min = MAX, max = 0;40 void avgstd( unsigned int buckets[] ) { 41 unsigned int min = MAX, max = 0; 47 42 double sum = 0.0, diff; 48 43 for ( i; BUCKETS ) { … … 59 54 } // for 60 55 double std = sqrt( sum / BUCKETS ); 61 mutex( sout ) sout | "trials" | trials| "buckets" | BUCKETS56 mutex( sout ) sout | "trials" | TRIALS | "buckets" | BUCKETS 62 57 | "min" | min | "max" | max 63 58 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%"; … … 69 64 thread T1 {}; 70 65 void main( T1 & ) { 71 size_t * buckets = calloc( BUCKETS );// too big for task stack72 for ( TRIALS / 50 ) {66 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 67 for ( TRIALS / 100 ) { 73 68 buckets[rand() % BUCKETS] += 1; // concurrent 74 69 } // for 75 avgstd( TRIALS / 50,buckets );70 avgstd( buckets ); 76 71 free( buckets ); 77 72 } // main … … 81 76 PRNG prng; 82 77 if ( seed != 0 ) set_seed( prng, seed ); 83 size_t * buckets = calloc( BUCKETS );// too big for task stack78 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 84 79 for ( TRIALS ) { 85 80 buckets[prng( prng ) % BUCKETS] += 1; // concurrent 86 81 } // for 87 avgstd( TRIALS,buckets );82 avgstd( buckets ); 88 83 free( buckets ); 89 84 } // main … … 91 86 thread T3 {}; 92 87 void main( T3 & th ) { 93 size_t * buckets = calloc( BUCKETS );// too big for task stack94 for ( TRIALS / 5) {88 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 89 for ( TRIALS ) { 95 90 buckets[prng() % BUCKETS] += 1; // concurrent 96 91 } // for 97 avgstd( TRIALS / 5,buckets );92 avgstd( buckets ); 98 93 free( buckets ); 99 94 } // main … … 101 96 thread T4 {}; 102 97 void main( T4 & th ) { 103 size_t * buckets = calloc( BUCKETS );// too big for task stack98 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 104 99 for ( TRIALS ) { 105 buckets[prng( th ) % BUCKETS] += 1; // concurrent106 } // for 107 avgstd( TRIALS,buckets );100 buckets[prng( th ) % BUCKETS] += 1; // concurrent 101 } // for 102 avgstd( buckets ); 108 103 free( buckets ); 109 104 } // main … … 113 108 static void dummy( thread$ & th ) __attribute__(( noinline )); 114 109 static void dummy( thread$ & th ) { 115 size_t * buckets = (size_t *)calloc( BUCKETS, sizeof(size_t) ); // too big for task stack116 for ( size_t i = 0; i < TRIALS; i += 1 ) {110 unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack 111 for ( unsigned int i = 0; i < TRIALS; i += 1 ) { 117 112 buckets[prng( th ) % BUCKETS] += 1; // sequential 118 113 } // for 119 avgstd( TRIALS,buckets );114 avgstd( buckets ); 120 115 free( buckets ); 121 116 } // dummy … … 131 126 enum { TASKS = 4 }; 132 127 Time start; 133 134 128 #ifdef TIME // too slow for test and generates non-repeatable results 135 129 #if 1 136 sout | "glib rand" | nl | nl; 137 138 size_t rseed; 130 unsigned int rseed; 139 131 if ( seed != 0 ) rseed = seed; 140 132 else rseed = rdtscl(); … … 142 134 143 135 sout | sepDisable; 144 sout | nl |wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" );136 sout | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" ); 145 137 for ( 20 ) { 146 138 sout | wd(26, rand()) | nonl; … … 154 146 STARTTIME; 155 147 { 156 size_t * buckets = calloc( BUCKETS );// too big for task stack157 for ( i; TRIALS / 5) {148 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 149 for ( i; TRIALS / 10 ) { 158 150 buckets[rand() % BUCKETS] += 1; // sequential 159 151 } // for 160 avgstd( TRIALS / 5,buckets );152 avgstd( buckets ); 161 153 free( buckets ); 162 154 } 163 ENDTIME( " x 5" );155 ENDTIME( " x 10 " ); 164 156 165 157 sout | nl | "Concurrent"; … … 171 163 } // wait for threads to complete 172 164 } 173 ENDTIME( " x 50 " );165 ENDTIME( " x 100 " ); 174 166 #endif // 0 175 167 #endif // TIME 176 177 sout | nl | "CFA " xstr(PRNG_NAME);178 179 168 #if 1 180 169 PRNG prng; … … 195 184 STARTTIME; 196 185 { 197 size_t * buckets = calloc( BUCKETS );// too big for task stack186 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 198 187 for ( TRIALS ) { 199 188 buckets[prng( prng ) % BUCKETS] += 1; // sequential 200 189 } // for 201 avgstd( TRIALS,buckets );190 avgstd( buckets ); 202 191 free( buckets ); 203 192 } … … 230 219 STARTTIME; 231 220 { 232 size_t * buckets = calloc( BUCKETS );// too big for task stack233 for ( TRIALS / 5) {221 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 222 for ( TRIALS ) { 234 223 buckets[prng() % BUCKETS] += 1; 235 224 } // for 236 avgstd( TRIALS / 5,buckets );225 avgstd( buckets ); 237 226 free( buckets ); 238 227 } 239 ENDTIME( " x 5 ");228 ENDTIME(); 240 229 241 230 sout | nl | "Concurrent"; … … 247 236 } // wait for threads to complete 248 237 } 249 ENDTIME( " x 5 ");238 ENDTIME(); 250 239 #endif // 0 251 240 #if 1 -
tests/attributes.cfa
rb110bcc r2ed94a9 10 10 // Created On : Mon Feb 6 16:07:02 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 23 20:33:07 202313 // Update Count : 3 912 // Last Modified On : Mon Mar 15 13:53:31 2021 13 // Update Count : 38 14 14 // 15 15 … … 22 22 23 23 // aggregate_name 24 st atic struct __attribute__(( unused )) {} Dummy;24 struct __attribute__(( unused )) {} Dummy; 25 25 struct __attribute__(( unused )) Agn1; 26 26 struct __attribute__(( unused )) Agn2 {}; -
tests/avltree/avl.h
rb110bcc r2ed94a9 9 9 // #include <lib.h> 10 10 11 forall(T) 12 trait Comparable { 11 trait Comparable(T) { 13 12 int ?<?(T, T); 14 13 }; -
tests/concurrent/actors/.expect/types.txt
rb110bcc r2ed94a9 12 12 -1 13 13 5 14 nested inheritance actor test15 -116 517 14 end -
tests/concurrent/actors/dynamic.cfa
rb110bcc r2ed94a9 7 7 int Times = 1000000; // default values 8 8 9 struct derived_actor { inline actor; }; 9 struct derived_actor { 10 inline actor; 11 }; 12 void ?{}( derived_actor & this ) { ((actor &)this){}; } 13 10 14 struct derived_msg { 11 15 inline message; … … 19 23 void ?{}( derived_msg & this ) { ((derived_msg &)this){ 0 }; } 20 24 25 21 26 Allocation receive( derived_actor & receiver, derived_msg & msg ) { 22 27 if ( msg.cnt >= Times ) { … … 28 33 derived_actor * d_actor = alloc(); 29 34 (*d_actor){}; 30 *d_actor <<*d_msg;35 *d_actor | *d_msg; 31 36 return Delete; 32 37 } … … 58 63 derived_actor * d_actor = alloc(); 59 64 (*d_actor){}; 60 *d_actor <<*d_msg;65 *d_actor | *d_msg; 61 66 62 67 printf("stopping\n"); -
tests/concurrent/actors/executor.cfa
rb110bcc r2ed94a9 15 15 }; 16 16 void ?{}( d_actor & this ) with(this) { 17 ((actor &)this){}; 17 18 id = ids++; 18 19 gstart = (&this + (id / Set * Set - id)); // remember group-start array-element … … 23 24 24 25 struct d_msg { inline message; } shared_msg; 26 void ?{}( d_msg & this ) { ((message &) this){ Nodelete }; } 25 27 26 28 Allocation receive( d_actor & this, d_msg & msg ) with( this ) { … … 28 30 if ( recs % Batch == 0 ) { 29 31 for ( i; Batch ) { 30 gstart[sends % Set] <<shared_msg;32 gstart[sends % Set] | shared_msg; 31 33 sends += 1; 32 34 } … … 83 85 } // switch 84 86 87 85 88 executor e{ Processors, Processors, Processors == 1 ? 1 : Processors * 512, true }; 86 89 … … 94 97 95 98 for ( i; Actors ) { 96 actors[i] <<shared_msg;99 actors[i] | shared_msg; 97 100 } // for 98 101 -
tests/concurrent/actors/matrix.cfa
rb110bcc r2ed94a9 7 7 unsigned int xr = 500, xc = 500, yc = 500, Processors = 1; // default values 8 8 9 struct derived_actor { inline actor; }; 9 struct derived_actor { 10 inline actor; 11 }; 12 void ?{}( derived_actor & this ) { ((actor &)this){}; } 10 13 11 14 struct derived_msg { … … 18 21 void ?{}( derived_msg & this ) {} 19 22 void ?{}( derived_msg & this, int * Z, int * X, int ** Y ) { 20 ((message &) this){ Nodelete};23 ((message &) this){ Finished }; 21 24 this.Z = Z; 22 25 this.X = X; … … 105 108 106 109 for ( unsigned int r = 0; r < xr; r += 1 ) { 107 actors[r] <<messages[r];110 actors[r] | messages[r]; 108 111 } // for 109 112 -
tests/concurrent/actors/pingpong.cfa
rb110bcc r2ed94a9 6 6 #include <actor.hfa> 7 7 8 struct ping { inline actor; }; 9 struct pong { inline actor; }; 8 struct ping { 9 inline actor; 10 }; 11 static inline void ?{}( ping & this ) { ((actor &)this){}; } 12 13 struct pong { 14 inline actor; 15 }; 16 static inline void ?{}( pong & this ) { ((actor &)this){}; } 10 17 11 18 struct p_msg { … … 25 32 Allocation retval = Nodelete; 26 33 if ( msg.count == times ) retval = Finished; 27 *po <<msg;34 *po | msg; 28 35 return retval; 29 36 } … … 35 42 Allocation retval = Nodelete; 36 43 if ( msg.count == times ) retval = Finished; 37 *pi <<msg;44 *pi | msg; 38 45 return retval; 39 46 } … … 53 60 pi = &pi_actor; 54 61 p_msg m; 55 pi_actor <<m;62 pi_actor | m; 56 63 stop_actor_system(); 57 64 -
tests/concurrent/actors/static.cfa
rb110bcc r2ed94a9 7 7 int Times = 1000000; // default values 8 8 9 struct derived_actor { inline actor; }; 9 struct derived_actor { 10 inline actor; 11 }; 12 void ?{}( derived_actor & this ) { ((actor &)this){}; } 13 10 14 struct derived_msg { 11 15 inline message; … … 19 23 void ?{}( derived_msg & this ) { ((derived_msg &)this){ 0 }; } 20 24 25 21 26 Allocation receive( derived_actor & receiver, derived_msg & msg ) { 22 27 if ( msg.cnt >= Times ) { … … 25 30 } 26 31 msg.cnt++; 27 receiver <<msg;32 receiver | msg; 28 33 return Nodelete; 29 34 } … … 55 60 derived_actor actor; 56 61 57 actor <<msg;62 actor | msg; 58 63 59 64 printf("stopping\n"); -
tests/concurrent/actors/types.cfa
rb110bcc r2ed94a9 18 18 int num; 19 19 }; 20 static inline void ?{}( d_msg & this ) { ((message &)this){}; } 20 21 21 22 // this isn't a valid receive routine since int is not a message type … … 35 36 inline actor; 36 37 }; 38 static inline void ?{}( derived_actor2 & this ) { ((actor &)this){}; } 37 39 38 40 Allocation receive( derived_actor2 & receiver, d_msg & msg ) { … … 41 43 } 42 44 43 struct derived_actor3 { inline actor; }; 44 struct derived_actor4 { inline derived_actor3; }; 45 struct derived_actor3 { 46 inline actor; 47 }; 48 static inline void ?{}( derived_actor3 & this ) { ((actor &)this){}; } 49 45 50 struct d_msg2 { 46 51 inline message; 47 52 int num; 48 53 }; 54 static inline void ?{}( d_msg2 & this ) { ((message &)this){}; } 49 55 50 56 Allocation receive( derived_actor3 & receiver, d_msg & msg ) { … … 72 78 b.num = 1; 73 79 c.num = 2; 74 a << b <<c;80 a | b | c; 75 81 stop_actor_system(); 76 82 … … 80 86 d_msg d_ac2_msg; 81 87 d_ac2_msg.num = 3; 82 d_ac2_0 <<d_ac2_msg;83 d_ac2_1 <<d_ac2_msg;88 d_ac2_0 | d_ac2_msg; 89 d_ac2_1 | d_ac2_msg; 84 90 stop_actor_system(); 85 91 … … 93 99 d_msg d_ac23_msg; 94 100 d_ac23_msg.num = 4; 95 d_ac3_0 <<d_ac23_msg;96 d_ac2_2 <<d_ac23_msg;101 d_ac3_0 | d_ac23_msg; 102 d_ac2_2 | d_ac23_msg; 97 103 stop_actor_system(); 98 104 } // RAII to clean up executor … … 107 113 b1.num = -1; 108 114 c2.num = 5; 109 a3 << b1 << c2; 110 stop_actor_system(); 111 } // RAII to clean up executor 112 113 { 114 printf("nested inheritance actor test\n"); 115 executor e{ 1, Processors, Processors == 1 ? 1 : Processors * 4, true }; 116 start_actor_system( Processors ); 117 derived_actor4 a4; 118 d_msg b1; 119 d_msg2 c2; 120 b1.num = -1; 121 c2.num = 5; 122 a4 << b1 << c2; 115 a3 | b1 | c2; 123 116 stop_actor_system(); 124 117 } // RAII to clean up executor -
tests/concurrent/channels/parallel_harness.hfa
rb110bcc r2ed94a9 100 100 101 101 int test( size_t Processors, size_t Channels, size_t Producers, size_t Consumers, size_t ChannelSize ) { 102 size_t Clusters = Processors;102 size_t Clusters = 1; 103 103 // create a cluster 104 104 cluster clus[Clusters]; … … 108 108 } 109 109 110 channels = a alloc( Channels );110 channels = anew( Channels ); 111 111 112 112 // sout | "Processors: " | Processors | " ProdsPerChan: " | Producers | " ConsPerChan: " | Consumers | "Channels: " | Channels | " Channel Size: " | ChannelSize; … … 139 139 while( cons_done_count != Consumers * Channels ) { 140 140 for ( i; Channels ) { 141 if ( has_wait ers( channels[i] ) ){141 if ( has_waiting_consumers( channels[i] ) ){ 142 142 #ifdef BIG 143 143 bigObject b{0}; … … 150 150 151 151 } 152 152 // for ( i; Channels ) { 153 // // sout | get_count( channels[i] ); 154 // if ( get_count( channels[i] ) < Consumers ){ 155 // #ifdef BIG 156 // bigObject b{0}; 157 // #endif 158 // for ( j; Consumers ) { 159 // #ifdef BIG 160 // insert( channels[i], b ); 161 // #else 162 // insert( channels[i], 0 ); 163 // #endif 164 // } 165 // } 166 // } 153 167 sout | "cons"; 154 168 for ( i; Consumers * Channels ) { -
tests/concurrent/pthread/.expect/bounded_buffer.x64.txt
rb110bcc r2ed94a9 1 producer total value is 397802 consumer total value is 397801 producer total value is 44280 2 consumer total value is 44280 -
tests/concurrent/pthread/.expect/bounded_buffer.x86.txt
rb110bcc r2ed94a9 1 producer total value is 17702 consumer total value is 17701 producer total value is 45060 2 consumer total value is 45060 -
tests/concurrent/signal/disjoint.cfa
rb110bcc r2ed94a9 38 38 39 39 // Use a global struct because the order needs to match with Signaller thread 40 st atic struct {40 struct { 41 41 global_t mut; 42 42 global_data_t data; -
tests/concurrent/waitfor/parse.cfa
rb110bcc r2ed94a9 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo1 //---------------------------------------------------------------------------------------- 2 //---------------------------------------------------------------------------------------- 3 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // waitfor.c -- 8 // 9 // Author : Peter A. Buhr 10 // Created On : Wed Aug 30 17:53:29 2017 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 22:52:18 2023 13 // Update Count : 64 14 // 4 // DEPRECATED TEST 5 // DIFFERS BETWEEN DEBUG AND RELEASE 6 // 7 //---------------------------------------------------------------------------------------- 8 //---------------------------------------------------------------------------------------- 15 9 16 10 #include <monitor.hfa> … … 18 12 monitor M {}; 19 13 20 void notcalled( M & mutex m1, M & mutex m2 ) { 21 abort(); 22 } 23 void or( M & mutex m ) { 24 abort(); 25 } 26 void timeout( M & mutex m ) { 27 abort(); 14 M a; 15 16 void f1( M & mutex a ); 17 void f2( M & mutex a ); 18 void f2( M & mutex a, M & mutex b ); 19 void f3( M & mutex a ); 20 void f3( M & mutex a, M & mutex b ); 21 void f3( M & mutex a, M & mutex b, M & mutex c ); 22 23 void foo() { 24 25 //--------------------------------------- 26 waitfor( f1 : a ) { 27 1; 28 } 29 30 //--------------------------------------- 31 waitfor( f1 : a ) { 32 2; 33 } 34 waitfor( f2 : a ) { 35 3; 36 } 37 38 //--------------------------------------- 39 when( 1 < 3 ) waitfor( f2 : a, a ) { 40 4; 41 } 42 or timeout( 100 ) { 43 5; 44 } 45 46 //--------------------------------------- 47 when( 2 < 3 ) waitfor( f3 : a ) { 48 5; 49 } 50 or else { 51 6; 52 } 53 54 //--------------------------------------- 55 when( 3 < 3 ) waitfor( f3 : a, a ) { 56 7; 57 } 58 or when( 4 < 3 ) timeout( 101 ) { 59 8; 60 } 61 or when( 5 < 3 ) else { 62 9; 63 } 64 65 //--------------------------------------- 66 when( 6 < 3 ) waitfor( f3 : a, a, a ) { 67 10; 68 } 69 or when( 7 < 3 ) waitfor( f1 : a ) { 70 11; 71 } 72 or else { 73 12; 74 } 75 76 //--------------------------------------- 77 when( 8 < 3 ) waitfor( f3 : a, a ) { 78 13; 79 } 80 or waitfor( f1 : a ) { 81 14; 82 } 83 or when( 9 < 3 ) timeout( 102 ) { 84 15; 85 } 86 87 //--------------------------------------- 88 when( 10 < 3 ) waitfor( f1 : a ) { 89 16; 90 } 91 or waitfor( f2 : a, a ) { 92 17; 93 } 94 or timeout( 103 ) { 95 18; 96 } 97 or when( 11 < 3 ) else { 98 19; 99 } 28 100 } 29 101 30 void fred( M & mutex m, M & mutex or, M & mutex timeout ) { 31 // test waitfor and when 32 33 waitfor( notcalled : m, m ); 34 35 waitfor( notcalled : m, m ) { 36 } 37 38 waitfor( notcalled : m, m ) { 39 } 40 41 when( true ) waitfor( notcalled : m, m ); 42 43 when( true ) waitfor( notcalled : m, m ) { 44 } 45 46 waitfor( notcalled : m, m ); 47 or waitfor( notcalled : m, m ); 48 49 when( true ) waitfor( notcalled : m, m ); 50 or when( true ) waitfor( notcalled : m, m ); 51 52 waitfor( notcalled : m, m ) { 53 } or waitfor( notcalled : m, m ) { 54 } 55 56 waitfor( notcalled : m, m ) { 57 } or waitfor( notcalled : m, m ) { 58 } 59 60 when( true ) waitfor( notcalled : m, m ) { 61 } or when( true ) waitfor( notcalled : m, m ) { 62 } 63 64 waitfor( notcalled : m, m ); 65 or waitfor( notcalled : m, m ) { 66 } 67 68 when( true ) waitfor( notcalled : m, m ); 69 or when( true ) waitfor( notcalled : m, m ) { 70 } 71 72 waitfor( notcalled : m, m ) { 73 } or waitfor( notcalled : m, m ); 74 75 when( true ) waitfor( notcalled : m, m ) { 76 } or when( true ) waitfor( notcalled : m, m ); 77 78 // test when, waitfor and else 79 80 waitfor( notcalled : m, m ); 81 or else; 82 83 when( true ) waitfor( notcalled : m, m ); 84 or else; 85 86 when( true ) waitfor( notcalled : m, m ); 87 or else; 88 89 waitfor( notcalled : m, m ) { 90 } or else { 91 } 92 93 when( true ) waitfor( notcalled : m, m ) { 94 } or else { 95 } 96 97 waitfor( notcalled : m, m ); 98 or else { 99 } 100 101 when( true ) waitfor( notcalled : m, m ); 102 or else { 103 } 104 105 when( true ) waitfor( notcalled : m, m ); 106 or else { 107 } 108 109 waitfor( notcalled : m, m ) { 110 } or else; 111 112 when( true ) waitfor( notcalled : m, m ) { 113 } or else; 114 115 waitfor( notcalled : m, m ); 116 or when( true ) else; 117 118 when( true ) waitfor( notcalled : m, m ); 119 or when( true ) else; 120 121 when( true ) waitfor( notcalled : m, m ); 122 or when( true ) else; 123 124 waitfor( notcalled : m, m ) { 125 } or when( true ) else { 126 } 127 128 when( true ) waitfor( notcalled : m, m ) { 129 } or when( true ) else { 130 } 131 132 waitfor( notcalled : m, m ); 133 or when( true ) else { 134 } 135 136 when( true ) waitfor( notcalled : m, m ); 137 or when( true ) else { 138 } 139 140 when( true ) waitfor( notcalled : m, m ); 141 or when( true ) else { 142 } 143 144 waitfor( notcalled : m, m ) { 145 } or when( true ) else; 146 147 when( true ) waitfor( notcalled : m, m ) { 148 } or when( true ) else; 149 150 // test when, waitfor and timeout 151 152 waitfor( notcalled : m, m ); 153 or timeout( 3 ); 154 155 waitfor( notcalled : m, m ); 156 or timeout( 3 ); 157 158 when( true ) waitfor( notcalled : m, m ); 159 or timeout( 3 ); 160 161 waitfor( notcalled : m, m ) { 162 } or timeout( 3 ) { 163 } 164 165 when( true ) waitfor( notcalled : m, m ) { 166 } or timeout( 3 ) { 167 } 168 169 when( true ) waitfor( notcalled : m, m ) { 170 } or timeout( 3 ) { 171 } 172 173 when( true ) waitfor( notcalled : m, m ) { 174 } or when ( true ) timeout( 3 ) { 175 } 176 177 when( true ) waitfor( notcalled : m, m ) { 178 } or when ( true ) timeout( 3 ) { 179 } 180 181 waitfor( notcalled : m, m ); 182 or timeout( 3 ) { 183 } 184 185 when( true ) waitfor( notcalled : m, m ); 186 or timeout( 3 ) { 187 } 188 189 when( true ) waitfor( notcalled : m, m ); 190 or when( true ) timeout( 3 ) { 191 } 192 193 waitfor( notcalled : m, m ) { 194 } or timeout( 3 ); 195 196 when( true ) waitfor( notcalled : m, m ) { 197 } or timeout( 3 ); 198 199 when( true ) waitfor( notcalled : m, m ) { 200 } or when( true ) timeout( 3 ); 201 202 // test when, waitfor, timeout and else 203 204 waitfor( notcalled : m, m ) { 205 } or timeout( 3 ) { 206 } or when( true ) else {} 207 208 when( true ) waitfor( notcalled : m, m ) { 209 } or timeout( 3 ) { 210 } or when( true ) else {} 211 212 waitfor( notcalled : m, m ) { 213 } or timeout( 3 ) { 214 } or when( true ) else {} 215 216 waitfor( notcalled : m, m ) { 217 } or when( true ) timeout( 3 ) { 218 } or when( true ) else {} 219 220 when( true ) waitfor( notcalled : m, m ) { 221 } or timeout( 3 ) { 222 } or when( true ) else {} 223 224 waitfor( notcalled : m, m ) { 225 } or when( true ) timeout( 3 ) { 226 } or when( true ) else {} 227 228 when( true ) waitfor( notcalled : m, m ) { 229 } or when( true ) timeout( 3 ) { 230 } or when( true ) else {} 231 232 // test quasi-keywords "or" and "timeout" 233 234 int or = 0, timeout = 0; 235 waitfor( timeout : timeout ) timeout += 1; or timeout( timeout ); 236 waitfor( notcalled : or, or ) or += 1; or timeout( or ) 3; 237 when( or ) waitfor( or : m ) { 4; } or timeout( or ) or += 1; 238 when( timeout ) waitfor( notcalled : timeout, timeout ) or += 1; or else timeout += 1; 239 when( or + timeout ) waitfor( or : m ) 4; or when( or ) timeout( or ) 4; or when( or ) else timeout += 1; 240 when( 3 ) waitfor( or : or ) 3; or when( or ) waitfor( notcalled : or, or ) 4; or else 4; 241 when( timeout ) waitfor( or : timeout ) 3; or waitfor( notcalled : timeout, or ) 4; or when( or ) timeout( timeout ) 4; 242 when( 3 ) waitfor( or : timeout ) or += 1; 243 or waitfor( or : or ) timeout += 1; 244 or timeout( timeout ) or += 1; 245 or when( 3 ) else or += 1; 246 247 // test else selection 248 249 if ( or > timeout ) waitfor( or : or ) 3; 250 else waitfor( timeout : timeout ) 4; 251 } 252 253 //Dummy main 254 int main( int argc, char const * argv[] ) { 255 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 256 } 257 258 // Local Variables: // 259 // tab-width: 4 // 260 // compile-command: "cfa waitfor.cfa" // 261 // End: // 102 int main() {} -
tests/declarationSpecifier.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed Aug 17 08:21:04 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Feb 23 20:53:31 202313 // Update Count : 812 // Last Modified On : Tue Apr 30 18:20:36 2019 13 // Update Count : 4 14 14 // 15 15 … … 25 25 short int volatile static const x8; 26 26 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; 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; 34 35 35 36 const Int volatile x20; … … 42 43 Int volatile static const x27; 43 44 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; 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; 51 53 52 54 _Thread_local int x37; -
tests/errors/.expect/declaration.txt
rb110bcc r2ed94a9 1 errors/declaration.cfa:16:1 error: duplicate static storage class(es)in declaration of x1: static const volatile short int1 errors/declaration.cfa:16:1 error: duplicate static in declaration of x1: static const volatile short int 2 2 3 errors/declaration.cfa:17:1 error: conflicting extern & static storage classesin declaration of x2: extern const volatile short int3 errors/declaration.cfa:17:1 error: conflicting extern & static in declaration of x2: extern const volatile short int 4 4 5 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 int5 errors/declaration.cfa:18:1 error: conflicting extern & auto, conflicting extern & static, conflicting extern & static, duplicate extern in declaration of x3: extern const volatile short int 6 6 7 errors/declaration.cfa:19:1 error: duplicate static storage class(es)in declaration of x4: static const volatile instance of const volatile struct __anonymous07 errors/declaration.cfa:19:1 error: duplicate static 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 qualifier(s), duplicate static storage class(es), duplicate volatile qualifier(s)in declaration of x5: static const volatile instance of const volatile struct __anonymous113 errors/declaration.cfa:20:1 error: duplicate const, duplicate static, duplicate volatile 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 storage class(es)in declaration of x6: static const volatile Int19 errors/declaration.cfa:22:1 error: duplicate static in declaration of x6: static const volatile Int 20 20 21 errors/declaration.cfa:24:1 error: duplicate const qualifier(s)in declaration of f01: static inline function21 errors/declaration.cfa:24:1 error: duplicate const 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 qualifier(s)in declaration of f02: static inline function26 errors/declaration.cfa:25:1 error: duplicate volatile 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 qualifier(s)in declaration of f03: static inline function31 errors/declaration.cfa:26:1 error: duplicate const 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 qualifier(s)in declaration of f04: static inline function36 errors/declaration.cfa:27:1 error: duplicate volatile 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 qualifier(s)in declaration of f05: static inline function41 errors/declaration.cfa:28:1 error: duplicate const 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 qualifier(s)in declaration of f06: static inline function46 errors/declaration.cfa:29:1 error: duplicate volatile 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 qualifier(s)in declaration of f07: static inline function51 errors/declaration.cfa:30:1 error: duplicate const 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 volatile qualifier(s)in declaration of f08: static inline function56 errors/declaration.cfa:31:1 error: duplicate const, duplicate volatile 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 volatile qualifier(s)in declaration of f09: static inline function61 errors/declaration.cfa:33:1 error: duplicate const, duplicate volatile 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 qualifier(s), duplicate _Atomic qualifier(s), duplicate _Atomic qualifier(s), duplicate const restrict volatile qualifier(s)in declaration of f09: static inline function66 errors/declaration.cfa:34:1 error: duplicate const, duplicate _Atomic, duplicate _Atomic, duplicate const, duplicate restrict, duplicate volatile in declaration of f09: static inline function 67 67 with no parameters 68 68 returning const restrict volatile _Atomic int -
tests/forall.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed May 9 08:48:15 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 23 20:29:59202313 // Update Count : 9 112 // Last Modified On : Sun Feb 5 07:54:43 2023 13 // Update Count : 90 14 14 // 15 15 … … 195 195 196 196 forall( T ) struct S { T t; } (int) x, y, z; 197 staticforall( T ) struct { T t; } (int) a, b, c;197 forall( T ) struct { T t; } (int) a, b, c; 198 198 199 199 forall( T ) static forall( S ) { -
tests/function-operator.cfa
rb110bcc r2ed94a9 10 10 // Created On : Fri Aug 25 15:21:11 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 25 07:26:10 202313 // Update Count : 1 212 // Last Modified On : Thu Apr 11 18:27:45 2019 13 // Update Count : 10 14 14 // 15 15 … … 22 22 23 23 // STL-like Algorithms 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 &); }; 24 trait Assignable(T &, U &) { T ?=?(T &, U); }; 25 trait Copyable(T &) { void ?{}(T &, T); }; 26 trait Destructable(T &) { void ^?{}(T &); }; 30 27 31 28 trait Iterator(iter & | sized(iter) | Copyable(iter) | Destructable(iter), T) { -
tests/include/includes.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 22 10:16:58 202313 // Update Count : 81112 // Last Modified On : Sun May 22 08:27:20 2022 13 // Update Count : 779 14 14 // 15 15 … … 72 72 #include <gshadow.h> 73 73 #include <iconv.h> 74 //#include <ifaddrs.h> // causes warning messages that break the build 74 #include <ifaddrs.h> 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( ) {172 int main( int argc, char const * argv[] ) { 173 173 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 174 174 } -
tests/io/comp_basic.cfa
rb110bcc r2ed94a9 26 26 #include <unistd.h> 27 27 28 st atic struct {28 struct { 29 29 barrier & bar; 30 30 int pipe[2]; 31 31 32 } globals; 32 33 -
tests/io/comp_fair.cfa
rb110bcc r2ed94a9 26 26 #include <unistd.h> 27 27 28 st atic struct {28 struct { 29 29 barrier & bar; 30 30 int pipe[2]; 31 31 32 } globals; 32 33 -
tests/linking/mangling/header.hfa
rb110bcc r2ed94a9 8 8 extern name_but_a_typedefed_t a_typedefed_global; 9 9 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 } 10 extern struct /* anonymous */ { 11 int some_int; 12 int some_other_int; 13 } a_global_with_no_type; -
tests/linking/mangling/lib.cfa
rb110bcc r2ed94a9 3 3 name_but_a_typedefed_t a_typedefed_global; 4 4 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 } 5 struct { 6 int some_int; 7 int some_other_int; 8 } a_global_with_no_type; -
tests/linking/mangling/main.cfa
rb110bcc r2ed94a9 1 1 #include <fstream.hfa> 2 2 3 st atic struct { int a; } test; // purposefully before the include to force anonymous name numbering3 struct { int a; } test; //purposefully before the include 4 4 5 5 #include "header.hfa" … … 13 13 14 14 sout | "Done!"; 15 16 return 0; 15 17 } -
tests/pybin/settings.py
rb110bcc r2ed94a9 126 126 global archive 127 127 global install 128 global invariant129 128 130 129 global continue_ … … 141 140 all_install = [Install(o) for o in list(dict.fromkeys(options.install))] 142 141 archive = os.path.abspath(os.path.join(original_path, options.archive_errors)) if options.archive_errors else None 143 invariant = options.invariant144 142 continue_ = options.continue_ 145 143 dry_run = options.dry_run # must be called before tools.config_hash() -
tests/quotedKeyword.cfa
rb110bcc r2ed94a9 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 23 20:31:05 202313 // Update Count : 2 612 // Last Modified On : Fri Feb 7 19:07:07 2020 13 // Update Count : 25 14 14 // 15 15 16 16 #include <fstream.hfa> 17 17 18 st atic struct {18 struct { 19 19 int ``otype; 20 20 int ``struct; -
tests/sum.cfa
rb110bcc r2ed94a9 11 11 // Created On : Wed May 27 17:56:53 2015 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Fri Feb 24 22:52:12 202314 // Update Count : 34 713 // Last Modified On : Thu Aug 5 21:27:25 2021 14 // Update Count : 346 15 15 // 16 16 … … 18 18 #include <stdlib.hfa> 19 19 20 forall( T ) 21 trait sumable { 20 trait sumable( T ) { 22 21 void ?{}( T &, zero_t ); // 0 literal constructor 23 22 void ?{}( T &, one_t ); // 1 literal constructor -
tests/test.py
rb110bcc r2ed94a9 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')117 116 parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180) 118 117 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) … … 173 172 test.prepare() 174 173 175 # extra flags for cfa to pass through make.176 cfa_flags = 'CFAFLAGS=--invariant' if settings.invariant else None177 178 174 # ---------- 179 175 # MAKE … … 181 177 # build, skipping to next test on error 182 178 with Timed() as comp_dur: 183 make_ret, _, _ = make( test.target(), flags=cfa_flags, output_file=subprocess.DEVNULL, error=out_file, error_file=err_file)179 make_ret, _, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file ) 184 180 185 181 # ----------
Note:
See TracChangeset
for help on using the changeset viewer.