aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyril SIX <cyril.six@kalray.eu>2020-04-10 12:05:55 +0200
committerCyril SIX <cyril.six@kalray.eu>2020-04-10 12:05:55 +0200
commit7505104944ce67229ac522665bc83c6cab5d113d (patch)
tree2cde0e43c20c7452418bc7ea028fb30d3bc718c9
parentd760be4554fa65f8fcfa9232f3d9ff7f9183f452 (diff)
parent6e7c693e6cfe683b7a44c4f2a3420678fcdcc36f (diff)
downloadcompcert-kvx-7505104944ce67229ac522665bc83c6cab5d113d.tar.gz
compcert-kvx-7505104944ce67229ac522665bc83c6cab5d113d.zip
[BROKEN] Merge branch 'mppa-work' into mppa-RTLpathSE
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore2
-rw-r--r--.gitlab-ci.yml240
-rw-r--r--Changelog38
-rw-r--r--Makefile6
-rw-r--r--Makefile.extr7
-rw-r--r--Makefile.menhir6
-rw-r--r--VERSION2
-rw-r--r--aarch64/Asmexpand.ml23
-rw-r--r--aarch64/Asmgen.v49
-rw-r--r--aarch64/Asmgenproof.v163
-rw-r--r--aarch64/Asmgenproof1.v704
-rw-r--r--aarch64/Builtins1.v2
-rw-r--r--aarch64/CSE2deps.v20
-rw-r--r--aarch64/CSE2depsproof.v128
-rw-r--r--aarch64/Conventions1.v137
-rw-r--r--aarch64/DuplicateOpcodeHeuristic.ml27
-rw-r--r--aarch64/Op.v70
-rw-r--r--aarch64/extractionMachdep.v1
-rw-r--r--arm/Asmgen.v16
-rw-r--r--arm/Asmgenproof.v7
-rw-r--r--arm/Asmgenproof1.v32
-rw-r--r--arm/Builtins1.v2
-rw-r--r--arm/CSE2deps.v20
-rw-r--r--arm/CSE2depsproof.v129
-rw-r--r--arm/Conventions1.v238
-rw-r--r--arm/DuplicateOpcodeHeuristic.ml22
-rw-r--r--arm/Op.v66
-rw-r--r--backend/Allnontrap.v26
-rw-r--r--backend/Allnontrapproof.v215
-rw-r--r--backend/Allocation.v32
-rw-r--r--backend/Allocproof.v136
-rw-r--r--backend/Asmexpandaux.ml2
-rw-r--r--backend/Bounds.v6
-rw-r--r--backend/CSE.v16
-rw-r--r--backend/CSE2.v518
-rw-r--r--backend/CSE2proof.v1715
-rw-r--r--backend/CSEdomain.v13
-rw-r--r--backend/CSEproof.v170
-rw-r--r--backend/CleanupLabelsproof.v12
-rw-r--r--backend/Cminor.v20
-rw-r--r--backend/Cminortyping.v45
-rw-r--r--backend/Constprop.v10
-rw-r--r--backend/Constpropproof.v59
-rw-r--r--backend/Conventions.v67
-rw-r--r--backend/Deadcode.v8
-rw-r--r--backend/Deadcodeproof.v77
-rw-r--r--backend/Debugvar.v2
-rw-r--r--backend/Debugvarproof.v16
-rw-r--r--backend/Duplicate.v43
-rw-r--r--backend/Duplicateaux.ml627
-rw-r--r--backend/Duplicateproof.v68
-rw-r--r--backend/ForwardMoves.v333
-rw-r--r--backend/ForwardMovesproof.v801
-rw-r--r--backend/IRC.ml1
-rw-r--r--backend/Inlining.v8
-rw-r--r--backend/Inliningaux.ml13
-rw-r--r--backend/Inliningproof.v54
-rw-r--r--backend/Inliningspec.v12
-rw-r--r--backend/LTL.v27
-rw-r--r--backend/Linear.v23
-rw-r--r--backend/Linearize.v6
-rw-r--r--backend/Linearizeaux.ml409
-rw-r--r--backend/Linearizeproof.v48
-rw-r--r--backend/Lineartyping.v19
-rw-r--r--backend/Liveness.v4
-rw-r--r--backend/Mach.v19
-rw-r--r--backend/OpHelpers.v20
-rw-r--r--backend/PrintAsmaux.ml6
-rw-r--r--backend/PrintCminor.ml6
-rw-r--r--backend/PrintLTL.ml12
-rw-r--r--backend/PrintLTLin.ml115
-rw-r--r--backend/PrintMach.ml5
-rw-r--r--backend/PrintRTL.ml12
-rw-r--r--backend/PrintXTL.ml9
-rw-r--r--backend/RTL.v55
-rw-r--r--backend/RTLgen.v20
-rw-r--r--backend/RTLgenspec.v18
-rw-r--r--backend/RTLtyping.v67
-rw-r--r--backend/Regalloc.ml46
-rw-r--r--backend/Renumber.v4
-rw-r--r--backend/Renumberproof.v12
-rw-r--r--backend/Splitting.ml8
-rw-r--r--backend/Stacking.v4
-rw-r--r--backend/Stackingproof.v40
-rw-r--r--backend/Tailcall.v2
-rw-r--r--backend/Tailcallproof.v47
-rw-r--r--backend/Tunneling.v4
-rw-r--r--backend/Tunnelingproof.v25
-rw-r--r--backend/Unusedglob.v4
-rw-r--r--backend/Unusedglobproof.v32
-rw-r--r--backend/ValueAnalysis.v38
-rw-r--r--backend/ValueDomain.v5
-rw-r--r--backend/XTL.ml10
-rw-r--r--backend/XTL.mli4
-rw-r--r--cfrontend/C2C.ml27
-rw-r--r--cfrontend/Cexec.v73
-rw-r--r--cfrontend/Cop.v4
-rw-r--r--cfrontend/Csem.v2
-rw-r--r--cfrontend/Cshmgen.v39
-rw-r--r--cfrontend/Cshmgenproof.v133
-rw-r--r--cfrontend/Csyntax.v2
-rw-r--r--cfrontend/Ctypes.v19
-rw-r--r--cfrontend/Ctyping.v87
-rw-r--r--cfrontend/PrintCsyntax.ml4
-rw-r--r--common/AST.v89
-rw-r--r--common/Builtins.v2
-rw-r--r--common/Builtins0.v64
-rw-r--r--common/Events.v131
-rw-r--r--common/Memdata.v31
-rw-r--r--common/Memory.v155
-rw-r--r--common/Memtype.v5
-rw-r--r--common/PrintAST.ml12
-rw-r--r--common/Sections.ml29
-rw-r--r--common/Sections.mli4
-rw-r--r--common/Values.v139
-rwxr-xr-xconfig_aarch64.sh1
-rwxr-xr-xconfig_arm.sh1
-rwxr-xr-xconfig_armhf.sh1
-rwxr-xr-xconfig_ia32.sh1
-rwxr-xr-xconfig_k1c.sh1
-rwxr-xr-xconfig_ppc.sh1
-rwxr-xr-xconfig_ppc64.sh1
-rwxr-xr-xconfig_rv32.sh1
-rwxr-xr-xconfig_rv64.sh1
-rwxr-xr-xconfig_simple.sh11
-rwxr-xr-xconfig_x86_64.sh1
-rwxr-xr-xconfigure31
-rwxr-xr-xcoq2
-rw-r--r--cparser/Ceval.ml2
-rw-r--r--cparser/Cutil.ml6
-rw-r--r--cparser/Cutil.mli2
-rw-r--r--cparser/Diagnostics.ml160
-rw-r--r--cparser/Elab.ml54
-rw-r--r--cparser/Lexer.mll2
-rw-r--r--debug/DwarfPrinter.ml45
-rw-r--r--debug/DwarfPrinter.mli2
-rw-r--r--debug/DwarfTypes.mli25
-rw-r--r--debug/Dwarfgen.ml16
-rw-r--r--doc/index.html4
-rw-r--r--driver/Clflags.ml9
-rw-r--r--driver/Compiler.v48
-rw-r--r--driver/Compopts.v12
-rw-r--r--driver/Driver.ml25
-rw-r--r--driver/Interp.ml4
-rw-r--r--exportclight/ExportClight.ml20
-rw-r--r--extraction/extraction.v10
-rw-r--r--lib/BoolEqual.v9
-rw-r--r--lib/Integers.v188
-rw-r--r--lib/IntvSets.v2
-rw-r--r--lib/Maps.v161
-rw-r--r--mppa_k1c/Asm.v82
-rw-r--r--mppa_k1c/Asmblock.v44
-rw-r--r--mppa_k1c/Asmblockdeps.v251
-rw-r--r--mppa_k1c/Asmblockgen.v45
-rw-r--r--mppa_k1c/Asmblockgenproof.v88
-rw-r--r--mppa_k1c/Asmblockgenproof1.v357
-rw-r--r--mppa_k1c/Asmblockprops.v343
-rw-r--r--mppa_k1c/Asmexpand.ml36
-rw-r--r--mppa_k1c/Asmvliw.v55
-rw-r--r--mppa_k1c/Builtins1.v12
-rw-r--r--mppa_k1c/CSE2deps.v20
-rw-r--r--mppa_k1c/CSE2depsproof.v127
-rw-r--r--mppa_k1c/Conventions1.v31
-rw-r--r--mppa_k1c/DuplicateOpcodeHeuristic.ml27
-rw-r--r--mppa_k1c/Op.v80
-rw-r--r--mppa_k1c/Peephole.v9
-rw-r--r--mppa_k1c/PostpassScheduling.v2
-rw-r--r--mppa_k1c/PostpassSchedulingOracle.ml146
-rw-r--r--mppa_k1c/PostpassSchedulingproof.v260
-rw-r--r--mppa_k1c/TargetPrinter.ml28
-rw-r--r--mppa_k1c/ValueAOp.v18
-rw-r--r--mppa_k1c/abstractbb/AbstractBasicBlocksDef.v2
-rw-r--r--mppa_k1c/abstractbb/ImpSimuTest.v14
-rw-r--r--mppa_k1c/abstractbb/Impure/ImpHCons.v4
-rw-r--r--mppa_k1c/abstractbb/Parallelizability.v8
-rw-r--r--mppa_k1c/abstractbb/SeqSimuTheory.v11
-rw-r--r--mppa_k1c/lib/Asmblockgenproof0.v (renamed from mppa_k1c/Asmblockgenproof0.v)139
-rw-r--r--mppa_k1c/lib/ForwardSimulationBlock.v6
-rw-r--r--mppa_k1c/lib/Machblock.v17
-rw-r--r--mppa_k1c/lib/Machblockgen.v10
-rw-r--r--mppa_k1c/lib/Machblockgenproof.v24
-rw-r--r--powerpc/Archi.v4
-rw-r--r--powerpc/Asm.v2
-rw-r--r--powerpc/Asmexpand.ml2
-rw-r--r--powerpc/Asmgen.v14
-rw-r--r--powerpc/Asmgenproof.v8
-rw-r--r--powerpc/Asmgenproof1.v9
-rw-r--r--powerpc/Builtins1.v2
-rw-r--r--powerpc/CSE2deps.v20
-rw-r--r--powerpc/CSE2depsproof.v135
-rw-r--r--powerpc/Conventions1.v177
-rw-r--r--powerpc/DuplicateOpcodeHeuristic.ml27
-rw-r--r--powerpc/Op.v66
-rw-r--r--powerpc/extractionMachdep.v3
-rw-r--r--riscV/Asmexpand.ml42
-rw-r--r--riscV/Asmgen.v43
-rw-r--r--riscV/Asmgenproof.v12
-rw-r--r--riscV/Asmgenproof1.v52
-rw-r--r--riscV/Builtins1.v2
-rw-r--r--riscV/CSE2deps.v20
-rw-r--r--riscV/CSE2depsproof.v127
-rw-r--r--riscV/Conventions1.v350
-rw-r--r--riscV/DuplicateOpcodeHeuristic.ml27
-rw-r--r--riscV/Op.v70
-rw-r--r--runtime/arm/i64_stof.S9
-rw-r--r--runtime/include/math.h8
-rw-r--r--runtime/mppa_k1c/vararg.s (renamed from runtime/mppa_k1c/vararg.S)6
-rw-r--r--runtime/powerpc/i64_dtos.s100
-rw-r--r--runtime/powerpc/i64_dtou.s92
-rw-r--r--runtime/powerpc/i64_sar.s60
-rw-r--r--runtime/powerpc/i64_sdiv.s71
-rw-r--r--runtime/powerpc/i64_shl.s64
-rw-r--r--runtime/powerpc/i64_shr.s65
-rw-r--r--runtime/powerpc/i64_smod.s70
-rw-r--r--runtime/powerpc/i64_smulh.s80
-rw-r--r--runtime/powerpc/i64_stod.s67
-rw-r--r--runtime/powerpc/i64_stof.s67
-rw-r--r--runtime/powerpc/i64_udiv.s54
-rw-r--r--runtime/powerpc/i64_udivmod.s234
-rw-r--r--runtime/powerpc/i64_umod.s47
-rw-r--r--runtime/powerpc/i64_umulh.s65
-rw-r--r--runtime/powerpc/i64_utod.s66
-rw-r--r--runtime/powerpc/i64_utof.s64
-rw-r--r--runtime/powerpc/vararg.s163
-rw-r--r--runtime/powerpc64/i64_dtou.s66
-rw-r--r--runtime/powerpc64/i64_stof.s68
-rw-r--r--runtime/powerpc64/i64_utod.s79
-rw-r--r--runtime/powerpc64/i64_utof.s64
-rw-r--r--runtime/powerpc64/vararg.s163
-rw-r--r--test/Makefile4
-rw-r--r--test/c/mandelbrot.c2
-rw-r--r--test/clightgen/issue319.c12
-rw-r--r--test/cse2/globals.c8
-rw-r--r--test/cse2/indexed_addr.c6
-rw-r--r--test/monniaux/README.md135
-rwxr-xr-xtest/monniaux/build_benches.sh5
-rw-r--r--test/monniaux/clock.c4
-rw-r--r--test/monniaux/cse2/loopaccess.c7
-rw-r--r--test/monniaux/cse2/loopinvariant.c7
-rw-r--r--test/monniaux/cse2/loopload.c5
-rw-r--r--test/monniaux/cycles.h57
-rw-r--r--test/monniaux/moves/array.c18
-rw-r--r--test/monniaux/quicksort/quicksort_run.c2
-rwxr-xr-xtest/monniaux/run_benches.sh5
-rw-r--r--test/monniaux/yarpgen/Makefile130
-rw-r--r--test/monniaux/yarpgen/Makefile.old52
-rwxr-xr-xtest/mppa/check.sh6
-rwxr-xr-xtest/mppa/hardcheck.sh6
-rwxr-xr-xtest/mppa/hardtest.sh6
-rw-r--r--test/mppa/instr/Makefile66
-rw-r--r--test/mppa/interop/Makefile137
-rwxr-xr-xtest/mppa/simucheck.sh6
-rwxr-xr-xtest/mppa/simutest.sh (renamed from test/mppa/test.sh)2
-rw-r--r--test/regression/Makefile4
-rw-r--r--test/regression/Results/int64874
-rw-r--r--test/regression/Results/interop18
-rw-r--r--test/regression/int64.c3
-rw-r--r--test/regression/interop1.c15
-rw-r--r--test/regression/packedstruct1.c24
-rw-r--r--x86/Asmexpand.ml4
-rw-r--r--x86/Asmgen.v12
-rw-r--r--x86/Asmgenproof.v12
-rw-r--r--x86/Asmgenproof1.v8
-rw-r--r--x86/Builtins1.v4
-rw-r--r--x86/CBuiltins.ml3
-rw-r--r--x86/CSE2deps.v24
-rw-r--r--x86/CSE2depsproof.v253
-rw-r--r--x86/Conventions1.v187
-rw-r--r--x86/DuplicateOpcodeHeuristic.ml27
-rw-r--r--x86/Op.v72
-rw-r--r--x86/ValueAOp.v21
272 files changed, 14919 insertions, 3107 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..02ab53c1
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+# Files that should be ignored by Github linguist
+test/* linguist-vendored
+doc/* linguist-documentation
diff --git a/.gitignore b/.gitignore
index eb11c837..e886bc10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@
**.out
**.tok
*.vo
+*.vok
+*.vos
*.glob
*.o
*.a
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000..1f854fc3
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,240 @@
+stages:
+ - build
+
+check-admitted:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_x86_64.sh
+ - make check-admitted
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_x86_64:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_x86_64.sh
+ - make -j "$NJOBS"
+ - make -C test all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_ia32:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-multilib
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_ia32.sh
+ - make -j "$NJOBS"
+ - make -C test all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen BITS=32 TARGET_CC='gcc -m32'
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_aarch64:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-aarch64-linux-gnu qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_aarch64.sh
+ - make -j "$NJOBS"
+ - make -C test CCOMPOPTS='-static' SIMU='qemu-aarch64' EXECUTE='qemu-aarch64' all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen TARGET_CC='aarch64-linux-gnu-gcc' EXECUTE='qemu-aarch64' CCOMPOPTS='-static' TARGET_CFLAGS='-static'
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_arm:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-arm-linux-gnueabi qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_arm.sh
+ - make -j "$NJOBS"
+ - make -C test CCOMPOPTS=-static SIMU='qemu-arm' EXECUTE='qemu-arm' all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen TARGET_CC='arm-linux-gnueabi-gcc' EXECUTE='qemu-arm' CCOMPOPTS='-static' TARGET_CFLAGS='-static' BITS=32
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+
+build_armhf:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-arm-linux-gnueabihf qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_armhf.sh
+ - make -j "$NJOBS"
+ - make -C test CCOMPOPTS=-static SIMU='qemu-arm' EXECUTE='qemu-arm' all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen TARGET_CC='arm-linux-gnueabihf-gcc' EXECUTE='qemu-arm' CCOMPOPTS='-static' TARGET_CFLAGS='-static' BITS=32
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_ppc:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-powerpc-linux-gnu qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_ppc.sh
+ - make -j "$NJOBS"
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_ppc64:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-powerpc64-linux-gnu
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_ppc64.sh
+ - make -j "$NJOBS"
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_rv64:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-riscv64-linux-gnu qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_rv64.sh
+ - make -j "$NJOBS"
+ - make -C test CCOMPOPTS=-static SIMU='qemu-riscv64' EXECUTE='qemu-riscv64' all test
+ - ulimit -s65536 && make -C test/monniaux/yarpgen TARGET_CC='riscv64-linux-gnu-gcc' EXECUTE='qemu-riscv64' CCOMPOPTS='-static' TARGET_CFLAGS='-static'
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_rv32:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - sudo apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Check-Date=false update
+ - sudo apt-get -y install gcc-riscv64-linux-gnu qemu-user
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_rv32.sh -no-runtime-lib
+ - make -j "$NJOBS"
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
+
+build_k1c:
+ stage: build
+ image: "coqorg/coq"
+ before_script:
+ - opam switch 4.07.1+flambda
+ - eval `opam config env`
+ - opam install -y menhir
+ script:
+ - ./config_k1c.sh -no-runtime-lib
+ - make -j "$NJOBS"
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "mppa-work"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "mppa-k1c"'
+ when: always
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: always
+ - when: manual
diff --git a/Changelog b/Changelog
index 935f77f2..8cf4e548 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,41 @@
+Release 3.7, 2020-03-31
+=======================
+
+ISO C conformance:
+- Functions declared `extern` then implemented `inline` remain `extern`
+- The type of a wide char constant is `wchar_t`, not `int`
+- Support vertical tabs and treat them as whitespace
+- Define the semantics of `free(NULL)`
+
+Bug fixing:
+- Take sign into account for conversions from 32-bit integers to 64-bit pointers
+- PowerPC: more precise determination of small data accesses
+- AArch64: when addressing global variables, check for correct alignment
+- PowerPC, ARM: double rounding error in int64->float32 conversions
+
+ABI conformance:
+- x86, AArch64: re-normalize values of small integer types returned by
+ function calls
+- PowerPC: `float` arguments passed on stack are passed in 64-bit format
+- RISC-V: use the new ELF psABI instead of the old ABI from ISA 2.1
+
+Usability and diagnostics:
+- Unknown builtin functions trigger a specific error message
+- Improved error messages
+
+Coq formalization:
+- Revised modeling of the PowerPC/EREF `isel` instruction
+- Weaker `ec_readonly` condition over external calls
+ (permissions can be dropped on read-only locations)
+
+Coq and OCaml development:
+- Compatibility with Coq version 8.10.1, 8.10.2, 8.11.0
+- Compatibility with OCaml 4.10 and up
+- Compatibility with Menhir 20200123 and up
+- Coq versions prior to 8.8.0 are no longer supported
+- OCaml versions prior to 4.05.0 are no longer supported
+
+
Release 3.6, 2019-09-17
=======================
diff --git a/Makefile b/Makefile
index 299f5ffe..2cd40800 100644
--- a/Makefile
+++ b/Makefile
@@ -86,9 +86,13 @@ BACKEND=\
ValueDomain.v ValueAOp.v ValueAnalysis.v \
ConstpropOp.v Constprop.v ConstpropOpproof.v Constpropproof.v \
CSEdomain.v CombineOp.v CSE.v CombineOpproof.v CSEproof.v \
+ CSE2deps.v CSE2depsproof.v \
+ CSE2.v CSE2proof.v \
NeedDomain.v NeedOp.v Deadcode.v Deadcodeproof.v \
Unusedglob.v Unusedglobproof.v \
Machregs.v Locations.v Conventions1.v Conventions.v LTL.v \
+ ForwardMoves.v ForwardMovesproof.v \
+ Allnontrap.v Allnontrapproof.v \
Allocation.v Allocproof.v \
Tunneling.v Tunnelingproof.v \
Linear.v Lineartyping.v \
@@ -263,7 +267,7 @@ endif
clean:
- rm -f $(patsubst %, %/*.vo, $(DIRS))
+ rm -f $(patsubst %, %/*.vo*, $(DIRS))
rm -f $(patsubst %, %/.*.aux, $(DIRS))
rm -rf doc/html doc/*.glob
rm -f driver/Version.ml
diff --git a/Makefile.extr b/Makefile.extr
index 51e9be59..f2d06def 100644
--- a/Makefile.extr
+++ b/Makefile.extr
@@ -50,13 +50,12 @@ INCLUDES=$(patsubst %,-I %, $(DIRS))
# Control of warnings:
WARNINGS=-w +a-4-9-27-42 -strict-sequence -safe-string -warn-error +a #Deprication returns with ocaml 4.03
-extraction/%.cmx: WARNINGS +=-w -20-27-32..34-39-41-44..45-60
-extraction/%.cmo: WARNINGS +=-w -20-27-32..34-39-41-44..45-60
-
+extraction/%.cmx: WARNINGS +=-w -20-27-32..34-39-41-44..45-60-67
+extraction/%.cmo: WARNINGS +=-w -20-27-32..34-39-41-44..45-60-67
cparser/pre_parser.cmx: WARNINGS += -w -41
cparser/pre_parser.cmo: WARNINGS += -w -41
-COMPFLAGS+=-g $(INCLUDES) $(MENHIR_INCLUDES) $(WARNINGS)
+COMPFLAGS+=-g $(INCLUDES) -I "$(MENHIR_DIR)" $(WARNINGS)
# Using .opt compilers if available
diff --git a/Makefile.menhir b/Makefile.menhir
index 98bfc750..7909b2f6 100644
--- a/Makefile.menhir
+++ b/Makefile.menhir
@@ -41,7 +41,11 @@ MENHIR_FLAGS = -v --no-stdlib -la 1
# Using Menhir in --table mode requires MenhirLib.
ifeq ($(MENHIR_TABLE),true)
- MENHIR_LIBS = menhirLib.cmx
+ ifeq ($(wildcard $(MENHIR_DIR)/menhirLib.cmxa),)
+ MENHIR_LIBS = menhirLib.cmx
+ else
+ MENHIR_LIBS = menhirLib.cmxa
+ endif
else
MENHIR_LIBS =
endif
diff --git a/VERSION b/VERSION
index 92686b06..b60e8d9b 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,3 @@
-version=3.6
+version=3.7
buildnr=
tag=
diff --git a/aarch64/Asmexpand.ml b/aarch64/Asmexpand.ml
index ab155e9c..471ad501 100644
--- a/aarch64/Asmexpand.ml
+++ b/aarch64/Asmexpand.ml
@@ -408,19 +408,34 @@ let expand_instruction instr =
| _ ->
emit instr
-let int_reg_to_dwarf r = 0 (* TODO *)
-
-let float_reg_to_dwarf r = 0 (* TODO *)
+let int_reg_to_dwarf = function
+ | X0 -> 0 | X1 -> 1 | X2 -> 2 | X3 -> 3 | X4 -> 4
+ | X5 -> 5 | X6 -> 6 | X7 -> 7 | X8 -> 8 | X9 -> 9
+ | X10 -> 10 | X11 -> 11 | X12 -> 12 | X13 -> 13 | X14 -> 14
+ | X15 -> 15 | X16 -> 16 | X17 -> 17 | X18 -> 18 | X19 -> 19
+ | X20 -> 20 | X21 -> 21 | X22 -> 22 | X23 -> 23 | X24 -> 24
+ | X25 -> 25 | X26 -> 26 | X27 -> 27 | X28 -> 28 | X29 -> 29
+ | X30 -> 30
+
+let float_reg_to_dwarf = function
+ | D0 -> 64 | D1 -> 65 | D2 -> 66 | D3 -> 67 | D4 -> 68
+ | D5 -> 69 | D6 -> 70 | D7 -> 71 | D8 -> 72 | D9 -> 73
+ | D10 -> 74 | D11 -> 75 | D12 -> 76 | D13 -> 77 | D14 -> 78
+ | D15 -> 79 | D16 -> 80 | D17 -> 81 | D18 -> 82 | D19 -> 83
+ | D20 -> 84 | D21 -> 85 | D22 -> 86 | D23 -> 87 | D24 -> 88
+ | D25 -> 89 | D26 -> 90 | D27 -> 91 | D28 -> 92 | D29 -> 93
+ | D30 -> 94 | D31 -> 95
let preg_to_dwarf = function
| IR r -> int_reg_to_dwarf r
| FR r -> float_reg_to_dwarf r
+ | SP -> 31
| _ -> assert false
let expand_function id fn =
try
set_current_function fn;
- expand id (* sp= *) 2 preg_to_dwarf expand_instruction fn.fn_code;
+ expand id (* sp= *) 31 preg_to_dwarf expand_instruction fn.fn_code;
Errors.OK (get_current_function ())
with Error s ->
Errors.Error (Errors.msg (coqstring_of_camlstring s))
diff --git a/aarch64/Asmgen.v b/aarch64/Asmgen.v
index 1c0e41a1..024c9a17 100644
--- a/aarch64/Asmgen.v
+++ b/aarch64/Asmgen.v
@@ -20,6 +20,11 @@ Local Open Scope string_scope.
Local Open Scope list_scope.
Local Open Scope error_monad_scope.
+(** Alignment check for symbols *)
+
+Parameter symbol_is_aligned : ident -> Z -> bool.
+(** [symbol_is_aligned id sz] checks whether the symbol [id] is [sz] aligned *)
+
(** Extracting integer or float registers. *)
Definition ireg_of (r: mreg) : res ireg :=
@@ -263,18 +268,24 @@ Definition arith_extended
Definition shrx32 (rd r1: ireg) (n: int) (k: code) : code :=
if Int.eq n Int.zero then
Pmov rd r1 :: k
- else
- Porr W X16 XZR r1 (SOasr (Int.repr 31)) ::
- Padd W X16 r1 X16 (SOlsr (Int.sub Int.iwordsize n)) ::
- Porr W rd XZR X16 (SOasr n) :: k.
+ else if Int.eq n Int.one then
+ Padd W X16 r1 r1 (SOlsr (Int.repr 31)) ::
+ Porr W rd XZR X16 (SOasr n) :: k
+ else
+ Porr W X16 XZR r1 (SOasr (Int.repr 31)) ::
+ Padd W X16 r1 X16 (SOlsr (Int.sub Int.iwordsize n)) ::
+ Porr W rd XZR X16 (SOasr n) :: k.
Definition shrx64 (rd r1: ireg) (n: int) (k: code) : code :=
if Int.eq n Int.zero then
Pmov rd r1 :: k
- else
- Porr X X16 XZR r1 (SOasr (Int.repr 63)) ::
- Padd X X16 r1 X16 (SOlsr (Int.sub Int64.iwordsize' n)) ::
- Porr X rd XZR X16 (SOasr n) :: k.
+ else if Int.eq n Int.one then
+ Padd X X16 r1 r1 (SOlsr (Int.repr 63)) ::
+ Porr X rd XZR X16 (SOasr n) :: k
+ else
+ Porr X X16 XZR r1 (SOasr (Int.repr 63)) ::
+ Padd X X16 r1 X16 (SOlsr (Int.sub Int64.iwordsize' n)) ::
+ Porr X rd XZR X16 (SOasr n) :: k.
(** Load the address [id + ofs] in [rd] *)
@@ -942,7 +953,7 @@ Definition transl_addressing (sz: Z) (addr: Op.addressing) (args: list mreg)
(insn (ADimm X16 Int64.zero) :: k))
| Aglobal id ofs, nil =>
assertion (negb (Archi.pic_code tt));
- if Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero
+ if Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero && symbol_is_aligned id sz
then OK (Padrp X16 id ofs :: insn (ADadr X16 id ofs) :: k)
else OK (loadsymbol X16 id ofs (insn (ADimm X16 Int64.zero) :: k))
| Ainstack ofs, nil =>
@@ -957,8 +968,12 @@ Definition transl_addressing (sz: Z) (addr: Op.addressing) (args: list mreg)
(** Translation of loads and stores *)
-Definition transl_load (chunk: memory_chunk) (addr: Op.addressing)
+Definition transl_load (trap: trapping_mode)
+ (chunk: memory_chunk) (addr: Op.addressing)
(args: list mreg) (dst: mreg) (k: code) : res code :=
+ match trap with
+ | NOTRAP => Error (msg "Asmgen.transl_load non-trapping loads unsupported on aarch64")
+ | TRAP =>
match chunk with
| Mint8unsigned =>
do rd <- ireg_of dst; transl_addressing 1 addr args (Pldrb W rd) k
@@ -980,6 +995,7 @@ Definition transl_load (chunk: memory_chunk) (addr: Op.addressing)
do rd <- ireg_of dst; transl_addressing 4 addr args (Pldrw_a rd) k
| Many64 =>
do rd <- ireg_of dst; transl_addressing 8 addr args (Pldrx_a rd) k
+ end
end.
Definition transl_store (chunk: memory_chunk) (addr: Op.addressing)
@@ -1045,8 +1061,13 @@ Definition storeptr (src: ireg) (base: iregsp) (ofs: ptrofs) (k: code) :=
(** Function epilogue *)
Definition make_epilogue (f: Mach.function) (k: code) :=
- loadptr XSP f.(fn_retaddr_ofs) RA
- (Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k).
+ (* FIXME
+ Cannot be used because memcpy destroys X30;
+ issue being discussed with X. Leroy *)
+ (* if is_leaf_function f
+ then Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k
+ else*) loadptr XSP f.(fn_retaddr_ofs) RA
+ (Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k).
(** Translation of a Mach instruction. *)
@@ -1063,8 +1084,8 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
OK (if r29_is_parent then c else loadptr XSP f.(fn_link_ofs) X29 c)
| Mop op args res =>
transl_op op args res k
- | Mload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | Mload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| Mstore chunk addr args src =>
transl_store chunk addr args src k
| Mcall sig (inl r) =>
diff --git a/aarch64/Asmgenproof.v b/aarch64/Asmgenproof.v
index eeff1956..6831509f 100644
--- a/aarch64/Asmgenproof.v
+++ b/aarch64/Asmgenproof.v
@@ -259,13 +259,13 @@ Proof.
- apply logicalimm32_label; unfold nolabel; auto.
- apply logicalimm32_label; unfold nolabel; auto.
- apply logicalimm32_label; unfold nolabel; auto.
-- unfold shrx32. destruct Int.eq; TailNoLabel.
+- unfold shrx32. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
- apply arith_extended_label; unfold nolabel; auto.
- apply arith_extended_label; unfold nolabel; auto.
- apply logicalimm64_label; unfold nolabel; auto.
- apply logicalimm64_label; unfold nolabel; auto.
- apply logicalimm64_label; unfold nolabel; auto.
-- unfold shrx64. destruct Int.eq; TailNoLabel.
+- unfold shrx64. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
- eapply tail_nolabel_trans. eapply transl_cond_label; eauto. TailNoLabel.
- destruct (preg_of r); try discriminate; TailNoLabel;
(eapply tail_nolabel_trans; [eapply transl_cond_label; eauto | TailNoLabel]).
@@ -283,10 +283,10 @@ Proof.
Qed.
Remark transl_load_label:
- forall chunk addr args dst k c,
- transl_load chunk addr args dst k = OK c -> tail_nolabel k c.
+ forall trap chunk addr args dst k c,
+ transl_load trap chunk addr args dst k = OK c -> tail_nolabel k c.
Proof.
- unfold transl_load; intros; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
+ unfold transl_load; intros; destruct trap; try discriminate; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
Qed.
Remark transl_store_label:
@@ -337,7 +337,12 @@ Qed.
Remark make_epilogue_label:
forall f k, tail_nolabel k (make_epilogue f k).
Proof.
- unfold make_epilogue; intros. eapply tail_nolabel_trans. apply loadptr_label. TailNoLabel.
+ unfold make_epilogue; intros.
+ (* FIXME destruct is_leaf_function.
+ { TailNoLabel. } *)
+ eapply tail_nolabel_trans.
+ apply loadptr_label.
+ TailNoLabel.
Qed.
Lemma transl_instr_label:
@@ -472,7 +477,8 @@ Inductive match_states: Mach.state -> Asm.state -> Prop :=
(MEXT: Mem.extends m m')
(AT: transl_code_at_pc ge (rs PC) fb f c ep tf tc)
(AG: agree ms sp rs)
- (DXP: ep = true -> rs#X29 = parent_sp s),
+ (DXP: ep = true -> rs#X29 = parent_sp s)
+ (LEAF: is_leaf_function f = true -> rs#RA = parent_ra s),
match_states (Mach.State s fb sp c ms m)
(Asm.State rs m')
| match_states_call:
@@ -503,16 +509,17 @@ Lemma exec_straight_steps:
exists rs2,
exec_straight tge tf c rs1 m1' k rs2 m2'
/\ agree ms2 sp rs2
- /\ (it1_is_parent ep i = true -> rs2#X29 = parent_sp s)) ->
+ /\ (it1_is_parent ep i = true -> rs2#X29 = parent_sp s)
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
exists st',
plus step tge (State rs1 m1') E0 st' /\
match_states (Mach.State s fb sp c ms2 m2) st'.
Proof.
intros. inversion H2. subst. monadInv H7.
- exploit H3; eauto. intros [rs2 [A [B C]]].
+ exploit H3; eauto. intros [rs2 [A [B [C D]]]].
exists (State rs2 m2'); split.
- eapply exec_straight_exec; eauto.
- econstructor; eauto. eapply exec_straight_at; eauto.
+ - eapply exec_straight_exec; eauto.
+ - econstructor; eauto. eapply exec_straight_at; eauto.
Qed.
Lemma exec_straight_steps_goto:
@@ -527,13 +534,14 @@ Lemma exec_straight_steps_goto:
exists jmp, exists k', exists rs2,
exec_straight tge tf c rs1 m1' (jmp :: k') rs2 m2'
/\ agree ms2 sp rs2
- /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2') ->
+ /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
exists st',
plus step tge (State rs1 m1') E0 st' /\
match_states (Mach.State s fb sp c' ms2 m2) st'.
Proof.
intros. inversion H3. subst. monadInv H9.
- exploit H5; eauto. intros [jmp [k' [rs2 [A [B C]]]]].
+ exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
generalize (functions_transl _ _ _ H7 H8); intro FN.
generalize (transf_function_no_overflow _ _ H8); intro NOOV.
exploit exec_straight_steps_2; eauto.
@@ -550,6 +558,7 @@ Proof.
econstructor; eauto.
apply agree_exten with rs2; auto with asmgen.
congruence.
+ rewrite OTH by congruence; auto.
Qed.
Lemma exec_straight_opt_steps_goto:
@@ -564,13 +573,14 @@ Lemma exec_straight_opt_steps_goto:
exists jmp, exists k', exists rs2,
exec_straight_opt tge tf c rs1 m1' (jmp :: k') rs2 m2'
/\ agree ms2 sp rs2
- /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2') ->
+ /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
exists st',
plus step tge (State rs1 m1') E0 st' /\
match_states (Mach.State s fb sp c' ms2 m2) st'.
Proof.
intros. inversion H3. subst. monadInv H9.
- exploit H5; eauto. intros [jmp [k' [rs2 [A [B C]]]]].
+ exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
generalize (functions_transl _ _ _ H7 H8); intro FN.
generalize (transf_function_no_overflow _ _ H8); intro NOOV.
inv A.
@@ -583,6 +593,7 @@ Proof.
econstructor; eauto.
apply agree_exten with rs2; auto with asmgen.
congruence.
+ rewrite OTH by congruence; auto.
- exploit exec_straight_steps_2; eauto.
intros [ofs' [PC2 CT2]].
exploit find_label_goto_label; eauto.
@@ -597,6 +608,7 @@ Proof.
econstructor; eauto.
apply agree_exten with rs2; auto with asmgen.
congruence.
+ rewrite OTH by congruence; auto.
Qed.
(** We need to show that, in the simulation diagram, we cannot
@@ -629,7 +641,7 @@ Qed.
Theorem step_simulation:
forall S1 t S2, Mach.step return_address_offset ge S1 t S2 ->
- forall S1' (MS: match_states S1 S1'),
+ forall S1' (MS: match_states S1 S1') (WF: wf_state ge S1),
(exists S2', plus step tge S1' t S2' /\ match_states S2 S2')
\/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 S1')%nat.
Proof.
@@ -638,17 +650,20 @@ Proof.
- (* Mlabel *)
left; eapply exec_straight_steps; eauto; intros.
monadInv TR. econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split. apply agree_nextinstr; auto. simpl; congruence.
+ split. { apply agree_nextinstr; auto. }
+ split. { simpl; congruence. }
+ rewrite nextinstr_inv by congruence; assumption.
- (* Mgetstack *)
unfold load_stack in H.
exploit Mem.loadv_extends; eauto. intros [v' [A B]].
rewrite (sp_val _ _ _ AG) in A.
left; eapply exec_straight_steps; eauto. intros. simpl in TR.
- exploit loadind_correct; eauto with asmgen. intros [rs' [P [Q R]]].
+ exploit loadind_correct; eauto with asmgen. intros [rs' [P [Q [R S]]]].
exists rs'; split. eauto.
- split. eapply agree_set_mreg; eauto with asmgen. congruence.
- simpl; congruence.
+ split. { eapply agree_set_mreg; eauto with asmgen. congruence. }
+ split. { simpl; congruence. }
+ rewrite S. assumption.
- (* Msetstack *)
unfold store_stack in H.
@@ -656,10 +671,12 @@ Proof.
exploit Mem.storev_extends; eauto. intros [m2' [A B]].
left; eapply exec_straight_steps; eauto.
rewrite (sp_val _ _ _ AG) in A. intros. simpl in TR.
- exploit storeind_correct; eauto with asmgen. intros [rs' [P Q]].
+ exploit storeind_correct; eauto with asmgen. intros [rs' [P [Q R]]].
exists rs'; split. eauto.
split. eapply agree_undef_regs; eauto with asmgen.
- simpl; intros. rewrite Q; auto with asmgen.
+ simpl; intros.
+ split. rewrite Q; auto with asmgen.
+ rewrite R. assumption.
- (* Mgetparam *)
assert (f0 = f) by congruence; subst f0.
@@ -675,50 +692,69 @@ Opaque loadind.
(* X30 contains parent *)
exploit loadind_correct. eexact EQ.
instantiate (2 := rs0). simpl; rewrite DXP; eauto. simpl; congruence.
- intros [rs1 [P [Q R]]].
+ intros [rs1 [P [Q [R S]]]].
exists rs1; split. eauto.
split. eapply agree_set_mreg. eapply agree_set_mreg; eauto. congruence. auto with asmgen.
- simpl; intros. rewrite R; auto with asmgen.
- apply preg_of_not_X29; auto.
+ simpl; split; intros.
+ { rewrite R; auto with asmgen.
+ apply preg_of_not_X29; auto.
+ }
+ { rewrite S; auto. }
+
(* X30 does not contain parent *)
exploit loadptr_correct. eexact A. simpl; congruence. intros [rs1 [P [Q R]]].
exploit loadind_correct. eexact EQ. instantiate (2 := rs1). simpl; rewrite Q. eauto. simpl; congruence.
- intros [rs2 [S [T U]]].
+ intros [rs2 [S [T [U V]]]].
exists rs2; split. eapply exec_straight_trans; eauto.
split. eapply agree_set_mreg. eapply agree_set_mreg. eauto. eauto.
instantiate (1 := rs1#X29 <- (rs2#X29)). intros.
rewrite Pregmap.gso; auto with asmgen.
congruence.
intros. unfold Pregmap.set. destruct (PregEq.eq r' X29). congruence. auto with asmgen.
- simpl; intros. rewrite U; auto with asmgen.
+ split; simpl; intros. rewrite U; auto with asmgen.
apply preg_of_not_X29; auto.
-
+ rewrite V. rewrite R by congruence. auto.
+
- (* Mop *)
assert (eval_operation tge sp op (map rs args) m = Some v).
{ rewrite <- H. apply eval_operation_preserved. exact symbols_preserved. }
exploit eval_operation_lessdef. eapply preg_vals; eauto. eauto. eexact H0.
intros [v' [A B]]. rewrite (sp_val _ _ _ AG) in A.
left; eapply exec_straight_steps; eauto; intros. simpl in TR.
- exploit transl_op_correct; eauto. intros [rs2 [P [Q R]]].
+ exploit transl_op_correct; eauto. intros [rs2 [P [Q [R S]]]].
exists rs2; split. eauto. split.
apply agree_set_undef_mreg with rs0; auto.
apply Val.lessdef_trans with v'; auto.
- simpl; intros. InvBooleans.
+ split; simpl; intros. InvBooleans.
rewrite R; auto. apply preg_of_not_X29; auto.
Local Transparent destroyed_by_op.
destruct op; try exact I; simpl; congruence.
-
+ rewrite S.
+ auto.
- (* Mload *)
+ destruct trap.
+ {
assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
{ rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved. }
exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
exploit Mem.loadv_extends; eauto. intros [v' [C D]].
left; eapply exec_straight_steps; eauto; intros. simpl in TR.
- exploit transl_load_correct; eauto. intros [rs2 [P [Q R]]].
+ exploit transl_load_correct; eauto. intros [rs2 [P [Q [R S]]]].
exists rs2; split. eauto.
split. eapply agree_set_undef_mreg; eauto. congruence.
- simpl; congruence.
+ split. simpl; congruence.
+ rewrite S. assumption.
+ }
+
+ (* Mload notrap1 *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
- (* Mstore *)
assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
@@ -728,10 +764,11 @@ Local Transparent destroyed_by_op.
assert (Val.lessdef (rs src) (rs0 (preg_of src))) by (eapply preg_val; eauto).
exploit Mem.storev_extends; eauto. intros [m2' [C D]].
left; eapply exec_straight_steps; eauto.
- intros. simpl in TR. exploit transl_store_correct; eauto. intros [rs2 [P Q]].
+ intros. simpl in TR. exploit transl_store_correct; eauto. intros [rs2 [P [Q R]]].
exists rs2; split. eauto.
split. eapply agree_undef_regs; eauto with asmgen.
- simpl; congruence.
+ split. simpl; congruence.
+ rewrite R. assumption.
- (* Mcall *)
assert (f0 = f) by congruence. subst f0.
@@ -840,6 +877,18 @@ Local Transparent destroyed_by_op.
eapply agree_undef_regs; eauto. intros. rewrite undef_regs_other_2; auto.
congruence.
+ Simpl.
+ rewrite set_res_other by trivial.
+ rewrite undef_regs_other.
+ assumption.
+ intro.
+ rewrite in_map_iff.
+ intros (x0 & PREG & IN).
+ subst r'.
+ intro.
+ apply (preg_of_not_RA x0).
+ congruence.
+
- (* Mgoto *)
assert (f0 = f) by congruence. subst f0.
inv AT. monadInv H4.
@@ -853,25 +902,33 @@ Local Transparent destroyed_by_op.
eapply agree_exten; eauto with asmgen.
congruence.
+ rewrite INV by congruence.
+ assumption.
+
- (* Mcond true *)
assert (f0 = f) by congruence. subst f0.
exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
left; eapply exec_straight_opt_steps_goto; eauto.
intros. simpl in TR.
- exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C).
+ exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
exists jmp; exists k; exists rs'.
split. eexact A.
split. apply agree_exten with rs0; auto with asmgen.
- exact B.
+ split.
+ exact B.
+ rewrite D. exact LEAF.
- (* Mcond false *)
exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
left; eapply exec_straight_steps; eauto. intros. simpl in TR.
- exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C).
+ exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
econstructor; split.
eapply exec_straight_opt_right. eexact A. apply exec_straight_one. eexact B. auto.
split. apply agree_exten with rs0; auto. intros. Simpl.
+ split.
simpl; congruence.
+ Simpl. rewrite D.
+ exact LEAF.
- (* Mjumptable *)
assert (f0 = f) by congruence. subst f0.
@@ -893,6 +950,10 @@ Local Transparent destroyed_by_op.
simpl. intros. rewrite C; auto with asmgen. Simpl.
congruence.
+ rewrite C by congruence.
+ repeat rewrite Pregmap.gso by congruence.
+ assumption.
+
- (* Mreturn *)
assert (f0 = f) by congruence. subst f0.
inversion AT; subst. simpl in H6; monadInv H6.
@@ -935,7 +996,7 @@ Local Transparent destroyed_by_op.
simpl preg_of_iregsp. change (rs2 X30) with (rs0 X30). rewrite ATLR.
change (rs2 X2) with sp. eexact P.
simpl; congruence. congruence.
- intros (rs3 & U & V).
+ intros (rs3 & U & V & W).
assert (EXEC_PROLOGUE:
exec_straight tge tf
tf.(fn_code) rs0 m'
@@ -962,6 +1023,10 @@ Local Transparent destroyed_at_function_entry. simpl.
unfold sp; congruence.
intros. rewrite V by auto with asmgen. reflexivity.
+ rewrite W.
+ unfold rs2.
+ Simpl.
+
- (* external function *)
exploit functions_translated; eauto.
intros [tf [A B]]. simpl in B. inv B.
@@ -981,6 +1046,10 @@ Local Transparent destroyed_at_function_entry. simpl.
right. split. omega. split. auto.
rewrite <- ATPC in H5.
econstructor; eauto. congruence.
+ inv WF.
+ inv STACK.
+ inv H1.
+ congruence.
Qed.
Lemma transf_initial_states:
@@ -1016,11 +1085,17 @@ Qed.
Theorem transf_program_correct:
forward_simulation (Mach.semantics return_address_offset prog) (Asm.semantics tprog).
Proof.
- eapply forward_simulation_star with (measure := measure).
- apply senv_preserved.
- eexact transf_initial_states.
- eexact transf_final_states.
- exact step_simulation.
+ eapply forward_simulation_star with (measure := measure)
+ (match_states := fun S1 S2 => match_states S1 S2 /\ wf_state ge S1).
+ - apply senv_preserved.
+ - simpl; intros. exploit transf_initial_states; eauto.
+ intros (s2 & A & B).
+ exists s2; intuition auto. apply wf_initial; auto.
+ - simpl; intros. destruct H as [MS WF]. eapply transf_final_states; eauto.
+ - simpl; intros. destruct H0 as [MS WF].
+ exploit step_simulation; eauto. intros [ (s2' & A & B) | (A & B & C) ].
+ + left; exists s2'; intuition auto. eapply wf_step; eauto.
+ + right; intuition auto. eapply wf_step; eauto.
Qed.
End PRESERVATION.
diff --git a/aarch64/Asmgenproof1.v b/aarch64/Asmgenproof1.v
index 663ee50b..0e36bd05 100644
--- a/aarch64/Asmgenproof1.v
+++ b/aarch64/Asmgenproof1.v
@@ -22,6 +22,51 @@ Local Transparent Archi.ptr64.
(** Properties of registers *)
+Lemma preg_of_not_RA:
+ forall r, (preg_of r) <> RA.
+Proof.
+ destruct r; discriminate.
+Qed.
+
+Lemma RA_not_written:
+ forall (rs : regset) dst v,
+ rs # (preg_of dst) <- v RA = rs RA.
+Proof.
+ intros.
+ apply Pregmap.gso.
+ intro.
+ symmetry in H.
+ exact (preg_of_not_RA dst H).
+Qed.
+
+Hint Resolve RA_not_written : asmgen.
+
+Lemma RA_not_written2:
+ forall (rs : regset) dst v i,
+ preg_of dst = i ->
+ rs # i <- v RA = rs RA.
+Proof.
+ intros.
+ subst i.
+ apply RA_not_written.
+Qed.
+
+Hint Resolve RA_not_written2 : asmgen.
+
+Lemma RA_not_written3:
+ forall (rs : regset) dst v i,
+ ireg_of dst = OK i ->
+ rs # i <- v RA = rs RA.
+Proof.
+ intros.
+ unfold ireg_of in H.
+ destruct preg_of eqn:PREG; try discriminate.
+ replace i0 with i in * by congruence.
+ eapply RA_not_written2; eassumption.
+Qed.
+
+Hint Resolve RA_not_written3 : asmgen.
+
Lemma preg_of_iregsp_not_PC: forall r, preg_of_iregsp r <> PC.
Proof.
destruct r; simpl; congruence.
@@ -39,6 +84,26 @@ Proof.
red; intros; subst x. elim (preg_of_not_X16 r); auto.
Qed.
+Lemma ireg_of_not_RA: forall r x, ireg_of r = OK x -> x <> RA.
+Proof.
+ unfold ireg_of; intros. destruct (preg_of r) eqn:E; inv H.
+ red; intros; subst x. elim (preg_of_not_RA r); auto.
+Qed.
+
+Lemma ireg_of_not_RA': forall r x, ireg_of r = OK x -> RA <> x.
+Proof.
+ intros. intro.
+ apply (ireg_of_not_RA r x); auto.
+Qed.
+
+Lemma ireg_of_not_RA'': forall r x, ireg_of r = OK x -> IR RA <> IR x.
+Proof.
+ intros. intro.
+ apply (ireg_of_not_RA' r x); auto. congruence.
+Qed.
+
+Hint Resolve ireg_of_not_RA ireg_of_not_RA' ireg_of_not_RA'' : asmgen.
+
Lemma ireg_of_not_X16': forall r x, ireg_of r = OK x -> IR x <> IR X16.
Proof.
intros. apply ireg_of_not_X16 in H. congruence.
@@ -205,42 +270,49 @@ Qed.
Lemma exec_loadimm_k_w:
forall (rd: ireg) k m l,
wf_decomposition l ->
+ rd <> RA ->
forall (rs: regset) accu,
rs#rd = Vint (Int.repr accu) ->
exists rs',
exec_straight_opt ge fn (loadimm_k W rd l k) rs m k rs' m
/\ rs'#rd = Vint (Int.repr (recompose_int accu l))
- /\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, r <> PC -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
- induction 1; intros rs accu ACCU; simpl.
+ induction 1; intros RD_NOT_RA rs accu ACCU; simpl.
- exists rs; split. apply exec_straight_opt_refl. auto.
-- destruct (IHwf_decomposition
+- destruct (IHwf_decomposition RD_NOT_RA
(nextinstr (rs#rd <- (insert_in_int rs#rd n p 16)))
(Zinsert accu n p 16))
- as (rs' & P & Q & R).
+ as (rs' & P & Q & R & S).
Simpl. rewrite ACCU. simpl. f_equal. apply Int.eqm_samerepr.
apply Zinsert_eqmod. auto. omega. apply Int.eqm_sym; apply Int.eqm_unsigned_repr.
exists rs'; split.
eapply exec_straight_opt_step_opt. simpl; eauto. auto. exact P.
- split. exact Q. intros; Simpl. rewrite R by auto. Simpl.
+ split. exact Q.
+ split.
+ { intros; Simpl.
+ rewrite R by auto. Simpl. }
+ { rewrite S. Simpl. }
Qed.
Lemma exec_loadimm_z_w:
forall rd l k rs m,
wf_decomposition l ->
+ rd <> RA ->
exists rs',
exec_straight ge fn (loadimm_z W rd l k) rs m k rs' m
/\ rs'#rd = Vint (Int.repr (recompose_int 0 l))
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- unfold loadimm_z; destruct 1.
+ unfold loadimm_z; destruct 1; intro RD_NOT_RA.
- econstructor; split.
apply exec_straight_one. simpl; eauto. auto.
split. Simpl.
intros; Simpl.
- set (accu0 := Zinsert 0 n p 16).
set (rs1 := nextinstr (rs#rd <- (Vint (Int.repr accu0)))).
- destruct (exec_loadimm_k_w rd k m l H1 rs1 accu0) as (rs2 & P & Q & R); auto.
+ destruct (exec_loadimm_k_w rd k m l H1 RD_NOT_RA rs1 accu0) as (rs2 & P & Q & R & S); auto.
unfold rs1; Simpl.
exists rs2; split.
eapply exec_straight_opt_step; eauto.
@@ -253,12 +325,13 @@ Qed.
Lemma exec_loadimm_n_w:
forall rd l k rs m,
wf_decomposition l ->
+ rd <> RA ->
exists rs',
exec_straight ge fn (loadimm_n W rd l k) rs m k rs' m
/\ rs'#rd = Vint (Int.repr (Z.lnot (recompose_int 0 l)))
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- unfold loadimm_n; destruct 1.
+ unfold loadimm_n; destruct 1; intro RD_NOT_RA.
- econstructor; split.
apply exec_straight_one. simpl; eauto. auto.
split. Simpl.
@@ -267,7 +340,8 @@ Proof.
set (rs1 := nextinstr (rs#rd <- (Vint (Int.repr accu0)))).
destruct (exec_loadimm_k_w rd k m (negate_decomposition l)
(negate_decomposition_wf l H1)
- rs1 accu0) as (rs2 & P & Q & R).
+ RD_NOT_RA rs1 accu0)
+ as (rs2 & P & Q & R & S).
unfold rs1; Simpl.
exists rs2; split.
eapply exec_straight_opt_step; eauto.
@@ -279,7 +353,8 @@ Proof.
Qed.
Lemma exec_loadimm32:
- forall rd n k rs m,
+ forall rd n k rs m
+ (RD_NOT_RA : rd <> RA),
exists rs',
exec_straight ge fn (loadimm32 rd n k) rs m k rs' m
/\ rs'#rd = Vint n
@@ -302,13 +377,14 @@ Proof.
apply Int.eqm_samerepr. apply decompose_notint_eqmod.
apply Int.repr_unsigned. }
destruct Nat.leb.
-+ rewrite <- A. apply exec_loadimm_z_w. apply decompose_int_wf; omega.
-+ rewrite <- B. apply exec_loadimm_n_w. apply decompose_int_wf; omega.
++ rewrite <- A. apply exec_loadimm_z_w. apply decompose_int_wf; omega. trivial.
++ rewrite <- B. apply exec_loadimm_n_w. apply decompose_int_wf; omega. trivial.
Qed.
Lemma exec_loadimm_k_x:
forall (rd: ireg) k m l,
- wf_decomposition l ->
+ wf_decomposition l ->
+ rd <> RA ->
forall (rs: regset) accu,
rs#rd = Vlong (Int64.repr accu) ->
exists rs',
@@ -316,9 +392,9 @@ Lemma exec_loadimm_k_x:
/\ rs'#rd = Vlong (Int64.repr (recompose_int accu l))
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- induction 1; intros rs accu ACCU; simpl.
+ induction 1; intros RD_NOT_RA rs accu ACCU; simpl.
- exists rs; split. apply exec_straight_opt_refl. auto.
-- destruct (IHwf_decomposition
+- destruct (IHwf_decomposition RD_NOT_RA
(nextinstr (rs#rd <- (insert_in_long rs#rd n p 16)))
(Zinsert accu n p 16))
as (rs' & P & Q & R).
@@ -332,19 +408,20 @@ Qed.
Lemma exec_loadimm_z_x:
forall rd l k rs m,
wf_decomposition l ->
+ rd <> RA ->
exists rs',
exec_straight ge fn (loadimm_z X rd l k) rs m k rs' m
/\ rs'#rd = Vlong (Int64.repr (recompose_int 0 l))
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- unfold loadimm_z; destruct 1.
+ unfold loadimm_z; destruct 1; intro RD_NOT_RA.
- econstructor; split.
apply exec_straight_one. simpl; eauto. auto.
split. Simpl.
intros; Simpl.
- set (accu0 := Zinsert 0 n p 16).
set (rs1 := nextinstr (rs#rd <- (Vlong (Int64.repr accu0)))).
- destruct (exec_loadimm_k_x rd k m l H1 rs1 accu0) as (rs2 & P & Q & R); auto.
+ destruct (exec_loadimm_k_x rd k m l H1 RD_NOT_RA rs1 accu0) as (rs2 & P & Q & R); auto.
unfold rs1; Simpl.
exists rs2; split.
eapply exec_straight_opt_step; eauto.
@@ -357,12 +434,13 @@ Qed.
Lemma exec_loadimm_n_x:
forall rd l k rs m,
wf_decomposition l ->
+ rd <> RA ->
exists rs',
exec_straight ge fn (loadimm_n X rd l k) rs m k rs' m
/\ rs'#rd = Vlong (Int64.repr (Z.lnot (recompose_int 0 l)))
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- unfold loadimm_n; destruct 1.
+ unfold loadimm_n; destruct 1; intro RD_NOT_RA.
- econstructor; split.
apply exec_straight_one. simpl; eauto. auto.
split. Simpl.
@@ -371,7 +449,7 @@ Proof.
set (rs1 := nextinstr (rs#rd <- (Vlong (Int64.repr accu0)))).
destruct (exec_loadimm_k_x rd k m (negate_decomposition l)
(negate_decomposition_wf l H1)
- rs1 accu0) as (rs2 & P & Q & R).
+ RD_NOT_RA rs1 accu0) as (rs2 & P & Q & R).
unfold rs1; Simpl.
exists rs2; split.
eapply exec_straight_opt_step; eauto.
@@ -384,12 +462,13 @@ Qed.
Lemma exec_loadimm64:
forall rd n k rs m,
+ rd <> RA ->
exists rs',
exec_straight ge fn (loadimm64 rd n k) rs m k rs' m
/\ rs'#rd = Vlong n
/\ forall r, r <> PC -> r <> rd -> rs'#r = rs#r.
Proof.
- unfold loadimm64, loadimm; intros.
+ unfold loadimm64, loadimm; intros until m; intro RD_NOT_RA.
destruct (is_logical_imm64 n).
- econstructor; split.
apply exec_straight_one. simpl; eauto. auto.
@@ -406,8 +485,8 @@ Proof.
apply Int64.eqm_samerepr. apply decompose_notint_eqmod.
apply Int64.repr_unsigned. }
destruct Nat.leb.
-+ rewrite <- A. apply exec_loadimm_z_x. apply decompose_int_wf; omega.
-+ rewrite <- B. apply exec_loadimm_n_x. apply decompose_int_wf; omega.
++ rewrite <- A. apply exec_loadimm_z_x. apply decompose_int_wf; omega. trivial.
++ rewrite <- B. apply exec_loadimm_n_x. apply decompose_int_wf; omega. trivial.
Qed.
(** Add immediate *)
@@ -419,55 +498,59 @@ Lemma exec_addimm_aux_32:
Next (nextinstr (rs#rd <- (sem rs#r1 (Vint (Int.repr n))))) m) ->
(forall v n1 n2, sem (sem v (Vint n1)) (Vint n2) = sem v (Vint (Int.add n1 n2))) ->
forall rd r1 n k rs m,
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (addimm_aux insn rd r1 (Int.unsigned n) k) rs m k rs' m
/\ rs'#rd = sem rs#r1 (Vint n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
- intros insn sem SEM ASSOC; intros. unfold addimm_aux.
+ intros insn sem SEM ASSOC; intros until m; intro RD_NOT_RA. unfold addimm_aux.
set (nlo := Zzero_ext 12 (Int.unsigned n)). set (nhi := Int.unsigned n - nlo).
assert (E: Int.unsigned n = nhi + nlo) by (unfold nhi; omega).
rewrite <- (Int.repr_unsigned n).
destruct (Z.eqb_spec nhi 0); [|destruct (Z.eqb_spec nlo 0)].
- econstructor; split. apply exec_straight_one. apply SEM. Simpl.
split. Simpl. do 3 f_equal; omega.
- intros; Simpl.
+ split; intros; Simpl.
- econstructor; split. apply exec_straight_one. apply SEM. Simpl.
split. Simpl. do 3 f_equal; omega.
- intros; Simpl.
+ split; intros; Simpl.
- econstructor; split. eapply exec_straight_two.
apply SEM. apply SEM. Simpl. Simpl.
split. Simpl. rewrite ASSOC. do 2 f_equal. apply Int.eqm_samerepr.
rewrite E. auto with ints.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
Lemma exec_addimm32:
forall rd r1 n k rs m,
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (addimm32 rd r1 n k) rs m k rs' m
/\ rs'#rd = Val.add rs#r1 (Vint n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros. unfold addimm32. set (nn := Int.neg n).
destruct (Int.eq n (Int.zero_ext 24 n)); [| destruct (Int.eq nn (Int.zero_ext 24 nn))].
-- apply exec_addimm_aux_32 with (sem := Val.add). auto. intros; apply Val.add_assoc.
+- apply exec_addimm_aux_32 with (sem := Val.add); auto. intros; apply Val.add_assoc.
- rewrite <- Val.sub_opp_add.
- apply exec_addimm_aux_32 with (sem := Val.sub). auto.
+ apply exec_addimm_aux_32 with (sem := Val.sub); auto.
intros. rewrite ! Val.sub_add_opp, Val.add_assoc. rewrite Int.neg_add_distr. auto.
- destruct (Int.lt n Int.zero).
+ rewrite <- Val.sub_opp_add; fold nn.
- edestruct (exec_loadimm32 X16 nn) as (rs1 & A & B & C).
+ edestruct (exec_loadimm32 X16 nn) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A. eapply exec_straight_one. simpl; eauto. auto.
split. Simpl. rewrite B, C; eauto with asmgen.
- intros; Simpl.
-+ edestruct (exec_loadimm32 X16 n) as (rs1 & A & B & C).
+ split; intros; Simpl.
++ edestruct (exec_loadimm32 X16 n) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A. eapply exec_straight_one. simpl; eauto. auto.
split. Simpl. rewrite B, C; eauto with asmgen.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
Lemma exec_addimm_aux_64:
@@ -477,10 +560,12 @@ Lemma exec_addimm_aux_64:
Next (nextinstr (rs#rd <- (sem rs#r1 (Vlong (Int64.repr n))))) m) ->
(forall v n1 n2, sem (sem v (Vlong n1)) (Vlong n2) = sem v (Vlong (Int64.add n1 n2))) ->
forall rd r1 n k rs m,
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (addimm_aux insn rd r1 (Int64.unsigned n) k) rs m k rs' m
/\ rs'#rd = sem rs#r1 (Vlong n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros insn sem SEM ASSOC; intros. unfold addimm_aux.
set (nlo := Zzero_ext 12 (Int64.unsigned n)). set (nhi := Int64.unsigned n - nlo).
@@ -489,44 +574,46 @@ Proof.
destruct (Z.eqb_spec nhi 0); [|destruct (Z.eqb_spec nlo 0)].
- econstructor; split. apply exec_straight_one. apply SEM. Simpl.
split. Simpl. do 3 f_equal; omega.
- intros; Simpl.
+ split; intros; Simpl.
- econstructor; split. apply exec_straight_one. apply SEM. Simpl.
split. Simpl. do 3 f_equal; omega.
- intros; Simpl.
+ split; intros; Simpl.
- econstructor; split. eapply exec_straight_two.
apply SEM. apply SEM. Simpl. Simpl.
split. Simpl. rewrite ASSOC. do 2 f_equal. apply Int64.eqm_samerepr.
rewrite E. auto with ints.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
Lemma exec_addimm64:
forall rd r1 n k rs m,
preg_of_iregsp r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (addimm64 rd r1 n k) rs m k rs' m
/\ rs'#rd = Val.addl rs#r1 (Vlong n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros.
unfold addimm64. set (nn := Int64.neg n).
destruct (Int64.eq n (Int64.zero_ext 24 n)); [| destruct (Int64.eq nn (Int64.zero_ext 24 nn))].
-- apply exec_addimm_aux_64 with (sem := Val.addl). auto. intros; apply Val.addl_assoc.
+- apply exec_addimm_aux_64 with (sem := Val.addl); auto. intros; apply Val.addl_assoc.
- rewrite <- Val.subl_opp_addl.
- apply exec_addimm_aux_64 with (sem := Val.subl). auto.
+ apply exec_addimm_aux_64 with (sem := Val.subl); auto.
intros. rewrite ! Val.subl_addl_opp, Val.addl_assoc. rewrite Int64.neg_add_distr. auto.
- destruct (Int64.lt n Int64.zero).
+ rewrite <- Val.subl_opp_addl; fold nn.
- edestruct (exec_loadimm64 X16 nn) as (rs1 & A & B & C).
+ edestruct (exec_loadimm64 X16 nn) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A. eapply exec_straight_one. simpl; eauto. Simpl.
split. Simpl. rewrite B, C; eauto with asmgen. simpl. rewrite Int64.shl'_zero. auto.
- intros; Simpl.
-+ edestruct (exec_loadimm64 X16 n) as (rs1 & A & B & C).
+ split; intros; Simpl.
++ edestruct (exec_loadimm64 X16 n) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A. eapply exec_straight_one. simpl; eauto. Simpl.
split. Simpl. rewrite B, C; eauto with asmgen. simpl. rewrite Int64.shl'_zero. auto.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Logical immediate *)
@@ -543,22 +630,25 @@ Lemma exec_logicalimm32:
Next (nextinstr (rs#rd <- (sem rs##r1 (eval_shift_op_int rs#r2 s)))) m) ->
forall rd r1 n k rs m,
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (logicalimm32 insn1 insn2 rd r1 n k) rs m k rs' m
/\ rs'#rd = sem rs#r1 (Vint n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros until sem; intros SEM1 SEM2; intros. unfold logicalimm32.
destruct (is_logical_imm32 n).
- econstructor; split.
apply exec_straight_one. apply SEM1. reflexivity.
- split. Simpl. rewrite Int.repr_unsigned; auto. intros; Simpl.
-- edestruct (exec_loadimm32 X16 n) as (rs1 & A & B & C).
+ split. Simpl. rewrite Int.repr_unsigned; auto.
+ split; intros; Simpl.
+- edestruct (exec_loadimm32 X16 n) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. apply SEM2. reflexivity.
split. Simpl. f_equal; auto. apply C; auto with asmgen.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
Lemma exec_logicalimm64:
@@ -573,50 +663,58 @@ Lemma exec_logicalimm64:
Next (nextinstr (rs#rd <- (sem rs###r1 (eval_shift_op_long rs#r2 s)))) m) ->
forall rd r1 n k rs m,
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (logicalimm64 insn1 insn2 rd r1 n k) rs m k rs' m
/\ rs'#rd = sem rs#r1 (Vlong n)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros until sem; intros SEM1 SEM2; intros. unfold logicalimm64.
destruct (is_logical_imm64 n).
- econstructor; split.
apply exec_straight_one. apply SEM1. reflexivity.
- split. Simpl. rewrite Int64.repr_unsigned. auto. intros; Simpl.
-- edestruct (exec_loadimm64 X16 n) as (rs1 & A & B & C).
+ split. Simpl. rewrite Int64.repr_unsigned. auto.
+ split; intros; Simpl.
+- edestruct (exec_loadimm64 X16 n) as (rs1 & A & B & C). congruence.
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. apply SEM2. reflexivity.
split. Simpl. f_equal; auto. apply C; auto with asmgen.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Load address of symbol *)
Lemma exec_loadsymbol: forall rd s ofs k rs m,
- rd <> X16 \/ Archi.pic_code tt = false ->
+ rd <> X16 \/ Archi.pic_code tt = false ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (loadsymbol rd s ofs k) rs m k rs' m
/\ rs'#rd = Genv.symbol_address ge s ofs
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs'#RA = rs#RA.
Proof.
unfold loadsymbol; intros. destruct (Archi.pic_code tt).
- predSpec Ptrofs.eq Ptrofs.eq_spec ofs Ptrofs.zero.
+ subst ofs. econstructor; split.
apply exec_straight_one; [simpl; eauto | reflexivity].
- split. Simpl. intros; Simpl.
+ split. Simpl. split; intros; Simpl.
+
+ exploit exec_addimm64. instantiate (1 := rd). simpl. destruct H; congruence.
- intros (rs1 & A & B & C).
+ instantiate (1 := rd). assumption.
+ intros (rs1 & A & B & C & D).
econstructor; split.
econstructor. simpl; eauto. auto. eexact A.
split. simpl in B; rewrite B. Simpl.
rewrite <- Genv.shift_symbol_address_64 by auto.
rewrite Ptrofs.add_zero_l, Ptrofs.of_int64_to_int64 by auto. auto.
- intros. rewrite C by auto. Simpl.
+ split; intros. rewrite C by auto; Simpl.
+ rewrite D. Simpl.
- econstructor; split.
eapply exec_straight_two. simpl; eauto. simpl; eauto. auto. auto.
split. Simpl. rewrite symbol_high_low; auto.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Shifted operands *)
@@ -725,23 +823,25 @@ Lemma exec_arith_extended:
Next (nextinstr (rs#rd <- (sem rs###r1 (eval_shift_op_long rs#r2 s)))) m) ->
forall (rd r1 r2: ireg) (ex: extension) (a: amount64) (k: code) rs m,
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (arith_extended insnX insnS rd r1 r2 ex a k) rs m k rs' m
/\ rs'#rd = sem rs#r1 (Op.eval_extend ex rs#r2 a)
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros sem insnX insnS EX ES; intros. unfold arith_extended. destruct (Int.ltu a (Int.repr 5)).
- econstructor; split.
apply exec_straight_one. rewrite EX; eauto. auto.
split. Simpl. f_equal. destruct ex; auto.
- intros; Simpl.
+ split; intros; Simpl.
- exploit (exec_move_extended_base X16 r2 ex). intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one.
rewrite ES. eauto. auto.
split. Simpl. unfold ir0x. rewrite C by eauto with asmgen. f_equal.
rewrite B. destruct ex; auto.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Extended right shift *)
@@ -749,41 +849,73 @@ Qed.
Lemma exec_shrx32: forall (rd r1: ireg) (n: int) k v (rs: regset) m,
Val.shrx rs#r1 (Vint n) = Some v ->
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (shrx32 rd r1 n k) rs m k rs' m
/\ rs'#rd = v
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
- unfold shrx32; intros. apply Val.shrx_shr_2 in H.
+ unfold shrx32; intros. apply Val.shrx_shr_3 in H.
destruct (Int.eq n Int.zero) eqn:E.
- econstructor; split. apply exec_straight_one; [simpl;eauto|auto].
- split. Simpl. subst v; auto. intros; Simpl.
-- econstructor; split. eapply exec_straight_three.
- unfold exec_instr. rewrite or_zero_eval_shift_op_int by congruence. eauto.
- simpl; eauto.
- unfold exec_instr. rewrite or_zero_eval_shift_op_int by congruence. eauto.
- auto. auto. auto.
- split. subst v; Simpl. intros; Simpl.
+ split. Simpl. subst v; auto.
+ split; intros; Simpl.
+- generalize (Int.eq_spec n Int.one).
+ destruct (Int.eq n Int.one); intro ONE.
+ * subst n.
+ econstructor; split. eapply exec_straight_two.
+ all: simpl; auto.
+ split.
+ ** subst v; Simpl.
+ destruct (Val.add _ _); simpl; trivial.
+ change (Int.ltu Int.one Int.iwordsize) with true; simpl.
+ rewrite Int.or_zero_l.
+ reflexivity.
+ ** split; intros; Simpl.
+ * econstructor; split. eapply exec_straight_three.
+ unfold exec_instr. rewrite or_zero_eval_shift_op_int by congruence. eauto.
+ simpl; eauto.
+ unfold exec_instr. rewrite or_zero_eval_shift_op_int by congruence. eauto.
+ auto. auto. auto.
+ split. subst v; Simpl.
+ split; intros; Simpl.
Qed.
Lemma exec_shrx64: forall (rd r1: ireg) (n: int) k v (rs: regset) m,
Val.shrxl rs#r1 (Vint n) = Some v ->
r1 <> X16 ->
+ (IR RA) <> (preg_of_iregsp (RR1 rd)) ->
exists rs',
exec_straight ge fn (shrx64 rd r1 n k) rs m k rs' m
/\ rs'#rd = v
- /\ forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> r <> rd -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
- unfold shrx64; intros. apply Val.shrxl_shrl_2 in H.
+ unfold shrx64; intros. apply Val.shrxl_shrl_3 in H.
destruct (Int.eq n Int.zero) eqn:E.
- econstructor; split. apply exec_straight_one; [simpl;eauto|auto].
- split. Simpl. subst v; auto. intros; Simpl.
-- econstructor; split. eapply exec_straight_three.
- unfold exec_instr. rewrite or_zero_eval_shift_op_long by congruence. eauto.
- simpl; eauto.
- unfold exec_instr. rewrite or_zero_eval_shift_op_long by congruence. eauto.
- auto. auto. auto.
- split. subst v; Simpl. intros; Simpl.
+ split. Simpl. subst v; auto.
+ split; intros; Simpl.
+- generalize (Int.eq_spec n Int.one).
+ destruct (Int.eq n Int.one); intro ONE.
+ * subst n.
+ econstructor; split. eapply exec_straight_two.
+ all: simpl; auto.
+ split.
+ ** subst v; Simpl.
+ destruct (Val.addl _ _); simpl; trivial.
+ change (Int.ltu Int.one Int64.iwordsize') with true; simpl.
+ rewrite Int64.or_zero_l.
+ reflexivity.
+ ** split; intros; Simpl.
+ * econstructor; split. eapply exec_straight_three.
+ unfold exec_instr. rewrite or_zero_eval_shift_op_long by congruence. eauto.
+ simpl; eauto.
+ unfold exec_instr. rewrite or_zero_eval_shift_op_long by congruence. eauto.
+ auto. auto. auto.
+ split. subst v; Simpl.
+ split; intros; Simpl.
Qed.
(** Condition bits *)
@@ -1039,6 +1171,56 @@ Ltac ArgsInv :=
| [ H: freg_of _ = OK _ |- _ ] => simpl in *; rewrite (freg_of_eq _ _ H) in *
end).
+Lemma compare_int_RA:
+ forall rs a b m,
+ compare_int rs a b m X30 = rs X30.
+Proof.
+ unfold compare_int.
+ intros.
+ repeat rewrite Pregmap.gso by congruence.
+ trivial.
+Qed.
+
+Hint Resolve compare_int_RA : asmgen.
+
+Lemma compare_long_RA:
+ forall rs a b m,
+ compare_long rs a b m X30 = rs X30.
+Proof.
+ unfold compare_long.
+ intros.
+ repeat rewrite Pregmap.gso by congruence.
+ trivial.
+Qed.
+
+Hint Resolve compare_long_RA : asmgen.
+
+Lemma compare_float_RA:
+ forall rs a b,
+ compare_float rs a b X30 = rs X30.
+Proof.
+ unfold compare_float.
+ intros.
+ destruct a; destruct b.
+ all: repeat rewrite Pregmap.gso by congruence; trivial.
+Qed.
+
+Hint Resolve compare_float_RA : asmgen.
+
+
+Lemma compare_single_RA:
+ forall rs a b,
+ compare_single rs a b X30 = rs X30.
+Proof.
+ unfold compare_single.
+ intros.
+ destruct a; destruct b.
+ all: repeat rewrite Pregmap.gso by congruence; trivial.
+Qed.
+
+Hint Resolve compare_single_RA : asmgen.
+
+
Lemma transl_cond_correct:
forall cond args k c rs m,
transl_cond cond args k = OK c ->
@@ -1047,185 +1229,218 @@ Lemma transl_cond_correct:
/\ (forall b,
eval_condition cond (map rs (map preg_of args)) m = Some b ->
eval_testcond (cond_for_cond cond) rs' = Some b)
- /\ forall r, data_preg r = true -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros until m; intros TR. destruct cond; simpl in TR; ArgsInv.
- (* Ccomp *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. apply eval_testcond_compare_sint; auto.
+ repeat split; intros. apply eval_testcond_compare_sint; auto.
destruct r; reflexivity || discriminate.
- (* Ccompu *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. apply eval_testcond_compare_uint; auto.
+ repeat split; intros. apply eval_testcond_compare_uint; auto.
destruct r; reflexivity || discriminate.
- (* Ccompimm *)
destruct (is_arith_imm32 n); [|destruct (is_arith_imm32 (Int.neg n))].
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int.repr_unsigned. apply eval_testcond_compare_sint; auto.
+ repeat split; intros. rewrite Int.repr_unsigned. apply eval_testcond_compare_sint; auto.
destruct r; reflexivity || discriminate.
+ econstructor; split.
apply exec_straight_one. simpl. rewrite Int.repr_unsigned, Int.neg_involutive. eauto. auto.
- split; intros. apply eval_testcond_compare_sint; auto.
+ repeat split; intros. apply eval_testcond_compare_sint; auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm32 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm32 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one.
simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply eval_testcond_compare_sint; auto.
- transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ repeat split; intros. apply eval_testcond_compare_sint; auto.
+ transitivity (rs' r). destruct r; reflexivity || discriminate.
+ auto with asmgen.
+ Simpl. rewrite compare_int_RA.
+ apply C; congruence.
- (* Ccompuimm *)
destruct (is_arith_imm32 n); [|destruct (is_arith_imm32 (Int.neg n))].
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int.repr_unsigned. apply eval_testcond_compare_uint; auto.
+ repeat split; intros. rewrite Int.repr_unsigned. apply eval_testcond_compare_uint; auto.
destruct r; reflexivity || discriminate.
+ econstructor; split.
apply exec_straight_one. simpl. rewrite Int.repr_unsigned, Int.neg_involutive. eauto. auto.
- split; intros. apply eval_testcond_compare_uint; auto.
+ repeat split; intros. apply eval_testcond_compare_uint; auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm32 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm32 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one.
simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply eval_testcond_compare_uint; auto.
+ repeat split; intros. apply eval_testcond_compare_uint; auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_int_RA.
+ apply C; congruence.
- (* Ccompshift *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite transl_eval_shift. apply eval_testcond_compare_sint; auto.
+ repeat split; intros. rewrite transl_eval_shift. apply eval_testcond_compare_sint; auto.
destruct r; reflexivity || discriminate.
- (* Ccompushift *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite transl_eval_shift. apply eval_testcond_compare_uint; auto.
+ repeat split; intros. rewrite transl_eval_shift. apply eval_testcond_compare_uint; auto.
destruct r; reflexivity || discriminate.
- (* Cmaskzero *)
destruct (is_logical_imm32 n).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int.repr_unsigned. apply (eval_testcond_compare_sint Ceq); auto.
+ repeat split; intros. rewrite Int.repr_unsigned. apply (eval_testcond_compare_sint Ceq); auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm32 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm32 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply (eval_testcond_compare_sint Ceq); auto.
+ repeat split; intros. apply (eval_testcond_compare_sint Ceq); auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_int_RA.
+ apply C; congruence.
+
- (* Cmasknotzero *)
destruct (is_logical_imm32 n).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int.repr_unsigned. apply (eval_testcond_compare_sint Cne); auto.
+ repeat split; intros. rewrite Int.repr_unsigned. apply (eval_testcond_compare_sint Cne); auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm32 X16 n). intros (rs' & A & B & C).
+
++ exploit (exec_loadimm32 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply (eval_testcond_compare_sint Cne); auto.
+ repeat split; intros. apply (eval_testcond_compare_sint Cne); auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_int_RA.
+ apply C; congruence.
+
- (* Ccompl *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. apply eval_testcond_compare_slong; auto.
+ repeat split; intros. apply eval_testcond_compare_slong; auto.
destruct r; reflexivity || discriminate.
- (* Ccomplu *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. apply eval_testcond_compare_ulong; auto.
+ repeat split; intros. apply eval_testcond_compare_ulong; auto.
destruct r; reflexivity || discriminate.
- (* Ccomplimm *)
destruct (is_arith_imm64 n); [|destruct (is_arith_imm64 (Int64.neg n))].
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int64.repr_unsigned. apply eval_testcond_compare_slong; auto.
+ repeat split; intros. rewrite Int64.repr_unsigned. apply eval_testcond_compare_slong; auto.
destruct r; reflexivity || discriminate.
+ econstructor; split.
apply exec_straight_one. simpl. rewrite Int64.repr_unsigned, Int64.neg_involutive. eauto. auto.
- split; intros. apply eval_testcond_compare_slong; auto.
+ repeat split; intros. apply eval_testcond_compare_slong; auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm64 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one.
simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply eval_testcond_compare_slong; auto.
+ repeat split; intros. apply eval_testcond_compare_slong; auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_long_RA.
+ apply C; congruence.
+
- (* Ccompluimm *)
destruct (is_arith_imm64 n); [|destruct (is_arith_imm64 (Int64.neg n))].
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int64.repr_unsigned. apply eval_testcond_compare_ulong; auto.
+ repeat split; intros. rewrite Int64.repr_unsigned. apply eval_testcond_compare_ulong; auto.
destruct r; reflexivity || discriminate.
+ econstructor; split.
apply exec_straight_one. simpl. rewrite Int64.repr_unsigned, Int64.neg_involutive. eauto. auto.
- split; intros. apply eval_testcond_compare_ulong; auto.
+ repeat split; intros. apply eval_testcond_compare_ulong; auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm64 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one.
simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply eval_testcond_compare_ulong; auto.
+ repeat split; intros. apply eval_testcond_compare_ulong; auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_long_RA.
+ apply C; congruence.
+
- (* Ccomplshift *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite transl_eval_shiftl. apply eval_testcond_compare_slong; auto.
+ repeat split; intros. rewrite transl_eval_shiftl. apply eval_testcond_compare_slong; auto.
destruct r; reflexivity || discriminate.
- (* Ccomplushift *)
econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite transl_eval_shiftl. apply eval_testcond_compare_ulong; auto.
+ repeat split; intros. rewrite transl_eval_shiftl. apply eval_testcond_compare_ulong; auto.
destruct r; reflexivity || discriminate.
- (* Cmasklzero *)
destruct (is_logical_imm64 n).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int64.repr_unsigned. apply (eval_testcond_compare_slong Ceq); auto.
+ repeat split; intros. rewrite Int64.repr_unsigned. apply (eval_testcond_compare_slong Ceq); auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm64 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply (eval_testcond_compare_slong Ceq); auto.
+ repeat split; intros. apply (eval_testcond_compare_slong Ceq); auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_long_RA.
+ apply C; congruence.
+
- (* Cmasknotzero *)
destruct (is_logical_imm64 n).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split; intros. rewrite Int64.repr_unsigned. apply (eval_testcond_compare_slong Cne); auto.
+ repeat split; intros. rewrite Int64.repr_unsigned. apply (eval_testcond_compare_slong Cne); auto.
destruct r; reflexivity || discriminate.
-+ exploit (exec_loadimm64 X16 n). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 n). congruence. intros (rs' & A & B & C).
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. simpl. rewrite B, C by eauto with asmgen. eauto. auto.
- split; intros. apply (eval_testcond_compare_slong Cne); auto.
+ repeat split; intros. apply (eval_testcond_compare_slong Cne); auto.
transitivity (rs' r). destruct r; reflexivity || discriminate. auto with asmgen.
+ Simpl. rewrite compare_long_RA.
+ apply C; congruence.
+
- (* Ccompf *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_float_inv; auto.
- split; intros. apply eval_testcond_compare_float; auto.
+ repeat split; intros. apply eval_testcond_compare_float; auto.
destruct r; discriminate || rewrite compare_float_inv; auto.
+ Simpl.
- (* Cnotcompf *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_float_inv; auto.
- split; intros. apply eval_testcond_compare_not_float; auto.
+ repeat split; intros. apply eval_testcond_compare_not_float; auto.
destruct r; discriminate || rewrite compare_float_inv; auto.
+ Simpl.
- (* Ccompfzero *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_float_inv; auto.
- split; intros. apply eval_testcond_compare_float; auto.
+ repeat split; intros. apply eval_testcond_compare_float; auto.
destruct r; discriminate || rewrite compare_float_inv; auto.
+ Simpl.
- (* Cnotcompfzero *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_float_inv; auto.
- split; intros. apply eval_testcond_compare_not_float; auto.
+ repeat split; intros. apply eval_testcond_compare_not_float; auto.
destruct r; discriminate || rewrite compare_float_inv; auto.
+ Simpl.
- (* Ccompfs *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_single_inv; auto.
- split; intros. apply eval_testcond_compare_single; auto.
+ repeat split; intros. apply eval_testcond_compare_single; auto.
destruct r; discriminate || rewrite compare_single_inv; auto.
+ Simpl.
- (* Cnotcompfs *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_single_inv; auto.
- split; intros. apply eval_testcond_compare_not_single; auto.
+ repeat split; intros. apply eval_testcond_compare_not_single; auto.
destruct r; discriminate || rewrite compare_single_inv; auto.
+ Simpl.
- (* Ccompfszero *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_single_inv; auto.
- split; intros. apply eval_testcond_compare_single; auto.
+ repeat split; intros. apply eval_testcond_compare_single; auto.
destruct r; discriminate || rewrite compare_single_inv; auto.
+ Simpl.
- (* Cnotcompfszero *)
econstructor; split. apply exec_straight_one. simpl; eauto.
rewrite compare_single_inv; auto.
- split; intros. apply eval_testcond_compare_not_single; auto.
+ repeat split; intros. apply eval_testcond_compare_not_single; auto.
destruct r; discriminate || rewrite compare_single_inv; auto.
+ Simpl.
Qed.
(** Translation of conditional branches *)
@@ -1238,7 +1453,8 @@ Lemma transl_cond_branch_correct:
exec_straight_opt ge fn c rs m (insn :: k) rs' m
/\ exec_instr ge fn insn rs' m =
(if b then goto_label fn lbl rs' m else Next (nextinstr rs') m)
- /\ forall r, data_preg r = true -> rs'#r = rs#r.
+ /\ (forall r, data_preg r = true -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA.
Proof.
intros until b; intros TR EV.
assert (DFL:
@@ -1247,13 +1463,14 @@ Proof.
exec_straight_opt ge fn c rs m (insn :: k) rs' m
/\ exec_instr ge fn insn rs' m =
(if b then goto_label fn lbl rs' m else Next (nextinstr rs') m)
- /\ forall r, data_preg r = true -> rs'#r = rs#r).
+ /\ (forall r, data_preg r = true -> rs'#r = rs#r)
+ /\ rs' # RA = rs # RA ).
{
unfold transl_cond_branch_default; intros.
- exploit transl_cond_correct; eauto. intros (rs' & A & B & C).
+ exploit transl_cond_correct; eauto. intros (rs' & A & B & C & D).
exists rs', (Pbc (cond_for_cond cond) lbl); split.
apply exec_straight_opt_intro. eexact A.
- split; auto. simpl. rewrite (B b) by auto. auto.
+ repeat split; auto. simpl. rewrite (B b) by auto. auto.
}
Local Opaque transl_cond transl_cond_branch_default.
destruct args as [ | a1 args]; simpl in TR; auto.
@@ -1347,13 +1564,15 @@ Ltac TranslOpSimpl :=
[ apply exec_straight_one; [simpl; eauto | reflexivity]
| split; [ rewrite ? transl_eval_shift, ? transl_eval_shiftl;
apply Val.lessdef_same; Simpl; fail
- | intros; Simpl; fail ] ].
+ | split; [ intros; Simpl; fail
+ | intros; Simpl; eauto with asmgen; fail] ]].
Ltac TranslOpBase :=
econstructor; split;
[ apply exec_straight_one; [simpl; eauto | reflexivity]
| split; [ rewrite ? transl_eval_shift, ? transl_eval_shiftl; Simpl
- | intros; Simpl; fail ] ].
+ | split; [ intros; Simpl; fail
+ | intros; Simpl; eapply RA_not_written2; eauto] ]].
Lemma transl_op_correct:
forall op args res k (rs: regset) m v c,
@@ -1362,21 +1581,29 @@ Lemma transl_op_correct:
exists rs',
exec_straight ge fn c rs m k rs' m
/\ Val.lessdef v rs'#(preg_of res)
- /\ forall r, data_preg r = true -> r <> preg_of res -> preg_notin r (destroyed_by_op op) -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> r <> preg_of res -> preg_notin r (destroyed_by_op op) -> rs' r = rs r)
+ /\ rs' RA = rs RA.
Proof.
Local Opaque Int.eq Int64.eq Val.add Val.addl Int.zwordsize Int64.zwordsize.
intros until c; intros TR EV.
unfold transl_op in TR; destruct op; ArgsInv; simpl in EV; SimplEval EV; try TranslOpSimpl.
- (* move *)
destruct (preg_of res) eqn:RR; try discriminate; destruct (preg_of m0) eqn:R1; inv TR.
-+ TranslOpSimpl.
-+ TranslOpSimpl.
+ all: TranslOpSimpl.
- (* intconst *)
- exploit exec_loadimm32. intros (rs' & A & B & C).
- exists rs'; split. eexact A. split. rewrite B; auto. intros; auto with asmgen.
+ exploit exec_loadimm32. apply (ireg_of_not_RA res); eassumption.
+ intros (rs' & A & B & C).
+ exists rs'; split. eexact A. split. rewrite B; auto.
+ split. intros; auto with asmgen.
+ apply C. congruence.
+ eapply ireg_of_not_RA''; eauto.
- (* longconst *)
- exploit exec_loadimm64. intros (rs' & A & B & C).
- exists rs'; split. eexact A. split. rewrite B; auto. intros; auto with asmgen.
+ exploit exec_loadimm64. apply (ireg_of_not_RA res); eassumption.
+ intros (rs' & A & B & C).
+ exists rs'; split. eexact A. split. rewrite B; auto.
+ split. intros; auto with asmgen.
+ apply C. congruence.
+ eapply ireg_of_not_RA''; eauto.
- (* floatconst *)
destruct (Float.eq_dec n Float.zero).
+ subst n. TranslOpSimpl.
@@ -1386,11 +1613,15 @@ Local Opaque Int.eq Int64.eq Val.add Val.addl Int.zwordsize Int64.zwordsize.
+ subst n. TranslOpSimpl.
+ TranslOpSimpl.
- (* loadsymbol *)
- exploit (exec_loadsymbol x id ofs). eauto with asmgen. intros (rs' & A & B & C).
- exists rs'; split. eexact A. split. rewrite B; auto. auto.
+ exploit (exec_loadsymbol x id ofs). eauto with asmgen.
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ exists rs'; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* addrstack *)
exploit (exec_addimm64 x XSP (Ptrofs.to_int64 ofs)). simpl; eauto with asmgen.
- intros (rs' & A & B & C).
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. simpl in B; rewrite B.
Local Transparent Val.addl.
destruct (rs SP); simpl; auto. rewrite Ptrofs.of_int64_to_int64 by auto. auto.
@@ -1398,7 +1629,8 @@ Local Transparent Val.addl.
- (* shift *)
rewrite <- transl_eval_shift'. TranslOpSimpl.
- (* addimm *)
- exploit (exec_addimm32 x x0 n). eauto with asmgen. intros (rs' & A & B & C).
+ exploit (exec_addimm32 x x0 n). eauto with asmgen. eapply ireg_of_not_RA''; eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. rewrite B; auto. auto.
- (* mul *)
TranslOpBase.
@@ -1406,18 +1638,20 @@ Local Transparent Val.add.
destruct (rs x0); auto; destruct (rs x1); auto. simpl. rewrite Int.add_zero_l; auto.
- (* andimm *)
exploit (exec_logicalimm32 (Pandimm W) (Pand W)).
- intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
- exists rs'; split. eexact A. split. rewrite B; auto. auto.
+ intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen. apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ exists rs'; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* orimm *)
exploit (exec_logicalimm32 (Porrimm W) (Porr W)).
- intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
- exists rs'; split. eexact A. split. rewrite B; auto. auto.
+ intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen. apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ exists rs'; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* xorimm *)
exploit (exec_logicalimm32 (Peorimm W) (Peor W)).
- intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
+ intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen. apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. rewrite B; auto. auto.
- (* not *)
TranslOpBase.
@@ -1426,8 +1660,10 @@ Local Transparent Val.add.
TranslOpBase.
destruct (eval_shift s (rs x0) a); auto. simpl. rewrite Int.or_zero_l; auto.
- (* shrx *)
- exploit (exec_shrx32 x x0 n); eauto with asmgen. intros (rs' & A & B & C).
- econstructor; split. eexact A. split. rewrite B; auto. auto.
+ exploit (exec_shrx32 x x0 n); eauto with asmgen. apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ econstructor; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* zero-ext *)
TranslOpBase.
destruct (rs x0); auto; simpl. rewrite Int.shl_zero. auto.
@@ -1451,36 +1687,47 @@ Local Transparent Val.add.
- (* extend *)
exploit (exec_move_extended x0 x1 x a k). intros (rs' & A & B & C).
econstructor; split. eexact A.
- split. rewrite B; auto. eauto with asmgen.
+ split. rewrite B; auto.
+ split; eauto with asmgen.
- (* addext *)
exploit (exec_arith_extended Val.addl Paddext (Padd X)).
- auto. auto. instantiate (1 := x1). eauto with asmgen. intros (rs' & A & B & C).
- econstructor; split. eexact A. split. rewrite B; auto. auto.
+ auto. auto. instantiate (1 := x1). eauto with asmgen.
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ econstructor; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* addlimm *)
exploit (exec_addimm64 x x0 n). simpl. generalize (ireg_of_not_X16 _ _ EQ1). congruence.
- intros (rs' & A & B & C).
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. simpl in B; rewrite B; auto. auto.
- (* subext *)
exploit (exec_arith_extended Val.subl Psubext (Psub X)).
- auto. auto. instantiate (1 := x1). eauto with asmgen. intros (rs' & A & B & C).
- econstructor; split. eexact A. split. rewrite B; auto. auto.
+ auto. auto. instantiate (1 := x1). eauto with asmgen.
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
+ econstructor; split. eexact A. split. rewrite B; auto.
+ split; auto.
- (* mull *)
TranslOpBase.
destruct (rs x0); auto; destruct (rs x1); auto. simpl. rewrite Int64.add_zero_l; auto.
- (* andlimm *)
exploit (exec_logicalimm64 (Pandimm X) (Pand X)).
intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. rewrite B; auto. auto.
- (* orlimm *)
exploit (exec_logicalimm64 (Porrimm X) (Porr X)).
intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. rewrite B; auto. auto.
- (* xorlimm *)
exploit (exec_logicalimm64 (Peorimm X) (Peor X)).
intros; reflexivity. intros; reflexivity. instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
+ apply (ireg_of_not_RA'' res); eassumption.
+ intros (rs' & A & B & C & D).
exists rs'; split. eexact A. split. rewrite B; auto. auto.
- (* notl *)
TranslOpBase.
@@ -1489,7 +1736,8 @@ Local Transparent Val.add.
TranslOpBase.
destruct (eval_shiftl s (rs x0) a); auto. simpl. rewrite Int64.or_zero_l; auto.
- (* shrx *)
- exploit (exec_shrx64 x x0 n); eauto with asmgen. intros (rs' & A & B & C).
+ exploit (exec_shrx64 x x0 n); eauto with asmgen.
+ apply (ireg_of_not_RA'' res); eassumption. intros (rs' & A & B & C & D ).
econstructor; split. eexact A. split. rewrite B; auto. auto.
- (* zero-ext-l *)
TranslOpBase.
@@ -1510,35 +1758,37 @@ Local Transparent Val.add.
TranslOpBase.
destruct (rs x0); simpl; auto. rewrite ! a64_range; simpl. rewrite <- Int64.sign_ext_shr'_min; auto using a64_range.
- (* condition *)
- exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C).
+ exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C & D).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one. simpl; eauto. auto.
split. Simpl. destruct (eval_condition cond (map rs (map preg_of args)) m) as [b|]; simpl in *.
rewrite (B b) by auto. auto.
auto.
- intros; Simpl.
+ split; intros; Simpl.
- (* select *)
destruct (preg_of res) eqn:RES; monadInv TR.
+ (* integer *)
generalize (ireg_of_eq _ _ EQ) (ireg_of_eq _ _ EQ1); intros E1 E2; rewrite E1, E2.
- exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C).
+ exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C & D).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one. simpl; eauto. auto.
split. Simpl. destruct (eval_condition cond (map rs (map preg_of args)) m) as [b|]; simpl in *.
rewrite (B b) by auto. rewrite !C. apply Val.lessdef_normalize.
rewrite <- E2; auto with asmgen. rewrite <- E1; auto with asmgen.
auto.
- intros; Simpl.
+ split; intros; Simpl.
+ rewrite <- D.
+ eapply RA_not_written2; eassumption.
+ (* FP *)
generalize (freg_of_eq _ _ EQ) (freg_of_eq _ _ EQ1); intros E1 E2; rewrite E1, E2.
- exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C).
+ exploit (transl_cond_correct cond args); eauto. intros (rs' & A & B & C & D).
econstructor; split.
eapply exec_straight_trans. eexact A. apply exec_straight_one. simpl; eauto. auto.
split. Simpl. destruct (eval_condition cond (map rs (map preg_of args)) m) as [b|]; simpl in *.
rewrite (B b) by auto. rewrite !C. apply Val.lessdef_normalize.
rewrite <- E2; auto with asmgen. rewrite <- E1; auto with asmgen.
auto.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Translation of addressing modes, loads, stores *)
@@ -1550,7 +1800,8 @@ Lemma transl_addressing_correct:
exists ad rs',
exec_straight_opt ge fn c rs m (insn ad :: k) rs' m
/\ Asm.eval_addressing ge ad rs' = Vptr b o
- /\ forall r, data_preg r = true -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> rs' r = rs r)
+ /\ rs' # RA = rs # RA.
Proof.
intros until o; intros TR EV.
unfold transl_addressing in TR; destruct addr; ArgsInv; SimplEval EV.
@@ -1558,10 +1809,10 @@ Proof.
destruct (offset_representable sz ofs); inv EQ0.
+ econstructor; econstructor; split. apply exec_straight_opt_refl.
auto.
-+ exploit (exec_loadimm64 X16 ofs). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 ofs). congruence. intros (rs' & A & B & C).
econstructor; exists rs'; split. apply exec_straight_opt_intro; eexact A.
split. simpl. rewrite B, C by eauto with asmgen. auto.
- eauto with asmgen.
+ split; eauto with asmgen.
- (* Aindexed2 *)
econstructor; econstructor; split. apply exec_straight_opt_refl.
auto.
@@ -1577,33 +1828,38 @@ Proof.
+ econstructor; econstructor; split.
apply exec_straight_opt_intro. apply exec_straight_one. simpl; eauto. auto.
split. simpl. Simpl. rewrite H0. simpl. rewrite Ptrofs.add_zero. auto.
- intros; Simpl.
+ split; intros; Simpl.
- (* Aindexed2ext *)
destruct (Int.eq a Int.zero || Int.eq (Int.shl Int.one a) (Int.repr sz)); inv EQ2.
+ econstructor; econstructor; split. apply exec_straight_opt_refl.
split; auto. destruct x; auto.
+ exploit (exec_arith_extended Val.addl Paddext (Padd X)); auto.
instantiate (1 := x0). eauto with asmgen.
- intros (rs' & A & B & C).
+ instantiate (1 := X16). simpl. congruence.
+ intros (rs' & A & B & C & D).
econstructor; exists rs'; split.
apply exec_straight_opt_intro. eexact A.
split. simpl. rewrite B. rewrite Val.addl_assoc. f_equal.
unfold Op.eval_extend; destruct x, (rs x1); simpl; auto; rewrite ! a64_range;
simpl; rewrite Int64.add_zero; auto.
- intros. apply C; eauto with asmgen.
+ split; intros.
+ apply C; eauto with asmgen.
+ trivial.
- (* Aglobal *)
- destruct (Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero); inv TR.
+ destruct (Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero && symbol_is_aligned id sz); inv TR.
+ econstructor; econstructor; split.
apply exec_straight_opt_intro. apply exec_straight_one. simpl; eauto. auto.
split. simpl. Simpl. rewrite symbol_high_low. simpl in EV. congruence.
- intros; Simpl.
-+ exploit (exec_loadsymbol X16 id ofs). auto. intros (rs' & A & B & C).
+ split; intros; Simpl.
++ exploit (exec_loadsymbol X16 id ofs). auto.
+ simpl. congruence.
+ intros (rs' & A & B & C & D).
econstructor; exists rs'; split.
apply exec_straight_opt_intro. eexact A.
split. simpl.
rewrite B. rewrite <- Genv.shift_symbol_address_64, Ptrofs.add_zero by auto.
simpl in EV. congruence.
- auto with asmgen.
+ split; auto with asmgen.
- (* Ainstrack *)
assert (E: Val.addl (rs SP) (Vlong (Ptrofs.to_int64 ofs)) = Vptr b o).
{ simpl in EV. inv EV. destruct (rs SP); simpl in H1; inv H1. simpl.
@@ -1611,7 +1867,9 @@ Proof.
destruct (offset_representable sz (Ptrofs.to_int64 ofs)); inv TR.
+ econstructor; econstructor; split. apply exec_straight_opt_refl.
auto.
-+ exploit (exec_loadimm64 X16 (Ptrofs.to_int64 ofs)). intros (rs' & A & B & C).
++ exploit (exec_loadimm64 X16 (Ptrofs.to_int64 ofs)).
+ simpl. congruence.
+ intros (rs' & A & B & C).
econstructor; exists rs'; split.
apply exec_straight_opt_intro. eexact A.
split. simpl. rewrite B, C by eauto with asmgen. auto.
@@ -1620,13 +1878,14 @@ Qed.
Lemma transl_load_correct:
forall chunk addr args dst k c (rs: regset) m vaddr v,
- transl_load chunk addr args dst k = OK c ->
+ transl_load TRAP chunk addr args dst k = OK c ->
Op.eval_addressing ge (rs#SP) addr (map rs (map preg_of args)) = Some vaddr ->
Mem.loadv chunk m vaddr = Some v ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
- /\ forall r, data_preg r = true -> r <> preg_of dst -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> r <> preg_of dst -> rs' r = rs r)
+ /\ rs' # RA = rs # RA.
Proof.
intros. destruct vaddr; try discriminate.
assert (A: exists sz insn,
@@ -1639,14 +1898,17 @@ Proof.
do 2 econstructor; (split; [eassumption|auto]).
}
destruct A as (sz & insn & B & C).
- exploit transl_addressing_correct. eexact B. eexact H0. intros (ad & rs' & P & Q & R).
+ exploit transl_addressing_correct. eexact B. eexact H0. intros (ad & rs' & P & Q & R & S).
assert (X: exec_load ge chunk (fun v => v) ad (preg_of dst) rs' m =
Next (nextinstr (rs'#(preg_of dst) <- v)) m).
{ unfold exec_load. rewrite Q, H1. auto. }
econstructor; split.
eapply exec_straight_opt_right. eexact P.
apply exec_straight_one. rewrite C, X; eauto. Simpl.
- split. Simpl. intros; Simpl.
+ split. Simpl.
+ split; intros; Simpl.
+ rewrite <- S.
+ apply RA_not_written.
Qed.
Lemma transl_store_correct:
@@ -1656,7 +1918,8 @@ Lemma transl_store_correct:
Mem.storev chunk m vaddr rs#(preg_of src) = Some m' ->
exists rs',
exec_straight ge fn c rs m k rs' m'
- /\ forall r, data_preg r = true -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> rs' r = rs r)
+ /\ rs' # RA = rs # RA.
Proof.
intros. destruct vaddr; try discriminate.
set (chunk' := match chunk with Mint8signed => Mint8unsigned
@@ -1672,7 +1935,7 @@ Proof.
do 2 econstructor; (split; [eassumption|auto]).
}
destruct A as (sz & insn & B & C).
- exploit transl_addressing_correct. eexact B. eexact H0. intros (ad & rs' & P & Q & R).
+ exploit transl_addressing_correct. eexact B. eexact H0. intros (ad & rs' & P & Q & R & S).
assert (X: Mem.storev chunk' m (Vptr b i) rs#(preg_of src) = Some m').
{ rewrite <- H1. unfold chunk'. destruct chunk; auto; simpl; symmetry.
apply Mem.store_signed_unsigned_8.
@@ -1683,7 +1946,7 @@ Proof.
econstructor; split.
eapply exec_straight_opt_right. eexact P.
apply exec_straight_one. rewrite C, Y; eauto. Simpl.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
(** Translation of indexed memory accesses *)
@@ -1701,7 +1964,9 @@ Proof.
{ destruct (rs base); try discriminate. simpl in *. rewrite Ptrofs.of_int64_to_int64 by auto. auto. }
destruct offset_representable.
- econstructor; econstructor; split. apply exec_straight_opt_refl. auto.
-- exploit (exec_loadimm64 X16); eauto. intros (rs' & A & B & C).
+- exploit (exec_loadimm64 X16); eauto.
+ simpl. congruence.
+ intros (rs' & A & B & C).
econstructor; econstructor; split. apply exec_straight_opt_intro; eexact A.
split. simpl. rewrite B, C by eauto with asmgen. auto. auto.
Qed.
@@ -1712,7 +1977,7 @@ Lemma loadptr_correct: forall (base: iregsp) ofs dst k m v (rs: regset),
exists rs',
exec_straight ge fn (loadptr base ofs dst k) rs m k rs' m
/\ rs'#dst = v
- /\ forall r, r <> PC -> r <> X16 -> r <> dst -> rs' r = rs r.
+ /\ (forall r, r <> PC -> r <> X16 -> r <> dst -> rs' r = rs r).
Proof.
intros.
destruct (Val.offset_ptr rs#base ofs) eqn:V; try discriminate.
@@ -1720,7 +1985,8 @@ Proof.
econstructor; split.
eapply exec_straight_opt_right. eexact A.
apply exec_straight_one. simpl. unfold exec_load. rewrite B, H. eauto. auto.
- split. Simpl. intros; Simpl.
+ split. Simpl.
+ intros; Simpl.
Qed.
Lemma storeptr_correct: forall (base: iregsp) ofs (src: ireg) k m m' (rs: regset),
@@ -1729,7 +1995,8 @@ Lemma storeptr_correct: forall (base: iregsp) ofs (src: ireg) k m m' (rs: regset
src <> X16 ->
exists rs',
exec_straight ge fn (storeptr src base ofs k) rs m k rs' m'
- /\ forall r, r <> PC -> r <> X16 -> rs' r = rs r.
+ /\ (forall r, r <> PC -> r <> X16 -> rs' r = rs r)
+ /\ rs' RA = rs RA.
Proof.
intros.
destruct (Val.offset_ptr rs#base ofs) eqn:V; try discriminate.
@@ -1737,7 +2004,7 @@ Proof.
econstructor; split.
eapply exec_straight_opt_right. eexact A.
apply exec_straight_one. simpl. unfold exec_store. rewrite B, C, H by eauto with asmgen. eauto. auto.
- intros; Simpl.
+ split; intros; Simpl.
Qed.
Lemma loadind_correct: forall (base: iregsp) ofs ty dst k c (rs: regset) m v,
@@ -1747,7 +2014,8 @@ Lemma loadind_correct: forall (base: iregsp) ofs ty dst k c (rs: regset) m v,
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
- /\ forall r, data_preg r = true -> r <> preg_of dst -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> r <> preg_of dst -> rs' r = rs r)
+ /\ rs' RA = rs RA.
Proof.
intros.
destruct (Val.offset_ptr rs#base ofs) eqn:V; try discriminate.
@@ -1763,7 +2031,10 @@ Proof.
econstructor; split.
eapply exec_straight_opt_right. eexact A.
apply exec_straight_one. rewrite SEM. unfold exec_load. rewrite B, H0. eauto. Simpl.
- split. Simpl. intros; Simpl.
+ split. Simpl.
+ split. intros; Simpl.
+ Simpl. rewrite RA_not_written.
+ apply C; congruence.
Qed.
Lemma storeind_correct: forall (base: iregsp) ofs ty src k c (rs: regset) m m',
@@ -1772,7 +2043,8 @@ Lemma storeind_correct: forall (base: iregsp) ofs ty src k c (rs: regset) m m',
preg_of_iregsp base <> IR X16 ->
exists rs',
exec_straight ge fn c rs m k rs' m'
- /\ forall r, data_preg r = true -> rs' r = rs r.
+ /\ (forall r, data_preg r = true -> rs' r = rs r)
+ /\ rs' RA = rs RA.
Proof.
intros.
destruct (Val.offset_ptr rs#base ofs) eqn:V; try discriminate.
@@ -1790,13 +2062,15 @@ Proof.
apply exec_straight_one. rewrite SEM.
unfold exec_store. rewrite B, C, H0 by eauto with asmgen. eauto.
Simpl.
- intros; Simpl.
+ split. intros; Simpl.
+ Simpl.
Qed.
Lemma make_epilogue_correct:
forall ge0 f m stk soff cs m' ms rs k tm,
+ (is_leaf_function f = true -> rs # (IR RA) = parent_ra cs) ->
load_stack m (Vptr stk soff) Tptr f.(fn_link_ofs) = Some (parent_sp cs) ->
- load_stack m (Vptr stk soff) Tptr f.(fn_retaddr_ofs) = Some (parent_ra cs) ->
+ ((* FIXME is_leaf_function f = false -> *) load_stack m (Vptr stk soff) Tptr f.(fn_retaddr_ofs) = Some (parent_ra cs)) ->
Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
agree ms (Vptr stk soff) rs ->
Mem.extends m tm ->
@@ -1807,18 +2081,46 @@ Lemma make_epilogue_correct:
/\ Mem.extends m' tm'
/\ rs'#RA = parent_ra cs
/\ rs'#SP = parent_sp cs
- /\ (forall r, r <> PC -> r <> SP -> r <> X30 -> r <> X16 -> rs'#r = rs#r).
+ /\ (forall r, r <> PC -> r <> SP -> r <> RA -> r <> X16 -> rs'#r = rs#r).
Proof.
- intros until tm; intros LP LRA FREE AG MEXT MCS.
+ intros until tm; intros LEAF_RA LP LRA FREE AG MEXT MCS.
+
+ (* FIXME
+ Cannot be used at this point
+ destruct (is_leaf_function f) eqn:IS_LEAF.
+ {
+ exploit Mem.loadv_extends. eauto. eexact LP. auto. simpl. intros (parent' & LP' & LDP').
+ exploit lessdef_parent_sp; eauto. intros EQ; subst parent'; clear LDP'.
+ exploit Mem.free_parallel_extends; eauto. intros (tm' & FREE' & MEXT').
+ unfold make_epilogue.
+ rewrite IS_LEAF.
+
+ econstructor; econstructor; split.
+ apply exec_straight_one. simpl.
+ rewrite <- (sp_val _ _ _ AG). simpl; rewrite LP'.
+ rewrite FREE'. eauto. auto.
+ split. apply agree_nextinstr. apply agree_set_other; auto.
+ apply agree_change_sp with (Vptr stk soff).
+ apply agree_exten with rs; auto.
+ eapply parent_sp_def; eauto.
+ split. auto.
+ split. Simpl.
+ split. Simpl.
+ intros. Simpl.
+ }
+ lapply LRA. 2: reflexivity.
+ clear LRA. intro LRA. *)
exploit Mem.loadv_extends. eauto. eexact LP. auto. simpl. intros (parent' & LP' & LDP').
exploit Mem.loadv_extends. eauto. eexact LRA. auto. simpl. intros (ra' & LRA' & LDRA').
exploit lessdef_parent_sp; eauto. intros EQ; subst parent'; clear LDP'.
exploit lessdef_parent_ra; eauto. intros EQ; subst ra'; clear LDRA'.
exploit Mem.free_parallel_extends; eauto. intros (tm' & FREE' & MEXT').
- unfold make_epilogue.
+ unfold make_epilogue.
+ (* FIXME rewrite IS_LEAF. *)
exploit (loadptr_correct XSP (fn_retaddr_ofs f)).
instantiate (2 := rs). simpl. rewrite <- (sp_val _ _ _ AG). simpl. eexact LRA'. simpl; congruence.
intros (rs1 & A1 & B1 & C1).
+
econstructor; econstructor; split.
eapply exec_straight_trans. eexact A1. apply exec_straight_one. simpl.
simpl; rewrite (C1 SP) by auto with asmgen. rewrite <- (sp_val _ _ _ AG). simpl; rewrite LP'.
@@ -1833,4 +2135,4 @@ Proof.
intros. Simpl.
Qed.
-End CONSTRUCTORS. \ No newline at end of file
+End CONSTRUCTORS.
diff --git a/aarch64/Builtins1.v b/aarch64/Builtins1.v
index f6e643d2..53c83d7e 100644
--- a/aarch64/Builtins1.v
+++ b/aarch64/Builtins1.v
@@ -29,5 +29,5 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with end.
diff --git a/aarch64/CSE2deps.v b/aarch64/CSE2deps.v
new file mode 100644
index 00000000..90b514a2
--- /dev/null
+++ b/aarch64/CSE2deps.v
@@ -0,0 +1,20 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs (Int64.unsigned ofs') chunk' (Int64.unsigned ofs) chunk)
+ else true | _, _, _, _ => true
+ end.
diff --git a/aarch64/CSE2depsproof.v b/aarch64/CSE2depsproof.v
new file mode 100644
index 00000000..4aac23af
--- /dev/null
+++ b/aarch64/CSE2depsproof.v
@@ -0,0 +1,128 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Lemma ptrofs_size :
+ Ptrofs.wordsize = 64%nat.
+Proof.
+ unfold Ptrofs.wordsize.
+ unfold Wordsize_Ptrofs.wordsize.
+ trivial.
+Qed.
+
+Lemma ptrofs_modulus :
+ Ptrofs.modulus = 18446744073709551616.
+Proof.
+ reflexivity.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : int64.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= Int64.unsigned ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= Int64.unsigned ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : Int64.unsigned ofsw + size_chunk chunkw <= Int64.unsigned ofsr
+ \/ Int64.unsigned ofsr + size_chunk chunkr <= Int64.unsigned ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in *.
+
+ rewrite ptrofs_modulus in *.
+ simpl in *.
+ inv ADDRR.
+ inv ADDRW.
+
+ destruct base; try discriminate.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: unfold Ptrofs.of_int64.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.repr (Int64.unsigned ofsr))) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.repr (Int64.unsigned ofsw))) as [OFSW | OFSW];
+ rewrite OFSW).
+ all: repeat rewrite Ptrofs.unsigned_repr by (change Ptrofs.max_unsigned with 18446744073709551615; lia).
+
+ all: try rewrite ptrofs_modulus in *.
+
+ all: intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs (Int64.unsigned ofsr) chunkr (Int64.unsigned ofsw) chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs (Int64.unsigned ofs0) chunk' (Int64.unsigned ofs) chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away with (F:=F) (V:=V) (genv:=genv) (sp:=sp); eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/aarch64/Conventions1.v b/aarch64/Conventions1.v
index 5914e8f2..efda835d 100644
--- a/aarch64/Conventions1.v
+++ b/aarch64/Conventions1.v
@@ -102,10 +102,9 @@ Definition is_float_reg (r: mreg): bool :=
with one integer result. *)
Definition loc_result (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R0
- | Some (Tint | Tlong | Tany32 | Tany64) => One R0
- | Some (Tfloat | Tsingle) => One F0
+ match proj_sig_res s with
+ | Tint | Tlong | Tany32 | Tany64 => One R0
+ | Tfloat | Tsingle => One F0
end.
(** The result registers have types compatible with that given in the signature. *)
@@ -114,7 +113,7 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result. destruct (sig_res sig) as [[]|]; auto.
+ intros. unfold loc_result. destruct (proj_sig_res sig); auto.
Qed.
(** The result locations are caller-save registers *)
@@ -124,7 +123,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros.
- unfold loc_result. destruct (sig_res s) as [[]|]; simpl; auto.
+ unfold loc_result. destruct (proj_sig_res s); simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -134,12 +133,12 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
- intros; unfold loc_result; destruct (sig_res sg) as [[]|]; exact I.
+ intros; unfold loc_result; destruct (proj_sig_res sg); exact I.
Qed.
(** The location of the result depends only on the result part of the signature *)
@@ -147,7 +146,7 @@ Qed.
Lemma loc_result_exten:
forall s1 s2, s1.(sig_res) = s2.(sig_res) -> loc_result s1 = loc_result s2.
Proof.
- intros. unfold loc_result. rewrite H; auto.
+ intros. unfold loc_result, proj_sig_res. rewrite H; auto.
Qed.
(** ** Location of function arguments *)
@@ -191,27 +190,6 @@ Fixpoint loc_arguments_rec
Definition loc_arguments (s: signature) : list (rpair loc) :=
loc_arguments_rec s.(sig_args) 0 0 0.
-(** [size_arguments s] returns the number of [Outgoing] slots used
- to call a function with signature [s]. *)
-
-Fixpoint size_arguments_rec (tyl: list typ) (ir fr ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => ofs
- | (Tint | Tlong | Tany32 | Tany64) :: tys =>
- match list_nth_z int_param_regs ir with
- | None => size_arguments_rec tys ir fr (ofs + 2)
- | Some ireg => size_arguments_rec tys (ir + 1) fr ofs
- end
- | (Tfloat | Tsingle) :: tys =>
- match list_nth_z float_param_regs fr with
- | None => size_arguments_rec tys ir fr (ofs + 2)
- | Some freg => size_arguments_rec tys ir (fr + 1) ofs
- end
- end.
-
-Definition size_arguments (s: signature) : Z :=
- size_arguments_rec s.(sig_args) 0 0 0.
-
(** Argument locations are either caller-save registers or [Outgoing]
stack slots at nonnegative offsets. *)
@@ -286,95 +264,22 @@ Qed.
Hint Resolve loc_arguments_acceptable: locs.
-(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
-
-Remark size_arguments_rec_above:
- forall tyl ir fr ofs0,
- ofs0 <= size_arguments_rec tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- omega.
- assert (A: ofs0 <=
- match list_nth_z int_param_regs ir with
- | Some _ => size_arguments_rec tyl (ir + 1) fr ofs0
- | None => size_arguments_rec tyl ir fr (ofs0 + 2)
- end).
- { destruct (list_nth_z int_param_regs ir); eauto.
- apply Z.le_trans with (ofs0 + 2); auto. omega. }
- assert (B: ofs0 <=
- match list_nth_z float_param_regs fr with
- | Some _ => size_arguments_rec tyl ir (fr + 1) ofs0
- | None => size_arguments_rec tyl ir fr (ofs0 + 2)
- end).
- { destruct (list_nth_z float_param_regs fr); eauto.
- apply Z.le_trans with (ofs0 + 2); auto. omega. }
- destruct a; auto.
-Qed.
-
-Lemma size_arguments_above:
- forall s, size_arguments s >= 0.
-Proof.
- intros; unfold size_arguments. apply Z.le_ge. apply size_arguments_rec_above.
-Qed.
-
-Lemma loc_arguments_rec_bounded:
- forall ofs ty tyl ir fr ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_rec tyl ir fr ofs0)) ->
- ofs + typesize ty <= size_arguments_rec tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
-- contradiction.
-- assert (T: forall ty0, typesize ty0 <= 2).
- { destruct ty0; simpl; omega. }
- assert (A: forall ty0,
- In (S Outgoing ofs ty) (regs_of_rpairs
- match list_nth_z int_param_regs ir with
- | Some ireg =>
- One (R ireg) :: loc_arguments_rec tyl (ir + 1) fr ofs0
- | None => One (S Outgoing ofs0 ty0) :: loc_arguments_rec tyl ir fr (ofs0 + 2)
- end) ->
- ofs + typesize ty <=
- match list_nth_z int_param_regs ir with
- | Some _ => size_arguments_rec tyl (ir + 1) fr ofs0
- | None => size_arguments_rec tyl ir fr (ofs0 + 2)
- end).
- { intros. destruct (list_nth_z int_param_regs ir); simpl in H0; destruct H0.
- - discriminate.
- - eapply IHtyl; eauto.
- - inv H0. apply Z.le_trans with (ofs + 2). specialize (T ty). omega. apply size_arguments_rec_above.
- - eapply IHtyl; eauto. }
- assert (B: forall ty0,
- In (S Outgoing ofs ty) (regs_of_rpairs
- match list_nth_z float_param_regs fr with
- | Some ireg =>
- One (R ireg) :: loc_arguments_rec tyl ir (fr + 1) ofs0
- | None => One (S Outgoing ofs0 ty0) :: loc_arguments_rec tyl ir fr (ofs0 + 2)
- end) ->
- ofs + typesize ty <=
- match list_nth_z float_param_regs fr with
- | Some _ => size_arguments_rec tyl ir (fr + 1) ofs0
- | None => size_arguments_rec tyl ir fr (ofs0 + 2)
- end).
- { intros. destruct (list_nth_z float_param_regs fr); simpl in H0; destruct H0.
- - discriminate.
- - eapply IHtyl; eauto.
- - inv H0. apply Z.le_trans with (ofs + 2). specialize (T ty). omega. apply size_arguments_rec_above.
- - eapply IHtyl; eauto. }
- destruct a; eauto.
-Qed.
-
-Lemma loc_arguments_bounded:
- forall (s: signature) (ofs: Z) (ty: typ),
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
- ofs + typesize ty <= size_arguments s.
-Proof.
- unfold loc_arguments, size_arguments; intros.
- eauto using loc_arguments_rec_bounded.
-Qed.
-
Lemma loc_arguments_main:
loc_arguments signature_main = nil.
Proof.
unfold loc_arguments; reflexivity.
Qed.
+(** ** Normalization of function results *)
+
+(** According to the AAPCS64 ABI specification, "padding bits" in the return
+ value of a function have unpredictable values and must be ignored.
+ Consequently, we force normalization of return values of small integer
+ types (8- and 16-bit integers), so that the top bits (the "padding bits")
+ are proper sign- or zero-extensions of the small integer value. *)
+
+Definition return_value_needs_normalization (t: rettype) : bool :=
+ match t with
+ | Tint8signed | Tint8unsigned | Tint16signed | Tint16unsigned => true
+ | _ => false
+ end.
diff --git a/aarch64/DuplicateOpcodeHeuristic.ml b/aarch64/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..5fc2156c
--- /dev/null
+++ b/aarch64/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,27 @@
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccomplimm (c, n) | Ccompluimm (c, n) -> if n == Integers.Int64.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c | Ccompfs c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c | Cnotcompfs c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
+
diff --git a/aarch64/Op.v b/aarch64/Op.v
index a7483d56..c0b9d435 100644
--- a/aarch64/Op.v
+++ b/aarch64/Op.v
@@ -921,6 +921,36 @@ Proof with (try exact I; try reflexivity; auto using Val.Vptr_has_type).
- unfold Val.select. destruct (eval_condition cond vl m). apply Val.normalize_type. exact I.
Qed.
+
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivu | Odivl | Odivlu
+ | Oshrximm _ | Oshrlximm _
+ | Ointoffloat | Ointuoffloat
+ | Ointofsingle | Ointuofsingle
+ | Ofloatofint | Ofloatofintu
+ | Osingleofint | Osingleofintu
+ | Olongoffloat | Olonguoffloat
+ | Olongofsingle | Olonguofsingle
+ | Ofloatoflong | Ofloatoflongu
+ | Osingleoflong | Osingleoflongu => true
+ | _ => false
+ end.
+
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -1576,6 +1606,21 @@ Proof.
- apply Val.offset_ptr_inject; auto.
Qed.
+
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *;
+ inv Hinjvl; trivial; try discriminate; inv H0; trivial; try discriminate; inv H2; trivial; try discriminate.
+Qed.
End EVAL_COMPAT.
(** Compatibility of the evaluation functions with the ``is less defined'' relation over values. *)
@@ -1682,6 +1727,18 @@ Proof.
destruct H1 as [v2 [A B]]. exists v2; split; auto. rewrite val_inject_lessdef; auto.
Qed.
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros. rewrite val_inject_list_lessdef in H.
+ eapply eval_addressing_inj_none with (sp1 := sp).
+ intros. rewrite <- val_inject_lessdef; auto.
+ rewrite <- val_inject_lessdef; auto.
+ eauto. auto.
+Qed.
End EVAL_LESSDEF.
(** Compatibility of the evaluation functions with memory injections. *)
@@ -1734,6 +1791,19 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/aarch64/extractionMachdep.v b/aarch64/extractionMachdep.v
index a447d12f..e82056e2 100644
--- a/aarch64/extractionMachdep.v
+++ b/aarch64/extractionMachdep.v
@@ -21,3 +21,4 @@ Extract Constant Archi.pic_code => "fun () -> false". (* for the time being *)
(* Asm *)
Extract Constant Asm.symbol_low => "fun _ _ _ -> assert false".
Extract Constant Asm.symbol_high => "fun _ _ _ -> assert false".
+Extract Constant Asmgen.symbol_is_aligned => "C2C.atom_is_aligned".
diff --git a/arm/Asmgen.v b/arm/Asmgen.v
index 1a1e7f2f..f428feea 100644
--- a/arm/Asmgen.v
+++ b/arm/Asmgen.v
@@ -481,6 +481,9 @@ Definition transl_op
do r <- ireg_of res; do r1 <- ireg_of a1;
if Int.eq n Int.zero then
OK (Pmov r (SOreg r1) :: k)
+ else if Int.eq n Int.one then
+ OK (Padd IR14 r1 (SOlsr r1 (Int.repr 31)) ::
+ Pmov r (SOasr IR14 n) :: k)
else
OK (Pmov IR14 (SOasr r1 (Int.repr 31)) ::
Padd IR14 r1 (SOlsr IR14 (Int.sub Int.iwordsize n)) ::
@@ -689,8 +692,12 @@ Definition transl_memory_access_float
None
mk_immed addr args k.
-Definition transl_load (chunk: memory_chunk) (addr: addressing)
- (args: list mreg) (dst: mreg) (k: code) :=
+Definition transl_load (trap : trapping_mode)
+ (chunk: memory_chunk) (addr: addressing)
+ (args: list mreg) (dst: mreg) (k: code) :=
+ match trap with
+ | NOTRAP => Error (msg "Asmgen.transl_load non-trapping loads unsupported on Arm")
+ | TRAP =>
match chunk with
| Mint8signed =>
transl_memory_access_int Pldrsb mk_immed_mem_small dst addr args k
@@ -708,6 +715,7 @@ Definition transl_load (chunk: memory_chunk) (addr: addressing)
transl_memory_access_float Pfldd mk_immed_mem_float dst addr args k
| _ =>
Error (msg "Asmgen.transl_load")
+ end
end.
Definition transl_store (chunk: memory_chunk) (addr: addressing)
@@ -747,8 +755,8 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
else loadind_int IR13 f.(fn_link_ofs) IR12 c)
| Mop op args res =>
transl_op op args res k
- | Mload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | Mload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| Mstore chunk addr args src =>
transl_store chunk addr args src k
| Mcall sig (inl arg) =>
diff --git a/arm/Asmgenproof.v b/arm/Asmgenproof.v
index 25f91d23..92ae524f 100644
--- a/arm/Asmgenproof.v
+++ b/arm/Asmgenproof.v
@@ -303,6 +303,7 @@ Proof.
eapply tail_nolabel_trans. 2: eapply loadind_label; eauto. unfold loadind_int; TailNoLabel.
eapply transl_op_label; eauto.
unfold transl_load, transl_memory_access_int, transl_memory_access_float in H.
+ destruct t; try discriminate.
destruct m; monadInv H; eapply transl_memory_access_label; eauto; simpl; auto.
unfold transl_store, transl_memory_access_int, transl_memory_access_float in H.
destruct m; monadInv H; eapply transl_memory_access_label; eauto; simpl; auto.
@@ -618,6 +619,12 @@ Opaque loadind.
split. eapply agree_set_undef_mreg; eauto. congruence.
simpl; congruence.
+- (* Mload notrap1 *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
- (* Mstore *)
assert (eval_addressing tge sp addr rs##args = Some a).
rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
diff --git a/arm/Asmgenproof1.v b/arm/Asmgenproof1.v
index 807e069d..cdac697e 100644
--- a/arm/Asmgenproof1.v
+++ b/arm/Asmgenproof1.v
@@ -1264,15 +1264,32 @@ Local Transparent destroyed_by_op.
destruct (rs x0) eqn: X0; simpl in H0; try discriminate.
destruct (Int.ltu i (Int.repr 31)) eqn: LTU; inv H0.
revert EQ2. predSpec Int.eq Int.eq_spec i Int.zero; intros EQ2.
+ {
(* i = 0 *)
inv EQ2. econstructor.
split. apply exec_straight_one. simpl. reflexivity. auto.
split. Simpl. unfold Int.shrx. rewrite Int.shl_zero. unfold Int.divs.
change (Int.signed Int.one) with 1. rewrite Z.quot_1_r. rewrite Int.repr_signed. auto.
intros. Simpl.
- (* i <> 0 *)
- inv EQ2.
- assert (LTU': Int.ltu (Int.sub Int.iwordsize i) Int.iwordsize = true).
+ }
+ { (* i <> 0 *)
+ revert EQ2. predSpec Int.eq Int.eq_spec i Int.one; intros EQ2.
+ {
+ inv EQ2.
+ econstructor; split.
+ eapply exec_straight_two; simpl; reflexivity.
+ split.
+ { rewrite X0.
+ rewrite Int.shrx1_shr by reflexivity.
+ Simpl.
+ }
+ { intros.
+ Simpl.
+ }
+ }
+ clear H0.
+ inv EQ2.
+ assert (LTU': Int.ltu (Int.sub Int.iwordsize i) Int.iwordsize = true).
{
generalize (Int.ltu_inv _ _ LTU). intros.
unfold Int.sub, Int.ltu. rewrite Int.unsigned_repr_wordsize.
@@ -1306,6 +1323,7 @@ Local Transparent destroyed_by_op.
rewrite LTU'; simpl. rewrite LTU''; simpl.
f_equal. symmetry. apply Int.shrx_shr_2. assumption.
intros. unfold rs3; Simpl. unfold rs2; Simpl. unfold rs1; Simpl.
+ }
(* intoffloat *)
econstructor; split. apply exec_straight_one; simpl. rewrite H0; simpl. eauto. auto.
Transparent destroyed_by_op.
@@ -1540,8 +1558,8 @@ Proof.
Qed.
Lemma transl_load_correct:
- forall chunk addr args dst k c (rs: regset) a m v,
- transl_load chunk addr args dst k = OK c ->
+ forall trap chunk addr args dst k c (rs: regset) a m v,
+ transl_load trap chunk addr args dst k = OK c ->
eval_addressing ge (rs#SP) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
@@ -1549,7 +1567,9 @@ Lemma transl_load_correct:
/\ rs'#(preg_of dst) = v
/\ forall r, data_preg r = true -> r <> preg_of dst -> rs'#r = rs#r.
Proof.
- intros. destruct chunk; simpl in H.
+ intros.
+ destruct trap; try (simpl in *; discriminate).
+ destruct chunk; simpl in H.
eapply transl_load_int_correct; eauto.
eapply transl_load_int_correct; eauto.
eapply transl_load_int_correct; eauto.
diff --git a/arm/Builtins1.v b/arm/Builtins1.v
index f6e643d2..53c83d7e 100644
--- a/arm/Builtins1.v
+++ b/arm/Builtins1.v
@@ -29,5 +29,5 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with end.
diff --git a/arm/CSE2deps.v b/arm/CSE2deps.v
new file mode 100644
index 00000000..9db51bbb
--- /dev/null
+++ b/arm/CSE2deps.v
@@ -0,0 +1,20 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs (Int.unsigned ofs') chunk' (Int.unsigned ofs) chunk)
+ else true | _, _, _, _ => true
+ end.
diff --git a/arm/CSE2depsproof.v b/arm/CSE2depsproof.v
new file mode 100644
index 00000000..61fe5980
--- /dev/null
+++ b/arm/CSE2depsproof.v
@@ -0,0 +1,129 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Lemma ptrofs_size :
+ Ptrofs.wordsize = 32%nat.
+Proof.
+ unfold Ptrofs.wordsize.
+ unfold Wordsize_Ptrofs.wordsize.
+ trivial.
+Qed.
+
+Lemma ptrofs_modulus :
+ Ptrofs.modulus = 4294967296.
+Proof.
+ unfold Ptrofs.modulus.
+ rewrite ptrofs_size.
+ destruct Archi.ptr64; reflexivity.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : int.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= Int.unsigned ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= Int.unsigned ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : Int.unsigned ofsw + size_chunk chunkw <= Int.unsigned ofsr
+ \/ Int.unsigned ofsr + size_chunk chunkr <= Int.unsigned ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in *.
+
+ rewrite ptrofs_modulus in *.
+ simpl in *.
+ inv ADDRR.
+ inv ADDRW.
+ destruct base; try discriminate.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.of_int ofsr)) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.of_int ofsw)) as [OFSW | OFSW];
+ rewrite OFSW).
+
+ all: try rewrite ptrofs_modulus in *.
+
+ all: unfold Ptrofs.of_int.
+
+ all: repeat rewrite Ptrofs.unsigned_repr by (change Ptrofs.max_unsigned with 4294967295; lia).
+ all: intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs (Int.unsigned ofsr) chunkr (Int.unsigned ofsw) chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs (Int.unsigned i0) chunk' (Int.unsigned i) chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away with (F:=F) (V:=V) (genv:=genv) (sp:=sp); eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/arm/Conventions1.v b/arm/Conventions1.v
index c5277e8d..fe49a781 100644
--- a/arm/Conventions1.v
+++ b/arm/Conventions1.v
@@ -104,13 +104,12 @@ Definition is_float_reg (r: mreg): bool :=
representation with a single LDM instruction. *)
Definition loc_result (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R0
- | Some (Tint | Tany32) => One R0
- | Some (Tfloat | Tsingle | Tany64) => One F0
- | Some Tlong => if Archi.big_endian
- then Twolong R0 R1
- else Twolong R1 R0
+ match proj_sig_res s with
+ | Tint | Tany32 => One R0
+ | Tfloat | Tsingle | Tany64 => One F0
+ | Tlong => if Archi.big_endian
+ then Twolong R0 R1
+ else Twolong R1 R0
end.
(** The result registers have types compatible with that given in the signature. *)
@@ -119,7 +118,7 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result. destruct (sig_res sig) as [[]|]; destruct Archi.big_endian; auto.
+ intros. unfold loc_result. destruct (proj_sig_res sig); destruct Archi.big_endian; auto.
Qed.
(** The result locations are caller-save registers *)
@@ -129,7 +128,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros.
- unfold loc_result. destruct (sig_res s) as [[]|]; destruct Archi.big_endian; simpl; auto.
+ unfold loc_result. destruct (proj_sig_res s); destruct Archi.big_endian; simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -139,14 +138,13 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
- intros; unfold loc_result; destruct (sig_res sg) as [[]|]; destruct Archi.big_endian; auto.
- intuition congruence.
- intuition congruence.
+ intros; unfold loc_result; destruct (proj_sig_res sg); auto.
+ destruct Archi.big_endian; intuition congruence.
Qed.
(** The location of the result depends only on the result part of the signature *)
@@ -154,7 +152,7 @@ Qed.
Lemma loc_result_exten:
forall s1 s2, s1.(sig_res) = s2.(sig_res) -> loc_result s1 = loc_result s2.
Proof.
- intros. unfold loc_result. rewrite H; auto.
+ intros. unfold loc_result, proj_sig_res. rewrite H; auto.
Qed.
(** ** Location of function arguments *)
@@ -271,48 +269,6 @@ Definition loc_arguments (s: signature) : list (rpair loc) :=
else loc_arguments_hf s.(sig_args) 0 0 0
end.
-(** [size_arguments s] returns the number of [Outgoing] slots used
- to call a function with signature [s]. *)
-
-Fixpoint size_arguments_hf (tyl: list typ) (ir fr ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => ofs
- | (Tint|Tany32) :: tys =>
- if zlt ir 4
- then size_arguments_hf tys (ir + 1) fr ofs
- else size_arguments_hf tys ir fr (ofs + 1)
- | (Tfloat|Tany64) :: tys =>
- if zlt fr 8
- then size_arguments_hf tys ir (fr + 1) ofs
- else size_arguments_hf tys ir fr (align ofs 2 + 2)
- | Tsingle :: tys =>
- if zlt fr 8
- then size_arguments_hf tys ir (fr + 1) ofs
- else size_arguments_hf tys ir fr (ofs + 1)
- | Tlong :: tys =>
- let ir := align ir 2 in
- if zlt ir 4
- then size_arguments_hf tys (ir + 2) fr ofs
- else size_arguments_hf tys ir fr (align ofs 2 + 2)
- end.
-
-Fixpoint size_arguments_sf (tyl: list typ) (ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => Z.max 0 ofs
- | (Tint | Tsingle | Tany32) :: tys => size_arguments_sf tys (ofs + 1)
- | (Tfloat | Tlong | Tany64) :: tys => size_arguments_sf tys (align ofs 2 + 2)
- end.
-
-Definition size_arguments (s: signature) : Z :=
- match Archi.abi with
- | Archi.Softfloat =>
- size_arguments_sf s.(sig_args) (-4)
- | Archi.Hardfloat =>
- if s.(sig_cc).(cc_vararg)
- then size_arguments_sf s.(sig_args) (-4)
- else size_arguments_hf s.(sig_args) 0 0 0
- end.
-
(** Argument locations are either non-temporary registers or [Outgoing]
stack slots at nonnegative offsets. *)
@@ -473,173 +429,15 @@ Qed.
Hint Resolve loc_arguments_acceptable: locs.
-(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
-
-Remark size_arguments_hf_above:
- forall tyl ir fr ofs0,
- ofs0 <= size_arguments_hf tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- omega.
- destruct a.
- destruct (zlt ir 4); eauto. apply Z.le_trans with (ofs0 + 1); auto; omega.
- destruct (zlt fr 8); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- set (ir' := align ir 2).
- destruct (zlt ir' 4); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- destruct (zlt fr 8); eauto.
- apply Z.le_trans with (ofs0 + 1); eauto. omega.
- destruct (zlt ir 4); eauto. apply Z.le_trans with (ofs0 + 1); auto; omega.
- destruct (zlt fr 8); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
-Qed.
-
-Remark size_arguments_sf_above:
- forall tyl ofs0,
- Z.max 0 ofs0 <= size_arguments_sf tyl ofs0.
-Proof.
- induction tyl; simpl; intros.
- omega.
- destruct a; (eapply Z.le_trans; [idtac|eauto]).
- xomega.
- assert (ofs0 <= align ofs0 2) by (apply align_le; omega). xomega.
- assert (ofs0 <= align ofs0 2) by (apply align_le; omega). xomega.
- xomega.
- xomega.
- assert (ofs0 <= align ofs0 2) by (apply align_le; omega). xomega.
-Qed.
-
-Lemma size_arguments_above:
- forall s, size_arguments s >= 0.
-Proof.
- intros; unfold size_arguments. apply Z.le_ge.
- assert (0 <= size_arguments_sf (sig_args s) (-4)).
- { change 0 with (Z.max 0 (-4)). apply size_arguments_sf_above. }
- assert (0 <= size_arguments_hf (sig_args s) 0 0 0).
- { apply size_arguments_hf_above. }
- destruct Archi.abi; [ | destruct (cc_vararg (sig_cc s)) ]; auto.
-Qed.
-
-Lemma loc_arguments_hf_bounded:
- forall ofs ty tyl ir fr ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_hf tyl ir fr ofs0)) ->
- ofs + typesize ty <= size_arguments_hf tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- elim H.
- destruct a.
-- (* int *)
- destruct (zlt ir 4); destruct H.
- discriminate.
- eauto.
- inv H. apply size_arguments_hf_above.
- eauto.
-- (* float *)
- destruct (zlt fr 8); destruct H.
- discriminate.
- eauto.
- inv H. apply size_arguments_hf_above.
- eauto.
-- (* long *)
- destruct (zlt (align ir 2) 4).
- destruct H. discriminate. destruct H. discriminate. eauto.
- destruct Archi.big_endian.
- destruct H. inv H.
- eapply Z.le_trans. 2: apply size_arguments_hf_above. simpl; omega.
- destruct H. inv H.
- rewrite <- Z.add_assoc. simpl. apply size_arguments_hf_above.
- eauto.
- destruct H. inv H.
- rewrite <- Z.add_assoc. simpl. apply size_arguments_hf_above.
- destruct H. inv H.
- eapply Z.le_trans. 2: apply size_arguments_hf_above. simpl; omega.
- eauto.
-- (* float *)
- destruct (zlt fr 8); destruct H.
- discriminate.
- eauto.
- inv H. apply size_arguments_hf_above.
- eauto.
-- (* any32 *)
- destruct (zlt ir 4); destruct H.
- discriminate.
- eauto.
- inv H. apply size_arguments_hf_above.
- eauto.
-- (* any64 *)
- destruct (zlt fr 8); destruct H.
- discriminate.
- eauto.
- inv H. apply size_arguments_hf_above.
- eauto.
-Qed.
-
-Lemma loc_arguments_sf_bounded:
- forall ofs ty tyl ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_sf tyl ofs0)) ->
- Z.max 0 (ofs + typesize ty) <= size_arguments_sf tyl ofs0.
-Proof.
- induction tyl; simpl; intros.
- elim H.
- destruct a.
-- (* int *)
- destruct H.
- destruct (zlt ofs0 0); inv H. apply size_arguments_sf_above.
- eauto.
-- (* float *)
- destruct H.
- destruct (zlt (align ofs0 2) 0); inv H. apply size_arguments_sf_above.
- eauto.
-- (* long *)
- destruct H.
- destruct Archi.big_endian.
- destruct (zlt (align ofs0 2) 0); inv H.
- eapply Z.le_trans. 2: apply size_arguments_sf_above. simpl; xomega.
- destruct (zlt (align ofs0 2) 0); inv H.
- rewrite <- Z.add_assoc. simpl. apply size_arguments_sf_above.
- destruct H.
- destruct Archi.big_endian.
- destruct (zlt (align ofs0 2) 0); inv H.
- rewrite <- Z.add_assoc. simpl. apply size_arguments_sf_above.
- destruct (zlt (align ofs0 2) 0); inv H.
- eapply Z.le_trans. 2: apply size_arguments_sf_above. simpl; xomega.
- eauto.
-- (* float *)
- destruct H.
- destruct (zlt ofs0 0); inv H. apply size_arguments_sf_above.
- eauto.
-- (* any32 *)
- destruct H.
- destruct (zlt ofs0 0); inv H. apply size_arguments_sf_above.
- eauto.
-- (* any64 *)
- destruct H.
- destruct (zlt (align ofs0 2) 0); inv H. apply size_arguments_sf_above.
- eauto.
-Qed.
-
-Lemma loc_arguments_bounded:
- forall (s: signature) (ofs: Z) (ty: typ),
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
- ofs + typesize ty <= size_arguments s.
-Proof.
- unfold loc_arguments, size_arguments; intros.
- assert (In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_sf (sig_args s) (-4))) ->
- ofs + typesize ty <= size_arguments_sf (sig_args s) (-4)).
- { intros. eapply Z.le_trans. 2: eapply loc_arguments_sf_bounded; eauto. xomega. }
- assert (In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_hf (sig_args s) 0 0 0)) ->
- ofs + typesize ty <= size_arguments_hf (sig_args s) 0 0 0).
- { intros. eapply loc_arguments_hf_bounded; eauto. }
- destruct Archi.abi; [ | destruct (cc_vararg (sig_cc s)) ]; eauto.
-Qed.
-
Lemma loc_arguments_main:
loc_arguments signature_main = nil.
Proof.
unfold loc_arguments.
destruct Archi.abi; reflexivity.
Qed.
+
+(** ** Normalization of function results *)
+
+(** No normalization needed. *)
+
+Definition return_value_needs_normalization (t: rettype) := false.
diff --git a/arm/DuplicateOpcodeHeuristic.ml b/arm/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..9b6a6409
--- /dev/null
+++ b/arm/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,22 @@
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c | Ccompfs c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c | Cnotcompfs c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
+
diff --git a/arm/Op.v b/arm/Op.v
index cc90e043..671bdbe4 100644
--- a/arm/Op.v
+++ b/arm/Op.v
@@ -518,6 +518,32 @@ Proof with (try exact I; try reflexivity).
unfold Val.select. destruct (eval_condition c vl m). apply Val.normalize_type. exact I.
Qed.
+
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivu
+ | Oshrximm _
+ | Ointoffloat | Ointuoffloat
+ | Ointofsingle | Ointuofsingle
+ | Ofloatofint | Ofloatofintu
+ | Osingleofint | Osingleofintu => true
+ | _ => false
+ end.
+
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -975,6 +1001,20 @@ Proof.
apply Val.offset_ptr_inject; auto.
Qed.
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *;
+ inv Hinjvl; trivial; try discriminate; inv H0; trivial; try discriminate; inv H2; trivial; try discriminate.
+Qed.
End EVAL_COMPAT.
(** Compatibility of the evaluation functions with the ``is less defined'' relation over values. *)
@@ -1080,6 +1120,19 @@ Proof.
destruct H1 as [v2 [A B]]. exists v2; split; auto. rewrite val_inject_lessdef; auto.
Qed.
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros. rewrite val_inject_list_lessdef in H.
+ eapply eval_addressing_inj_none with (sp1 := sp).
+ intros. rewrite <- val_inject_lessdef; auto.
+ rewrite <- val_inject_lessdef; auto.
+ eauto. auto.
+Qed.
+
End EVAL_LESSDEF.
(** Compatibility of the evaluation functions with memory injections. *)
@@ -1132,6 +1185,19 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/backend/Allnontrap.v b/backend/Allnontrap.v
new file mode 100644
index 00000000..acf03eca
--- /dev/null
+++ b/backend/Allnontrap.v
@@ -0,0 +1,26 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL.
+
+
+Definition transf_ros (ros: reg + ident) : reg + ident := ros.
+
+Definition transf_instr (pc: node) (instr: instruction) :=
+ match instr with
+ | Iload trap chunk addr args dst s => Iload NOTRAP chunk addr args dst s
+ | _ => instr
+ end.
+
+Definition transf_function (f: function) : function :=
+ {| fn_sig := f.(fn_sig);
+ fn_params := f.(fn_params);
+ fn_stacksize := f.(fn_stacksize);
+ fn_code := PTree.map transf_instr f.(fn_code);
+ fn_entrypoint := f.(fn_entrypoint) |}.
+
+Definition transf_fundef (fd: fundef) : fundef :=
+ AST.transf_fundef transf_function fd.
+
+Definition transf_program (p: program) : program :=
+ transform_program transf_fundef p.
+
diff --git a/backend/Allnontrapproof.v b/backend/Allnontrapproof.v
new file mode 100644
index 00000000..92e5a88c
--- /dev/null
+++ b/backend/Allnontrapproof.v
@@ -0,0 +1,215 @@
+Require Import FunInd.
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import Allnontrap.
+
+
+Definition match_prog (p tp: RTL.program) :=
+ match_program (fun ctx f tf => tf = transf_fundef f) eq p tp.
+
+Lemma transf_program_match:
+ forall p, match_prog p (transf_program p).
+Proof.
+ intros. eapply match_transform_program; eauto.
+Qed.
+
+Section PRESERVATION.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma functions_translated:
+ forall v f,
+ Genv.find_funct ge v = Some f ->
+ Genv.find_funct tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_transf TRANSL).
+
+Lemma function_ptr_translated:
+ forall v f,
+ Genv.find_funct_ptr ge v = Some f ->
+ Genv.find_funct_ptr tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_ptr_transf TRANSL).
+
+Lemma symbols_preserved:
+ forall id,
+ Genv.find_symbol tge id = Genv.find_symbol ge id.
+Proof (Genv.find_symbol_transf TRANSL).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_transf TRANSL).
+
+Lemma sig_preserved:
+ forall f, funsig (transf_fundef f) = funsig f.
+Proof.
+ destruct f; reflexivity.
+Qed.
+
+Lemma find_function_translated:
+ forall ros rs fd,
+ find_function ge ros rs = Some fd ->
+ find_function tge ros rs = Some (transf_fundef fd).
+Proof.
+ unfold find_function; intros. destruct ros as [r|id].
+ eapply functions_translated; eauto.
+ rewrite symbols_preserved. destruct (Genv.find_symbol ge id); try congruence.
+ eapply function_ptr_translated; eauto.
+Qed.
+
+Lemma transf_function_at:
+ forall f pc i,
+ f.(fn_code)!pc = Some i ->
+ (transf_function f).(fn_code)!pc = Some(transf_instr pc i).
+Proof.
+ intros until i. intro Hcode.
+ unfold transf_function; simpl.
+ rewrite PTree.gmap.
+ unfold option_map.
+ rewrite Hcode.
+ reflexivity.
+Qed.
+
+Ltac TR_AT :=
+ match goal with
+ | [ A: (fn_code _)!_ = Some _ |- _ ] =>
+ generalize (transf_function_at _ _ _ A); intros
+ end.
+
+
+Inductive match_frames: RTL.stackframe -> RTL.stackframe -> Prop :=
+ | match_frames_intro: forall res f sp pc rs,
+ match_frames (Stackframe res f sp pc rs)
+ (Stackframe res (transf_function f) sp pc rs).
+
+Inductive match_states: RTL.state -> RTL.state -> Prop :=
+ | match_regular_states: forall stk f sp pc rs m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (State stk f sp pc rs m)
+ (State stk' (transf_function f) sp pc rs m)
+ | match_callstates: forall stk f args m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Callstate stk f args m)
+ (Callstate stk' (transf_fundef f) args m)
+ | match_returnstates: forall stk v m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Returnstate stk v m)
+ (Returnstate stk' v m).
+
+Lemma step_simulation:
+ forall S1 t S2, RTL.step ge S1 t S2 ->
+ forall S1', match_states S1 S1' ->
+ exists S2', RTL.step tge S1' t S2' /\ match_states S2 S2'.
+Proof.
+ induction 1; intros S1' MS; inv MS; try TR_AT.
+- (* nop *)
+ econstructor; split. eapply exec_Inop; eauto.
+ constructor; auto.
+- (* op *)
+ econstructor; split.
+ eapply exec_Iop with (v := v); eauto.
+ rewrite <- H0. apply eval_operation_preserved. exact symbols_preserved.
+ constructor; auto.
+(* load *)
+- econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload; eauto.
+ constructor; auto.
+- (* load notrap1 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = None).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap1; eauto.
+ constructor; auto.
+- (* load notrap2 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap2; eauto.
+ constructor; auto.
+- (* store *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Istore; eauto.
+ constructor; auto.
+(* call *)
+- econstructor; split.
+ eapply exec_Icall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ constructor. constructor; auto. constructor.
+(* tailcall *)
+- econstructor; split.
+ eapply exec_Itailcall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ constructor. auto.
+(* builtin *)
+- econstructor; split.
+ eapply exec_Ibuiltin; eauto.
+ eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+(* cond *)
+- econstructor; split.
+ eapply exec_Icond; eauto.
+ constructor; auto.
+(* jumptbl *)
+- econstructor; split.
+ eapply exec_Ijumptable; eauto.
+ constructor; auto.
+(* return *)
+- econstructor; split.
+ eapply exec_Ireturn; eauto.
+ constructor; auto.
+(* internal function *)
+- simpl. econstructor; split.
+ eapply exec_function_internal; eauto.
+ constructor; auto.
+(* external function *)
+- econstructor; split.
+ eapply exec_function_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+(* return *)
+- inv STACKS. inv H1.
+ econstructor; split.
+ eapply exec_return; eauto.
+ constructor; auto.
+Qed.
+
+Lemma transf_initial_states:
+ forall S1, RTL.initial_state prog S1 ->
+ exists S2, RTL.initial_state tprog S2 /\ match_states S1 S2.
+Proof.
+ intros. inv H. econstructor; split.
+ econstructor.
+ eapply (Genv.init_mem_transf TRANSL); eauto.
+ rewrite symbols_preserved. rewrite (match_program_main TRANSL). eauto.
+ eapply function_ptr_translated; eauto.
+ rewrite <- H3; apply sig_preserved.
+ constructor. constructor.
+Qed.
+
+Lemma transf_final_states:
+ forall S1 S2 r, match_states S1 S2 -> RTL.final_state S1 r -> RTL.final_state S2 r.
+Proof.
+ intros. inv H0. inv H. inv STACKS. constructor.
+Qed.
+
+Theorem transf_program_correct:
+ forward_simulation (RTL.semantics prog) (RTL.semantics tprog).
+Proof.
+ eapply forward_simulation_step.
+ apply senv_preserved.
+ eexact transf_initial_states.
+ eexact transf_final_states.
+ exact step_simulation.
+Qed.
+
+End PRESERVATION.
diff --git a/backend/Allocation.v b/backend/Allocation.v
index 13e14530..2323c050 100644
--- a/backend/Allocation.v
+++ b/backend/Allocation.v
@@ -58,7 +58,7 @@ Inductive block_shape: Type :=
(mv2: moves) (s: node)
| BSopdead (op: operation) (args: list reg) (res: reg)
(mv: moves) (s: node)
- | BSload (chunk: memory_chunk) (addr: addressing) (args: list reg) (dst: reg)
+ | BSload (trap : trapping_mode) (chunk: memory_chunk) (addr: addressing) (args: list reg) (dst: reg)
(mv1: moves) (args': list mreg) (dst': mreg)
(mv2: moves) (s: node)
| BSloaddead (chunk: memory_chunk) (addr: addressing) (args: list reg) (dst: reg)
@@ -226,15 +226,19 @@ Definition pair_instr_block
| operation_other _ _ =>
pair_Iop_block op args res s b
end
- | Iload chunk addr args dst s =>
+ | Iload trap chunk addr args dst s =>
let (mv1, b1) := extract_moves nil b in
match b1 with
- | Lload chunk' addr' args' dst' :: b2 =>
+ | Lload trap' chunk' addr' args' dst' :: b2 =>
+ assertion (trapping_mode_eq trap' trap);
if chunk_eq chunk Mint64 && Archi.splitlong then
+ (* TODO: do not support non trapping split loads *)
+ assertion (trapping_mode_eq trap TRAP);
assertion (chunk_eq chunk' Mint32);
let (mv2, b3) := extract_moves nil b2 in
match b3 with
- | Lload chunk'' addr'' args'' dst'' :: b4 =>
+ | Lload trap'' chunk'' addr'' args'' dst'' :: b4 =>
+ assertion (trapping_mode_eq trap'' TRAP);
let (mv3, b5) := extract_moves nil b4 in
assertion (chunk_eq chunk'' Mint32);
assertion (eq_addressing addr addr');
@@ -254,7 +258,7 @@ Definition pair_instr_block
assertion (chunk_eq chunk chunk');
assertion (eq_addressing addr addr');
assertion (check_succ s b3);
- Some(BSload chunk addr args dst mv1 args' dst' mv2 s))
+ Some(BSload trap chunk addr args dst mv1 args' dst' mv2 s))
| _ =>
assertion (check_succ s b1);
Some(BSloaddead chunk addr args dst mv1 s)
@@ -310,10 +314,10 @@ Definition pair_instr_block
Some(BSbuiltin ef args res mv1 args' res' mv2 s)
| _ => None
end
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 i =>
let (mv1, b1) := extract_moves nil b in
match b1 with
- | Lcond cond' args' s1' s2' :: b2 =>
+ | Lcond cond' args' s1' s2' i' :: b2 =>
assertion (eq_condition cond cond');
assertion (peq s1 s1');
assertion (peq s2 s2');
@@ -734,11 +738,11 @@ Function add_equations_args (rl: list reg) (tyl: list typ) (ll: list (rpair loc)
(** [add_equations_res] is similar but is specialized to the case where
there is only one pseudo-register. *)
-Function add_equations_res (r: reg) (oty: option typ) (p: rpair mreg) (e: eqs) : option eqs :=
- match p, oty with
+Function add_equations_res (r: reg) (ty: typ) (p: rpair mreg) (e: eqs) : option eqs :=
+ match p, ty with
| One mr, _ =>
Some (add_equation (Eq Full r (R mr)) e)
- | Twolong mr1 mr2, Some Tlong =>
+ | Twolong mr1 mr2, Tlong =>
if Archi.ptr64 then None else
Some (add_equation (Eq Low r (R mr2)) (add_equation (Eq High r (R mr1)) e))
| _, _ =>
@@ -1023,7 +1027,7 @@ Definition transfer_aux (f: RTL.function) (env: regenv)
| BSopdead op args res mv s =>
assertion (reg_unconstrained res e);
track_moves env mv e
- | BSload chunk addr args dst mv1 args' dst' mv2 s =>
+ | BSload trap chunk addr args dst mv1 args' dst' mv2 s =>
do e1 <- track_moves env mv2 e;
do e2 <- transfer_use_def args dst args' dst' (destroyed_by_load chunk addr) e1;
track_moves env mv1 e2
@@ -1084,7 +1088,7 @@ Definition transfer_aux (f: RTL.function) (env: regenv)
| BStailcall sg ros args mv1 ros' =>
let args' := loc_arguments sg in
assertion (tailcall_is_possible sg);
- assertion (opt_typ_eq sg.(sig_res) f.(RTL.fn_sig).(sig_res));
+ assertion (rettype_eq sg.(sig_res) f.(RTL.fn_sig).(sig_res));
assertion (ros_compatible_tailcall ros');
do e1 <- add_equation_ros ros ros' empty_eqs;
do e2 <- add_equations_args args (sig_args sg) args' e1;
@@ -1114,7 +1118,7 @@ Definition transfer_aux (f: RTL.function) (env: regenv)
track_moves env mv empty_eqs
| BSreturn (Some arg) mv =>
let arg' := loc_result (RTL.fn_sig f) in
- do e1 <- add_equations_res arg (sig_res (RTL.fn_sig f)) arg' empty_eqs;
+ do e1 <- add_equations_res arg (proj_sig_res (RTL.fn_sig f)) arg' empty_eqs;
track_moves env mv e1
end.
@@ -1263,7 +1267,7 @@ Definition successors_block_shape (bsh: block_shape) : list node :=
| BShighlong src dst mv s => s :: nil
| BSop op args res mv1 args' res' mv2 s => s :: nil
| BSopdead op args res mv s => s :: nil
- | BSload chunk addr args dst mv1 args' dst' mv2 s => s :: nil
+ | BSload trap chunk addr args dst mv1 args' dst' mv2 s => s :: nil
| BSload2 addr addr' args dst mv1 args1' dst1' mv2 args2' dst2' mv3 s => s :: nil
| BSload2_1 addr args dst mv1 args' dst' mv2 s => s :: nil
| BSload2_2 addr addr' args dst mv1 args' dst' mv2 s => s :: nil
diff --git a/backend/Allocproof.v b/backend/Allocproof.v
index 1804f46b..3c7df58a 100644
--- a/backend/Allocproof.v
+++ b/backend/Allocproof.v
@@ -96,44 +96,44 @@ Inductive expand_block_shape: block_shape -> RTL.instruction -> LTL.bblock -> Pr
expand_block_shape (BSopdead op args res mv s)
(Iop op args res s)
(expand_moves mv (Lbranch s :: k))
- | ebs_load: forall chunk addr args dst mv1 args' dst' mv2 s k,
+ | ebs_load: forall trap chunk addr args dst mv1 args' dst' mv2 s k,
wf_moves mv1 -> wf_moves mv2 ->
- expand_block_shape (BSload chunk addr args dst mv1 args' dst' mv2 s)
- (Iload chunk addr args dst s)
+ expand_block_shape (BSload trap chunk addr args dst mv1 args' dst' mv2 s)
+ (Iload trap chunk addr args dst s)
(expand_moves mv1
- (Lload chunk addr args' dst' :: expand_moves mv2 (Lbranch s :: k)))
+ (Lload trap chunk addr args' dst' :: expand_moves mv2 (Lbranch s :: k)))
| ebs_load2: forall addr addr2 args dst mv1 args1' dst1' mv2 args2' dst2' mv3 s k,
wf_moves mv1 -> wf_moves mv2 -> wf_moves mv3 ->
Archi.splitlong = true ->
offset_addressing addr 4 = Some addr2 ->
expand_block_shape (BSload2 addr addr2 args dst mv1 args1' dst1' mv2 args2' dst2' mv3 s)
- (Iload Mint64 addr args dst s)
+ (Iload TRAP Mint64 addr args dst s)
(expand_moves mv1
- (Lload Mint32 addr args1' dst1' ::
+ (Lload TRAP Mint32 addr args1' dst1' ::
expand_moves mv2
- (Lload Mint32 addr2 args2' dst2' ::
+ (Lload TRAP Mint32 addr2 args2' dst2' ::
expand_moves mv3 (Lbranch s :: k))))
| ebs_load2_1: forall addr args dst mv1 args' dst' mv2 s k,
wf_moves mv1 -> wf_moves mv2 ->
Archi.splitlong = true ->
expand_block_shape (BSload2_1 addr args dst mv1 args' dst' mv2 s)
- (Iload Mint64 addr args dst s)
+ (Iload TRAP Mint64 addr args dst s)
(expand_moves mv1
- (Lload Mint32 addr args' dst' ::
+ (Lload TRAP Mint32 addr args' dst' ::
expand_moves mv2 (Lbranch s :: k)))
| ebs_load2_2: forall addr addr2 args dst mv1 args' dst' mv2 s k,
wf_moves mv1 -> wf_moves mv2 ->
Archi.splitlong = true ->
offset_addressing addr 4 = Some addr2 ->
expand_block_shape (BSload2_2 addr addr2 args dst mv1 args' dst' mv2 s)
- (Iload Mint64 addr args dst s)
+ (Iload TRAP Mint64 addr args dst s)
(expand_moves mv1
- (Lload Mint32 addr2 args' dst' ::
+ (Lload TRAP Mint32 addr2 args' dst' ::
expand_moves mv2 (Lbranch s :: k)))
- | ebs_load_dead: forall chunk addr args dst mv s k,
+ | ebs_load_dead: forall trap chunk addr args dst mv s k,
wf_moves mv ->
expand_block_shape (BSloaddead chunk addr args dst mv s)
- (Iload chunk addr args dst s)
+ (Iload trap chunk addr args dst s)
(expand_moves mv (Lbranch s :: k))
| ebs_store: forall chunk addr args src mv1 args' src' s k,
wf_moves mv1 ->
@@ -169,11 +169,11 @@ Inductive expand_block_shape: block_shape -> RTL.instruction -> LTL.bblock -> Pr
(Ibuiltin ef args res s)
(expand_moves mv1
(Lbuiltin ef args' res' :: expand_moves mv2 (Lbranch s :: k)))
- | ebs_cond: forall cond args mv args' s1 s2 k,
+ | ebs_cond: forall cond args mv args' s1 s2 k i i',
wf_moves mv ->
expand_block_shape (BScond cond args mv args' s1 s2)
- (Icond cond args s1 s2)
- (expand_moves mv (Lcond cond args' s1 s2 :: k))
+ (Icond cond args s1 s2 i)
+ (expand_moves mv (Lcond cond args' s1 s2 i' :: k))
| ebs_jumptable: forall arg mv arg' tbl k,
wf_moves mv ->
expand_block_shape (BSjumptable arg mv arg' tbl)
@@ -1301,10 +1301,10 @@ Proof.
Qed.
Lemma add_equations_res_lessdef:
- forall r oty l e e' rs ls,
- add_equations_res r oty l e = Some e' ->
+ forall r ty l e e' rs ls,
+ add_equations_res r ty l e = Some e' ->
satisf rs ls e' ->
- Val.has_type rs#r (match oty with Some ty => ty | None => Tint end) ->
+ Val.has_type rs#r ty ->
Val.lessdef rs#r (Locmap.getpair (map_rpair R l) ls).
Proof.
intros. functional inversion H; simpl.
@@ -1892,7 +1892,7 @@ Qed.
Inductive match_stackframes: list RTL.stackframe -> list LTL.stackframe -> signature -> Prop :=
| match_stackframes_nil: forall sg,
- sg.(sig_res) = Some Tint ->
+ sg.(sig_res) = Tint ->
match_stackframes nil nil sg
| match_stackframes_cons:
forall res f sp pc rs s tf bb ls ts sg an e env
@@ -1970,8 +1970,8 @@ Ltac UseShape :=
end.
Remark addressing_not_long:
- forall env f addr args dst s r,
- wt_instr f env (Iload Mint64 addr args dst s) -> Archi.splitlong = true ->
+ forall trap env f addr args dst s r,
+ wt_instr f env (Iload trap Mint64 addr args dst s) -> Archi.splitlong = true ->
In r args -> r <> dst.
Proof.
intros. inv H.
@@ -1981,7 +1981,7 @@ Proof.
{ rewrite <- H5. apply in_map; auto. }
assert (C: env r = Tint).
{ apply A in B. rewrite B. unfold Tptr. rewrite Archi.splitlong_ptr32 by auto. auto. }
- red; intros; subst r. rewrite C in H8; discriminate.
+ red; intros; subst r. rewrite C in H9; discriminate.
Qed.
(** The proof of semantic preservation is a simulation argument of the
@@ -2082,8 +2082,8 @@ Proof.
econstructor; eauto.
eapply wt_exec_Iop; eauto.
-(* load regular *)
-- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
+(* load regular TRAP *)
+- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
exploit (exec_moves mv1); eauto. intros [ls1 [A1 B1]].
exploit transfer_use_def_satisf; eauto. intros [X Y].
exploit eval_addressing_lessdef; eauto. intros [a' [F G]].
@@ -2100,7 +2100,7 @@ Proof.
econstructor; eauto.
(* load pair *)
-- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
+- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
exploit loadv_int64_split; eauto. intros (v1 & v2 & LOAD1 & LOAD2 & V1 & V2).
set (v2' := if Archi.big_endian then v2 else v1) in *.
set (v1' := if Archi.big_endian then v1 else v2) in *.
@@ -2155,7 +2155,7 @@ Proof.
econstructor; eauto.
(* load first word of a pair *)
-- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
+- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
exploit loadv_int64_split; eauto. intros (v1 & v2 & LOAD1 & LOAD2 & V1 & V2).
set (v2' := if Archi.big_endian then v2 else v1) in *.
set (v1' := if Archi.big_endian then v1 else v2) in *.
@@ -2185,7 +2185,7 @@ Proof.
econstructor; eauto.
(* load second word of a pair *)
-- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
+- generalize (wt_exec_Iload _ _ _ _ _ _ _ _ _ _ _ _ WTI H1 WTRS). intros WTRS'.
exploit loadv_int64_split; eauto. intros (v1 & v2 & LOAD1 & LOAD2 & V1 & V2).
set (v2' := if Archi.big_endian then v2 else v1) in *.
set (v1' := if Archi.big_endian then v1 else v2) in *.
@@ -2229,6 +2229,79 @@ Proof.
econstructor; eauto.
eapply wt_exec_Iload; eauto.
+- (* load notrap1 *)
+ generalize (wt_exec_Iload_notrap _ _ _ _ _ _ _ _ WTI WTRS).
+ intro WTRS'.
+ exploit (exec_moves mv1); eauto. intros [ls1 [A1 B1]].
+ exploit transfer_use_def_satisf; eauto. intros [X Y].
+ exploit eval_addressing_lessdef_none; eauto. intro Haddr.
+ exploit (exec_moves mv2); eauto. intros [ls2 [A2 B2]].
+ econstructor; split.
+ eapply plus_left. econstructor; eauto.
+ eapply star_trans. eexact A1.
+ eapply star_left. eapply exec_Lload_notrap1. rewrite <- Haddr.
+ apply eval_addressing_preserved. exact symbols_preserved. eauto.
+
+ eapply star_right. eexact A2. constructor.
+ eauto. eauto. eauto. traceEq.
+ exploit satisf_successors; eauto. simpl; eauto. intros [enext [U V]].
+ econstructor; eauto.
+
+(* load notrap1 dead *)
+- exploit exec_moves; eauto. intros [ls1 [X Y]].
+ econstructor; split.
+ eapply plus_left. econstructor; eauto.
+ eapply star_right. eexact X. econstructor; eauto.
+ eauto. traceEq.
+ exploit satisf_successors. eauto. eauto. simpl; eauto. eauto.
+ eapply reg_unconstrained_satisf; eauto.
+ intros [enext [U V]].
+ econstructor; eauto.
+ eapply wt_exec_Iload_notrap; eauto.
+
+(* load regular notrap2 *)
+- generalize (wt_exec_Iload_notrap _ _ _ _ _ _ _ _ WTI WTRS).
+ intro WTRS'.
+ exploit (exec_moves mv1); eauto. intros [ls1 [A1 B1]].
+ exploit transfer_use_def_satisf; eauto. intros [X Y].
+ exploit eval_addressing_lessdef; eauto. intros [a' [F G]].
+ destruct (Mem.loadv chunk m' a') as [v' |] eqn:Hload.
+ { exploit (exec_moves mv2 env (rs # dst <- Vundef)); eauto. intros [ls2 [A2 B2]].
+ econstructor; split.
+ eapply plus_left. econstructor; eauto.
+ eapply star_trans. eexact A1.
+ eapply star_left. econstructor. instantiate (1 := a'). rewrite <- F.
+ apply eval_addressing_preserved. exact symbols_preserved. eauto. eauto.
+ eapply star_right. eexact A2. constructor.
+ eauto. eauto. eauto. traceEq.
+ exploit satisf_successors; eauto. simpl; eauto. intros [enext [U V]].
+ econstructor; eauto.
+ }
+ { exploit (exec_moves mv2 env (rs # dst <- Vundef)); eauto. intros [ls2 [A2 B2]].
+ econstructor; split.
+ eapply plus_left. econstructor; eauto.
+ eapply star_trans. eexact A1.
+ eapply star_left. eapply exec_Lload_notrap2. rewrite <- F.
+ apply eval_addressing_preserved. exact symbols_preserved. assumption.
+ eauto.
+ eapply star_right. eexact A2. constructor.
+ eauto. eauto. eauto. traceEq.
+ exploit satisf_successors; eauto. simpl; eauto. intros [enext [U V]].
+ econstructor; eauto.
+ }
+
+- (* load notrap2 dead *)
+ exploit exec_moves; eauto. intros [ls1 [X Y]].
+ econstructor; split.
+ eapply plus_left. econstructor; eauto.
+ eapply star_right. eexact X. econstructor; eauto.
+ eauto. traceEq.
+ exploit satisf_successors. eauto. eauto. simpl; eauto. eauto.
+ eapply reg_unconstrained_satisf; eauto.
+ intros [enext [U V]].
+ econstructor; eauto.
+ eapply wt_exec_Iload_notrap; eauto.
+
(* store *)
- exploit exec_moves; eauto. intros [ls1 [X Y]].
exploit add_equations_lessdef; eauto. intros LD. simpl in LD. inv LD.
@@ -2425,13 +2498,13 @@ Proof.
(return_regs (parent_locset ts) ls1))
with (Locmap.getpair (map_rpair R (loc_result (RTL.fn_sig f))) ls1).
eapply add_equations_res_lessdef; eauto.
- rewrite H13. apply WTRS.
+ rewrite <- H14. apply WTRS.
generalize (loc_result_caller_save (RTL.fn_sig f)).
destruct (loc_result (RTL.fn_sig f)); simpl.
intros A; rewrite A; auto.
intros [A B]; rewrite A, B; auto.
apply return_regs_agree_callee_save.
- unfold proj_sig_res. rewrite <- H11; rewrite H13. apply WTRS.
+ rewrite <- H11, <- H14. apply WTRS.
(* internal function *)
- monadInv FUN. simpl in *.
@@ -2463,7 +2536,8 @@ Proof.
simpl. destruct (loc_result (ef_sig ef)) eqn:RES; simpl.
rewrite Locmap.gss; auto.
generalize (loc_result_pair (ef_sig ef)); rewrite RES; intros (A & B & C & D & E).
- exploit external_call_well_typed; eauto. unfold proj_sig_res; rewrite B. intros WTRES'.
+ assert (WTRES': Val.has_type v' Tlong).
+ { rewrite <- B. eapply external_call_well_typed; eauto. }
rewrite Locmap.gss. rewrite Locmap.gso by (red; auto). rewrite Locmap.gss.
rewrite val_longofwords_eq_1 by auto. auto.
red; intros. rewrite (AG l H0).
diff --git a/backend/Asmexpandaux.ml b/backend/Asmexpandaux.ml
index b1d822db..cc171cae 100644
--- a/backend/Asmexpandaux.ml
+++ b/backend/Asmexpandaux.ml
@@ -100,7 +100,7 @@ let translate_annot sp preg_to_dwarf annot =
| a::_ -> aux a)
let builtin_nop =
- let signature ={sig_args = []; sig_res = None; sig_cc = cc_default} in
+ let signature ={sig_args = []; sig_res = Tvoid; sig_cc = cc_default} in
let name = coqstring_of_camlstring "__builtin_nop" in
Pbuiltin(EF_builtin(name,signature),[],BR_none)
diff --git a/backend/Bounds.v b/backend/Bounds.v
index fa695234..b8c12166 100644
--- a/backend/Bounds.v
+++ b/backend/Bounds.v
@@ -67,7 +67,7 @@ Definition instr_within_bounds (i: instruction) :=
| Lgetstack sl ofs ty r => slot_within_bounds sl ofs ty /\ mreg_within_bounds r
| Lsetstack r sl ofs ty => slot_within_bounds sl ofs ty
| Lop op args res => mreg_within_bounds res
- | Lload chunk addr args dst => mreg_within_bounds dst
+ | Lload trap chunk addr args dst => mreg_within_bounds dst
| Lcall sig ros => size_arguments sig <= bound_outgoing b
| Lbuiltin ef args res =>
(forall r, In r (params_of_builtin_res res) \/ In r (destroyed_by_builtin ef) -> mreg_within_bounds r)
@@ -104,7 +104,7 @@ Definition record_regs_of_instr (u: RegSet.t) (i: instruction) : RegSet.t :=
| Lgetstack sl ofs ty r => record_reg u r
| Lsetstack r sl ofs ty => record_reg u r
| Lop op args res => record_reg u res
- | Lload chunk addr args dst => record_reg u dst
+ | Lload trap chunk addr args dst => record_reg u dst
| Lstore chunk addr args src => u
| Lcall sig ros => u
| Ltailcall sig ros => u
@@ -280,7 +280,7 @@ Definition defined_by_instr (r': mreg) (i: instruction) :=
match i with
| Lgetstack sl ofs ty r => r' = r
| Lop op args res => r' = res
- | Lload chunk addr args dst => r' = dst
+ | Lload trap chunk addr args dst => r' = dst
| Lbuiltin ef args res => In r' (params_of_builtin_res res) \/ In r' (destroyed_by_builtin ef)
| _ => False
end.
diff --git a/backend/CSE.v b/backend/CSE.v
index ecfa1f9e..1936d4e4 100644
--- a/backend/CSE.v
+++ b/backend/CSE.v
@@ -459,8 +459,10 @@ Definition transfer (f: function) (approx: PMap.t VA.t) (pc: node) (before: numb
before
| Iop op args res s =>
add_op before res op args
- | Iload chunk addr args dst s =>
- add_load before dst chunk addr args
+ | Iload TRAP chunk addr args dst s =>
+ add_load before dst chunk addr args
+ | Iload NOTRAP _ _ _ dst _ =>
+ set_unknown before dst
| Istore chunk addr args src s =>
let app := approx!!pc in
let n := kill_loads_after_store app before chunk addr args in
@@ -494,7 +496,7 @@ Definition transfer (f: function) (approx: PMap.t VA.t) (pc: node) (before: numb
| EF_vload _ | EF_annot _ _ _ | EF_annot_val _ _ _ | EF_debug _ _ _ =>
set_res_unknown before res
end
- | Icond cond args ifso ifnot =>
+ | Icond cond args ifso ifnot _ =>
before
| Ijumptable arg tbl =>
before
@@ -534,23 +536,23 @@ Definition transf_instr (n: numbering) (instr: instruction) :=
let (op', args') := reduce _ combine_op n1 op args vl in
Iop op' args' res s
end
- | Iload chunk addr args dst s =>
+ | Iload TRAP chunk addr args dst s =>
let (n1, vl) := valnum_regs n args in
match find_rhs n1 (Load chunk addr vl) with
| Some r =>
Iop Omove (r :: nil) dst s
| None =>
let (addr', args') := reduce _ combine_addr n1 addr args vl in
- Iload chunk addr' args' dst s
+ Iload TRAP chunk addr' args' dst s
end
| Istore chunk addr args src s =>
let (n1, vl) := valnum_regs n args in
let (addr', args') := reduce _ combine_addr n1 addr args vl in
Istore chunk addr' args' src s
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 i =>
let (n1, vl) := valnum_regs n args in
let (cond', args') := reduce _ combine_cond n1 cond args vl in
- Icond cond' args' s1 s2
+ Icond cond' args' s1 s2 i
| _ =>
instr
end.
diff --git a/backend/CSE2.v b/backend/CSE2.v
new file mode 100644
index 00000000..900a7517
--- /dev/null
+++ b/backend/CSE2.v
@@ -0,0 +1,518 @@
+(*
+Replace available expressions by the register containing their value.
+
+David Monniaux, CNRS, VERIMAG
+ *)
+
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps CSE2deps.
+
+(* Static analysis *)
+
+Inductive sym_val : Type :=
+| SMove (src : reg)
+| SOp (op : operation) (args : list reg)
+| SLoad (chunk : memory_chunk) (addr : addressing) (args : list reg).
+
+Definition eq_args (x y : list reg) : { x = y } + { x <> y } :=
+ list_eq_dec peq x y.
+
+Definition eq_sym_val : forall x y : sym_val,
+ {x = y} + { x <> y }.
+Proof.
+ generalize eq_operation.
+ generalize eq_args.
+ generalize peq.
+ generalize eq_addressing.
+ generalize chunk_eq.
+ decide equality.
+Defined.
+
+Module RELATION.
+
+Definition t := (PTree.t sym_val).
+Definition eq (r1 r2 : t) :=
+ forall x, (PTree.get x r1) = (PTree.get x r2).
+
+Definition top : t := PTree.empty sym_val.
+
+Lemma eq_refl: forall x, eq x x.
+Proof.
+ unfold eq.
+ intros; reflexivity.
+Qed.
+
+Lemma eq_sym: forall x y, eq x y -> eq y x.
+Proof.
+ unfold eq.
+ intros; eauto.
+Qed.
+
+Lemma eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+Proof.
+ unfold eq.
+ intros; congruence.
+Qed.
+
+Definition sym_val_beq (x y : sym_val) :=
+ if eq_sym_val x y then true else false.
+
+Definition beq (r1 r2 : t) := PTree.beq sym_val_beq r1 r2.
+
+Lemma beq_correct: forall r1 r2, beq r1 r2 = true -> eq r1 r2.
+Proof.
+ unfold beq, eq. intros r1 r2 EQ x.
+ pose proof (PTree.beq_correct sym_val_beq r1 r2) as CORRECT.
+ destruct CORRECT as [CORRECTF CORRECTB].
+ pose proof (CORRECTF EQ x) as EQx.
+ clear CORRECTF CORRECTB EQ.
+ unfold sym_val_beq in *.
+ destruct (r1 ! x) as [R1x | ] in *;
+ destruct (r2 ! x) as [R2x | ] in *;
+ trivial; try contradiction.
+ destruct (eq_sym_val R1x R2x) in *; congruence.
+Qed.
+
+Definition ge (r1 r2 : t) :=
+ forall x,
+ match PTree.get x r1 with
+ | None => True
+ | Some v => (PTree.get x r2) = Some v
+ end.
+
+Lemma ge_refl: forall r1 r2, eq r1 r2 -> ge r1 r2.
+Proof.
+ unfold eq, ge.
+ intros r1 r2 EQ x.
+ pose proof (EQ x) as EQx.
+ clear EQ.
+ destruct (r1 ! x).
+ - congruence.
+ - trivial.
+Qed.
+
+Lemma ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+Proof.
+ unfold ge.
+ intros r1 r2 r3 GE12 GE23 x.
+ pose proof (GE12 x) as GE12x; clear GE12.
+ pose proof (GE23 x) as GE23x; clear GE23.
+ destruct (r1 ! x); trivial.
+ destruct (r2 ! x); congruence.
+Qed.
+
+Definition lub (r1 r2 : t) :=
+ PTree.combine
+ (fun ov1 ov2 =>
+ match ov1, ov2 with
+ | (Some v1), (Some v2) =>
+ if eq_sym_val v1 v2
+ then ov1
+ else None
+ | None, _
+ | _, None => None
+ end)
+ r1 r2.
+
+Lemma ge_lub_left: forall x y, ge (lub x y) x.
+Proof.
+ unfold ge, lub.
+ intros r1 r2 x.
+ rewrite PTree.gcombine by reflexivity.
+ destruct (_ ! _); trivial.
+ destruct (_ ! _); trivial.
+ destruct (eq_sym_val _ _); trivial.
+Qed.
+
+Lemma ge_lub_right: forall x y, ge (lub x y) y.
+Proof.
+ unfold ge, lub.
+ intros r1 r2 x.
+ rewrite PTree.gcombine by reflexivity.
+ destruct (_ ! _); trivial.
+ destruct (_ ! _); trivial.
+ destruct (eq_sym_val _ _); trivial.
+ congruence.
+Qed.
+
+End RELATION.
+
+Module Type SEMILATTICE_WITHOUT_BOTTOM.
+
+ Parameter t: Type.
+ Parameter eq: t -> t -> Prop.
+ Axiom eq_refl: forall x, eq x x.
+ Axiom eq_sym: forall x y, eq x y -> eq y x.
+ Axiom eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+ Parameter beq: t -> t -> bool.
+ Axiom beq_correct: forall x y, beq x y = true -> eq x y.
+ Parameter ge: t -> t -> Prop.
+ Axiom ge_refl: forall x y, eq x y -> ge x y.
+ Axiom ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+ Parameter lub: t -> t -> t.
+ Axiom ge_lub_left: forall x y, ge (lub x y) x.
+ Axiom ge_lub_right: forall x y, ge (lub x y) y.
+
+End SEMILATTICE_WITHOUT_BOTTOM.
+
+Module ADD_BOTTOM(L : SEMILATTICE_WITHOUT_BOTTOM).
+ Definition t := option L.t.
+ Definition eq (a b : t) :=
+ match a, b with
+ | None, None => True
+ | Some x, Some y => L.eq x y
+ | Some _, None | None, Some _ => False
+ end.
+
+ Lemma eq_refl: forall x, eq x x.
+ Proof.
+ unfold eq; destruct x; trivial.
+ apply L.eq_refl.
+ Qed.
+
+ Lemma eq_sym: forall x y, eq x y -> eq y x.
+ Proof.
+ unfold eq; destruct x; destruct y; trivial.
+ apply L.eq_sym.
+ Qed.
+
+ Lemma eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+ Proof.
+ unfold eq; destruct x; destruct y; destruct z; trivial.
+ - apply L.eq_trans.
+ - contradiction.
+ Qed.
+
+ Definition beq (x y : t) :=
+ match x, y with
+ | None, None => true
+ | Some x, Some y => L.beq x y
+ | Some _, None | None, Some _ => false
+ end.
+
+ Lemma beq_correct: forall x y, beq x y = true -> eq x y.
+ Proof.
+ unfold beq, eq.
+ destruct x; destruct y; trivial; try congruence.
+ apply L.beq_correct.
+ Qed.
+
+ Definition ge (x y : t) :=
+ match x, y with
+ | None, Some _ => False
+ | _, None => True
+ | Some a, Some b => L.ge a b
+ end.
+
+ Lemma ge_refl: forall x y, eq x y -> ge x y.
+ Proof.
+ unfold eq, ge.
+ destruct x; destruct y; trivial.
+ apply L.ge_refl.
+ Qed.
+
+ Lemma ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+ Proof.
+ unfold ge.
+ destruct x; destruct y; destruct z; trivial; try contradiction.
+ apply L.ge_trans.
+ Qed.
+
+ Definition bot: t := None.
+ Lemma ge_bot: forall x, ge x bot.
+ Proof.
+ unfold ge, bot.
+ destruct x; trivial.
+ Qed.
+
+ Definition lub (a b : t) :=
+ match a, b with
+ | None, _ => b
+ | _, None => a
+ | (Some x), (Some y) => Some (L.lub x y)
+ end.
+
+ Lemma ge_lub_left: forall x y, ge (lub x y) x.
+ Proof.
+ unfold ge, lub.
+ destruct x; destruct y; trivial.
+ - apply L.ge_lub_left.
+ - apply L.ge_refl.
+ apply L.eq_refl.
+ Qed.
+
+ Lemma ge_lub_right: forall x y, ge (lub x y) y.
+ Proof.
+ unfold ge, lub.
+ destruct x; destruct y; trivial.
+ - apply L.ge_lub_right.
+ - apply L.ge_refl.
+ apply L.eq_refl.
+ Qed.
+End ADD_BOTTOM.
+
+Module RB := ADD_BOTTOM(RELATION).
+Module DS := Dataflow_Solver(RB)(NodeSetForward).
+
+Definition kill_sym_val (dst : reg) (sv : sym_val) :=
+ match sv with
+ | SMove src => if peq dst src then true else false
+ | SOp op args => List.existsb (peq dst) args
+ | SLoad chunk addr args => List.existsb (peq dst) args
+ end.
+
+Definition kill_reg (dst : reg) (rel : RELATION.t) :=
+ PTree.filter1 (fun x => negb (kill_sym_val dst x))
+ (PTree.remove dst rel).
+
+Definition kill_sym_val_mem (sv: sym_val) :=
+ match sv with
+ | SMove _ => false
+ | SOp op _ => op_depends_on_memory op
+ | SLoad _ _ _ => true
+ end.
+
+Definition kill_sym_val_store chunk addr args (sv: sym_val) :=
+ match sv with
+ | SMove _ => false
+ | SOp op _ => op_depends_on_memory op
+ | SLoad chunk' addr' args' => may_overlap chunk addr args chunk' addr' args'
+ end.
+
+Definition kill_mem (rel : RELATION.t) :=
+ PTree.filter1 (fun x => negb (kill_sym_val_mem x)) rel.
+
+Definition forward_move (rel : RELATION.t) (x : reg) : reg :=
+ match rel ! x with
+ | Some (SMove org) => org
+ | _ => x
+ end.
+
+Definition kill_store1 chunk addr args rel :=
+ PTree.filter1 (fun x => negb (kill_sym_val_store chunk addr args x)) rel.
+
+Definition kill_store chunk addr args rel :=
+ kill_store1 chunk addr (List.map (forward_move rel) args) rel.
+
+Definition move (src dst : reg) (rel : RELATION.t) :=
+ PTree.set dst (SMove (forward_move rel src)) (kill_reg dst rel).
+
+Definition find_op_fold op args (already : option reg) x sv :=
+ match already with
+ | Some found => already
+ | None =>
+ match sv with
+ | (SOp op' args') =>
+ if (eq_operation op op') && (eq_args args args')
+ then Some x
+ else None
+ | _ => None
+ end
+ end.
+
+Definition find_op (rel : RELATION.t) (op : operation) (args : list reg) :=
+ PTree.fold (find_op_fold op args) rel None.
+
+Definition find_load_fold chunk addr args (already : option reg) x sv :=
+ match already with
+ | Some found => already
+ | None =>
+ match sv with
+ | (SLoad chunk' addr' args') =>
+ if (chunk_eq chunk chunk') &&
+ (eq_addressing addr addr') &&
+ (eq_args args args')
+ then Some x
+ else None
+ | _ => None
+ end
+ end.
+
+Definition find_load (rel : RELATION.t) (chunk : memory_chunk) (addr : addressing) (args : list reg) :=
+ PTree.fold (find_load_fold chunk addr args) rel None.
+
+Definition oper2 (op: operation) (dst : reg) (args : list reg)
+ (rel : RELATION.t) :=
+ let rel' := kill_reg dst rel in
+ PTree.set dst (SOp op (List.map (forward_move rel') args)) rel'.
+
+Definition oper1 (op: operation) (dst : reg) (args : list reg)
+ (rel : RELATION.t) :=
+ if List.in_dec peq dst args
+ then kill_reg dst rel
+ else oper2 op dst args rel.
+
+Definition oper (op: operation) (dst : reg) (args : list reg)
+ (rel : RELATION.t) :=
+ match find_op rel op (List.map (forward_move rel) args) with
+ | Some r => move r dst rel
+ | None => oper1 op dst args rel
+ end.
+
+Definition gen_oper (op: operation) (dst : reg) (args : list reg)
+ (rel : RELATION.t) :=
+ match op, args with
+ | Omove, src::nil => move src dst rel
+ | _, _ => oper op dst args rel
+ end.
+
+Definition load2 (chunk: memory_chunk) (addr : addressing)
+ (dst : reg) (args : list reg) (rel : RELATION.t) :=
+ let rel' := kill_reg dst rel in
+ PTree.set dst (SLoad chunk addr (List.map (forward_move rel') args)) rel'.
+
+Definition load1 (chunk: memory_chunk) (addr : addressing)
+ (dst : reg) (args : list reg) (rel : RELATION.t) :=
+ if List.in_dec peq dst args
+ then kill_reg dst rel
+ else load2 chunk addr dst args rel.
+
+Definition load (chunk: memory_chunk) (addr : addressing)
+ (dst : reg) (args : list reg) (rel : RELATION.t) :=
+ match find_load rel chunk addr (List.map (forward_move rel) args) with
+ | Some r => move r dst rel
+ | None => load1 chunk addr dst args rel
+ end.
+
+(* NO LONGER NEEDED
+Fixpoint list_represents { X : Type } (l : list (positive*X)) (tr : PTree.t X) : Prop :=
+ match l with
+ | nil => True
+ | (r,sv)::tail => (tr ! r) = Some sv /\ list_represents tail tr
+ end.
+
+Lemma elements_represent :
+ forall { X : Type },
+ forall tr : (PTree.t X),
+ (list_represents (PTree.elements tr) tr).
+Proof.
+ intros.
+ generalize (PTree.elements_complete tr).
+ generalize (PTree.elements tr).
+ induction l; simpl; trivial.
+ intro COMPLETE.
+ destruct a as [ r sv ].
+ split.
+ {
+ apply COMPLETE.
+ left; reflexivity.
+ }
+ apply IHl; auto.
+Qed.
+*)
+
+Definition apply_instr instr (rel : RELATION.t) : RB.t :=
+ match instr with
+ | Inop _
+ | Icond _ _ _ _ _
+ | Ijumptable _ _ => Some rel
+ | Istore chunk addr args _ _ => Some (kill_store chunk addr args rel)
+ | Iop op args dst _ => Some (gen_oper op dst args rel)
+ | Iload trap chunk addr args dst _ => Some (load chunk addr dst args rel)
+ | Icall _ _ _ dst _ => Some (kill_reg dst (kill_mem rel))
+ | Ibuiltin _ _ res _ => Some (RELATION.top) (* TODO (kill_builtin_res res x) *)
+ | Itailcall _ _ _ | Ireturn _ => RB.bot
+ end.
+
+Definition apply_instr' code (pc : node) (ro : RB.t) : RB.t :=
+ match ro with
+ | None => None
+ | Some x =>
+ match code ! pc with
+ | None => RB.bot
+ | Some instr => apply_instr instr x
+ end
+ end.
+
+Definition forward_map (f : RTL.function) := DS.fixpoint
+ (RTL.fn_code f) RTL.successors_instr
+ (apply_instr' (RTL.fn_code f)) (RTL.fn_entrypoint f) (Some RELATION.top).
+
+Definition forward_move_b (rb : RB.t) (x : reg) :=
+ match rb with
+ | None => x
+ | Some rel => forward_move rel x
+ end.
+
+Definition subst_arg (fmap : option (PMap.t RB.t)) (pc : node) (x : reg) : reg :=
+ match fmap with
+ | None => x
+ | Some inv => forward_move_b (PMap.get pc inv) x
+ end.
+
+Definition subst_args fmap pc := List.map (subst_arg fmap pc).
+
+(* Transform *)
+Definition find_op_in_fmap fmap pc op args :=
+ match fmap with
+ | None => None
+ | Some map =>
+ match PMap.get pc map with
+ | Some rel => find_op rel op args
+ | None => None
+ end
+ end.
+
+Definition find_load_in_fmap fmap pc chunk addr args :=
+ match fmap with
+ | None => None
+ | Some map =>
+ match PMap.get pc map with
+ | Some rel => find_load rel chunk addr args
+ | None => None
+ end
+ end.
+
+Definition transf_instr (fmap : option (PMap.t RB.t))
+ (pc: node) (instr: instruction) :=
+ match instr with
+ | Iop op args dst s =>
+ let args' := subst_args fmap pc args in
+ match (if is_trivial_op op then None else find_op_in_fmap fmap pc op args') with
+ | None => Iop op args' dst s
+ | Some src => Iop Omove (src::nil) dst s
+ end
+ | Iload trap chunk addr args dst s =>
+ let args' := subst_args fmap pc args in
+ match find_load_in_fmap fmap pc chunk addr args' with
+ | None => Iload trap chunk addr args' dst s
+ | Some src => Iop Omove (src::nil) dst s
+ end
+ | Istore chunk addr args src s =>
+ Istore chunk addr (subst_args fmap pc args) src s
+ | Icall sig ros args dst s =>
+ Icall sig ros (subst_args fmap pc args) dst s
+ | Itailcall sig ros args =>
+ Itailcall sig ros (subst_args fmap pc args)
+ | Icond cond args s1 s2 i =>
+ Icond cond (subst_args fmap pc args) s1 s2 i
+ | Ijumptable arg tbl =>
+ Ijumptable (subst_arg fmap pc arg) tbl
+ | Ireturn (Some arg) =>
+ Ireturn (Some (subst_arg fmap pc arg))
+ | _ => instr
+ end.
+
+Definition transf_function (f: function) : function :=
+ {| fn_sig := f.(fn_sig);
+ fn_params := f.(fn_params);
+ fn_stacksize := f.(fn_stacksize);
+ fn_code := PTree.map (transf_instr (forward_map f)) f.(fn_code);
+ fn_entrypoint := f.(fn_entrypoint) |}.
+
+
+Definition transf_fundef (fd: fundef) : fundef :=
+ AST.transf_fundef transf_function fd.
+
+Definition transf_program (p: program) : program :=
+ transform_program transf_fundef p.
+
+Definition match_prog (p tp: RTL.program) :=
+ match_program (fun ctx f tf => tf = transf_fundef f) eq p tp.
+
+Lemma transf_program_match:
+ forall p, match_prog p (transf_program p).
+Proof.
+ intros. eapply match_transform_program; eauto.
+Qed.
diff --git a/backend/CSE2proof.v b/backend/CSE2proof.v
new file mode 100644
index 00000000..309ccce1
--- /dev/null
+++ b/backend/CSE2proof.v
@@ -0,0 +1,1715 @@
+(*
+Replace available expressions by the register containing their value.
+
+Proofs.
+
+David Monniaux, CNRS, VERIMAG
+ *)
+
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps CSE2depsproof.
+Require Import Lia.
+
+Lemma args_unaffected:
+ forall rs : regset,
+ forall dst : reg,
+ forall v,
+ forall args : list reg,
+ existsb (fun y : reg => peq dst y) args = false ->
+ (rs # dst <- v ## args) = (rs ## args).
+Proof.
+ induction args; simpl; trivial.
+ destruct (peq dst a) as [EQ | NEQ]; simpl.
+ { discriminate.
+ }
+ intro EXIST.
+ f_equal.
+ {
+ apply Regmap.gso.
+ congruence.
+ }
+ apply IHargs.
+ assumption.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section SAME_MEMORY.
+ Variable m : mem.
+
+Definition sem_sym_val sym rs (v : option val) : Prop :=
+ match sym with
+ | SMove src => v = Some (rs # src)
+ | SOp op args =>
+ v = (eval_operation genv sp op (rs ## args) m)
+ | SLoad chunk addr args =>
+ match eval_addressing genv sp addr rs##args with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => v = Some dat
+ | None => v = None \/ v = Some Vundef
+ end
+ | None => v = None \/ v = Some Vundef
+ end
+ end.
+
+Definition sem_reg (rel : RELATION.t) (x : reg) (rs : regset) (v : val) : Prop :=
+ match rel ! x with
+ | None => True
+ | Some sym => sem_sym_val sym rs (Some (rs # x))
+ end.
+
+Definition sem_rel (rel : RELATION.t) (rs : regset) :=
+ forall x : reg, (sem_reg rel x rs (rs # x)).
+
+Definition sem_rel_b (relb : RB.t) (rs : regset) :=
+ match relb with
+ | Some rel => sem_rel rel rs
+ | None => False
+ end.
+
+Definition fmap_sem (fmap : option (PMap.t RB.t))
+ (pc : node) (rs : regset) :=
+ match fmap with
+ | None => True
+ | Some m => sem_rel_b (PMap.get pc m) rs
+ end.
+
+Lemma subst_arg_ok:
+ forall f,
+ forall pc,
+ forall rs,
+ forall arg,
+ fmap_sem (forward_map f) pc rs ->
+ rs # (subst_arg (forward_map f) pc arg) = rs # arg.
+Proof.
+ intros until arg.
+ intro SEM.
+ unfold fmap_sem in SEM.
+ destruct (forward_map f) as [map |]in *; trivial.
+ simpl.
+ unfold sem_rel_b, sem_rel, sem_reg in *.
+ destruct (map # pc).
+ 2: contradiction.
+ pose proof (SEM arg) as SEMarg.
+ simpl. unfold forward_move.
+ unfold sem_sym_val in *.
+ destruct (t ! arg); trivial.
+ destruct s; congruence.
+Qed.
+
+Lemma subst_args_ok:
+ forall f,
+ forall pc,
+ forall rs,
+ fmap_sem (forward_map f) pc rs ->
+ forall args,
+ rs ## (subst_args (forward_map f) pc args) = rs ## args.
+Proof.
+ induction args; trivial.
+ simpl.
+ f_equal.
+ apply subst_arg_ok; assumption.
+ assumption.
+Qed.
+
+Lemma kill_reg_sound :
+ forall rel : RELATION.t,
+ forall dst : reg,
+ forall rs,
+ forall v,
+ sem_rel rel rs ->
+ sem_rel (kill_reg dst rel) (rs # dst <- v).
+Proof.
+ unfold sem_rel, kill_reg, sem_reg, sem_sym_val.
+ intros until v.
+ intros REL x.
+ rewrite PTree.gfilter1.
+ destruct (Pos.eq_dec dst x).
+ {
+ subst x.
+ rewrite PTree.grs.
+ trivial.
+ }
+ rewrite PTree.gro by congruence.
+ rewrite Regmap.gso by congruence.
+ destruct (rel ! x) as [relx | ] eqn:RELx; trivial.
+ unfold kill_sym_val.
+ pose proof (REL x) as RELinstx.
+ rewrite RELx in RELinstx.
+ destruct relx eqn:SYMVAL.
+ {
+ destruct (peq dst src); simpl.
+ { reflexivity. }
+ rewrite Regmap.gso by congruence.
+ assumption.
+ }
+ { destruct existsb eqn:EXISTS; simpl.
+ { reflexivity. }
+ rewrite args_unaffected by exact EXISTS.
+ assumption.
+ }
+ { destruct existsb eqn:EXISTS; simpl.
+ { reflexivity. }
+ rewrite args_unaffected by exact EXISTS.
+ assumption.
+ }
+Qed.
+
+Lemma write_same:
+ forall rs : regset,
+ forall src dst : reg,
+ (rs # dst <- (rs # src)) # src = rs # src.
+Proof.
+ intros.
+ destruct (peq src dst).
+ {
+ subst dst.
+ apply Regmap.gss.
+ }
+ rewrite Regmap.gso by congruence.
+ reflexivity.
+Qed.
+
+Lemma move_sound :
+ forall rel : RELATION.t,
+ forall src dst : reg,
+ forall rs,
+ sem_rel rel rs ->
+ sem_rel (move src dst rel) (rs # dst <- (rs # src)).
+Proof.
+ intros until rs. intros REL x.
+ pose proof (kill_reg_sound rel dst rs (rs # src) REL x) as KILL.
+ pose proof (REL src) as RELsrc.
+ unfold move.
+ destruct (peq x dst).
+ {
+ subst x.
+ unfold sem_reg.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ unfold sem_reg in *.
+ simpl.
+ unfold forward_move.
+ destruct (rel ! src) as [ sv |]; simpl.
+ destruct sv eqn:SV; simpl in *.
+ {
+ destruct (peq dst src0).
+ {
+ subst src0.
+ rewrite Regmap.gss.
+ reflexivity.
+ }
+ rewrite Regmap.gso by congruence.
+ assumption.
+ }
+ all: f_equal; symmetry; apply write_same.
+ }
+ rewrite Regmap.gso by congruence.
+ unfold sem_reg.
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso in KILL by congruence.
+ exact KILL.
+Qed.
+
+Lemma move_cases_neq:
+ forall dst rel a,
+ a <> dst ->
+ (forward_move (kill_reg dst rel) a) <> dst.
+Proof.
+ intros until a. intro NEQ.
+ unfold kill_reg, forward_move.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by congruence.
+ destruct (rel ! a); simpl.
+ 2: congruence.
+ destruct s.
+ {
+ unfold kill_sym_val.
+ destruct peq; simpl; congruence.
+ }
+ all: simpl;
+ destruct negb; simpl; congruence.
+Qed.
+
+Lemma args_replace_dst :
+ forall rel,
+ forall args : list reg,
+ forall dst : reg,
+ forall rs : regset,
+ forall v,
+ (sem_rel rel rs) ->
+ not (In dst args) ->
+ (rs # dst <- v)
+ ## (map
+ (forward_move (kill_reg dst rel)) args) = rs ## args.
+Proof.
+ induction args; simpl.
+ 1: reflexivity.
+ intros until v.
+ intros REL NOT_IN.
+ rewrite IHargs by auto.
+ f_equal.
+ pose proof (REL a) as RELa.
+ rewrite Regmap.gso by (apply move_cases_neq; auto).
+ unfold kill_reg.
+ unfold sem_reg in RELa.
+ unfold forward_move.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by auto.
+ destruct (rel ! a); simpl; trivial.
+ destruct s; simpl in *; destruct negb; simpl; congruence.
+Qed.
+
+Lemma oper2_sound :
+ forall rel : RELATION.t,
+ forall op : operation,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall v,
+ sem_rel rel rs ->
+ not (In dst args) ->
+ eval_operation genv sp op (rs ## args) m = Some v ->
+ sem_rel (oper2 op dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL NOT_IN EVAL x.
+ pose proof (kill_reg_sound rel dst rs v REL x) as KILL.
+ unfold oper2.
+ destruct (peq x dst).
+ {
+ subst x.
+ unfold sem_reg.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ simpl.
+ rewrite args_replace_dst by auto.
+ symmetry.
+ assumption.
+ }
+ rewrite Regmap.gso by congruence.
+ unfold sem_reg.
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso in KILL by congruence.
+ exact KILL.
+Qed.
+
+Lemma oper1_sound :
+ forall rel : RELATION.t,
+ forall op : operation,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall v,
+ sem_rel rel rs ->
+ eval_operation genv sp op (rs ## args) m = Some v ->
+ sem_rel (oper1 op dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL EVAL.
+ unfold oper1.
+ destruct in_dec.
+ {
+ apply kill_reg_sound; auto.
+ }
+ apply oper2_sound; auto.
+Qed.
+
+Lemma find_op_sound :
+ forall rel : RELATION.t,
+ forall op : operation,
+ forall src : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ find_op rel op args = Some src ->
+ (eval_operation genv sp op (rs ## args) m) = Some (rs # src).
+Proof.
+ intros until rs.
+ unfold find_op.
+ rewrite PTree.fold_spec.
+ intro REL.
+ assert (
+ forall start,
+ match start with
+ | None => True
+ | Some src => eval_operation genv sp op rs ## args m = Some rs # src
+ end -> fold_left
+ (fun (a : option reg) (p : positive * sym_val) =>
+ find_op_fold op args a (fst p) (snd p)) (PTree.elements rel) start =
+ Some src ->
+ eval_operation genv sp op rs ## args m = Some rs # src) as REC.
+ {
+ unfold sem_rel, sem_reg in REL.
+ generalize (PTree.elements_complete rel).
+ generalize (PTree.elements rel).
+ induction l; simpl.
+ {
+ intros.
+ subst start.
+ assumption.
+ }
+ destruct a as [r sv]; simpl.
+ intros COMPLETE start GEN.
+ apply IHl.
+ {
+ intros.
+ apply COMPLETE.
+ right.
+ assumption.
+ }
+ unfold find_op_fold.
+ destruct start.
+ assumption.
+ destruct sv; trivial.
+ destruct eq_operation; trivial.
+ subst op0.
+ destruct eq_args; trivial.
+ subst args0.
+ simpl.
+ assert ((rel ! r) = Some (SOp op args)) as RELatr.
+ {
+ apply COMPLETE.
+ left.
+ reflexivity.
+ }
+ pose proof (REL r) as RELr.
+ rewrite RELatr in RELr.
+ simpl in RELr.
+ symmetry.
+ assumption.
+ }
+ apply REC; auto.
+Qed.
+
+
+Lemma find_load_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall src : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ find_load rel chunk addr args = Some src ->
+ match eval_addressing genv sp addr rs##args with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end.
+Proof.
+ intros until rs.
+ unfold find_load.
+ rewrite PTree.fold_spec.
+ intro REL.
+ assert (
+ forall start,
+ match start with
+ | None => True
+ | Some src =>
+ match eval_addressing genv sp addr rs##args with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end
+ end ->
+ fold_left
+ (fun (a : option reg) (p : positive * sym_val) =>
+ find_load_fold chunk addr args a (fst p) (snd p)) (PTree.elements rel) start =
+ Some src ->
+ match eval_addressing genv sp addr rs##args with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end) as REC.
+
+ {
+ unfold sem_rel, sem_reg in REL.
+ generalize (PTree.elements_complete rel).
+ generalize (PTree.elements rel).
+ induction l; simpl.
+ {
+ intros.
+ subst start.
+ assumption.
+ }
+ destruct a as [r sv]; simpl.
+ intros COMPLETE start GEN.
+ apply IHl.
+ {
+ intros.
+ apply COMPLETE.
+ right.
+ assumption.
+ }
+ unfold find_load_fold.
+ destruct start.
+ assumption.
+ destruct sv; trivial.
+ destruct chunk_eq; trivial.
+ subst chunk0.
+ destruct eq_addressing; trivial.
+ subst addr0.
+ destruct eq_args; trivial.
+ subst args0.
+ simpl.
+ assert ((rel ! r) = Some (SLoad chunk addr args)) as RELatr.
+ {
+ apply COMPLETE.
+ left.
+ reflexivity.
+ }
+ pose proof (REL r) as RELr.
+ rewrite RELatr in RELr.
+ simpl in RELr.
+ destruct eval_addressing.
+ { destruct Mem.loadv.
+ congruence.
+ destruct RELr; congruence.
+ }
+ destruct RELr; congruence.
+ }
+ apply REC; auto.
+Qed.
+
+
+Lemma find_load_sound' :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall src : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ forall v,
+ sem_rel rel rs ->
+ find_load rel chunk addr args = Some src ->
+ eval_addressing genv sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ v = rs # src.
+Proof.
+ intros until v. intros REL FINDLOAD ADDR LOAD.
+ pose proof (find_load_sound rel chunk addr src args rs REL FINDLOAD) as Z.
+ destruct eval_addressing in *.
+ {
+ replace a with v0 in * by congruence.
+ destruct Mem.loadv in * ; congruence.
+ }
+ discriminate.
+Qed.
+
+Lemma find_load_notrap1_sound' :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall src : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ find_load rel chunk addr args = Some src ->
+ eval_addressing genv sp addr rs##args = None ->
+ rs # src = Vundef.
+Proof.
+ intros until rs. intros REL FINDLOAD ADDR.
+ pose proof (find_load_sound rel chunk addr src args rs REL FINDLOAD) as Z.
+ rewrite ADDR in Z.
+ assumption.
+Qed.
+
+Lemma find_load_notrap2_sound' :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall src : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ sem_rel rel rs ->
+ find_load rel chunk addr args = Some src ->
+ eval_addressing genv sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs # src = Vundef.
+Proof.
+ intros until a. intros REL FINDLOAD ADDR LOAD.
+ pose proof (find_load_sound rel chunk addr src args rs REL FINDLOAD) as Z.
+ rewrite ADDR in Z.
+ destruct Mem.loadv.
+ discriminate.
+ assumption.
+Qed.
+
+Lemma forward_move_map:
+ forall rel args rs,
+ sem_rel rel rs ->
+ rs ## (map (forward_move rel) args) = rs ## args.
+Proof.
+ induction args; simpl; trivial.
+ intros rs REL.
+ f_equal.
+ 2: (apply IHargs; assumption).
+ unfold forward_move, sem_rel, sem_reg, sem_sym_val in *.
+ pose proof (REL a) as RELa.
+ destruct (rel ! a); trivial.
+ destruct s; congruence.
+Qed.
+
+
+Lemma forward_move_rs:
+ forall rel arg rs,
+ sem_rel rel rs ->
+ rs # (forward_move rel arg) = rs # arg.
+Proof.
+ unfold forward_move, sem_rel, sem_reg, sem_sym_val in *.
+ intros until rs.
+ intro REL.
+ pose proof (REL arg) as RELarg.
+ destruct (rel ! arg); trivial.
+ destruct s; congruence.
+Qed.
+
+Lemma oper_sound :
+ forall rel : RELATION.t,
+ forall op : operation,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall v,
+ sem_rel rel rs ->
+ eval_operation genv sp op (rs ## args) m = Some v ->
+ sem_rel (oper op dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL EVAL.
+ unfold oper.
+ destruct find_op eqn:FIND.
+ {
+ assert (eval_operation genv sp op rs ## (map (forward_move rel) args) m = Some rs # r) as FIND_OP.
+ {
+ apply (find_op_sound rel); trivial.
+ }
+ rewrite forward_move_map in FIND_OP by assumption.
+ replace v with (rs # r) by congruence.
+ apply move_sound; auto.
+ }
+ apply oper1_sound; trivial.
+Qed.
+
+Lemma gen_oper_sound :
+ forall rel : RELATION.t,
+ forall op : operation,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall v,
+ sem_rel rel rs ->
+ eval_operation genv sp op (rs ## args) m = Some v ->
+ sem_rel (gen_oper op dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL EVAL.
+ unfold gen_oper.
+ destruct op.
+ { destruct args as [ | h0 t0].
+ apply oper_sound; auto.
+ destruct t0.
+ {
+ simpl in *.
+ replace v with (rs # h0) by congruence.
+ apply move_sound; auto.
+ }
+ apply oper_sound; auto.
+ }
+ all: apply oper_sound; auto.
+Qed.
+
+
+Lemma load2_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ forall v,
+ sem_rel rel rs ->
+ not (In dst args) ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ sem_rel (load2 chunk addr dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL NOT_IN ADDR LOAD x.
+ pose proof (kill_reg_sound rel dst rs v REL x) as KILL.
+ unfold load2.
+ destruct (peq x dst).
+ {
+ subst x.
+ unfold sem_reg.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ simpl.
+ rewrite args_replace_dst by auto.
+ destruct eval_addressing.
+ {
+ replace a with v0 in * by congruence.
+ destruct Mem.loadv; congruence.
+ }
+ discriminate.
+ }
+ rewrite Regmap.gso by congruence.
+ unfold sem_reg.
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso in KILL by congruence.
+ exact KILL.
+Qed.
+
+Lemma load2_notrap1_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ not (In dst args) ->
+ eval_addressing genv sp addr (rs ## args) = None ->
+ sem_rel (load2 chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until rs.
+ intros REL NOT_IN ADDR x.
+ pose proof (kill_reg_sound rel dst rs Vundef REL x) as KILL.
+ unfold load2.
+ destruct (peq x dst).
+ {
+ subst x.
+ unfold sem_reg.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ simpl.
+ rewrite args_replace_dst by auto.
+ rewrite ADDR.
+ right.
+ trivial.
+ }
+ rewrite Regmap.gso by congruence.
+ unfold sem_reg.
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso in KILL by congruence.
+ exact KILL.
+Qed.
+
+Lemma load2_notrap2_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ sem_rel rel rs ->
+ not (In dst args) ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = None ->
+ sem_rel (load2 chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until a.
+ intros REL NOT_IN ADDR LOAD x.
+ pose proof (kill_reg_sound rel dst rs Vundef REL x) as KILL.
+ unfold load2.
+ destruct (peq x dst).
+ {
+ subst x.
+ unfold sem_reg.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ simpl.
+ rewrite args_replace_dst by auto.
+ rewrite ADDR.
+ rewrite LOAD.
+ right; trivial.
+ }
+ rewrite Regmap.gso by congruence.
+ unfold sem_reg.
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso in KILL by congruence.
+ exact KILL.
+Qed.
+
+Lemma load1_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ forall v,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ sem_rel (load1 chunk addr dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL ADDR LOAD.
+ unfold load1.
+ destruct in_dec.
+ {
+ apply kill_reg_sound; auto.
+ }
+ apply load2_sound with (a := a); auto.
+Qed.
+
+Lemma load1_notrap1_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = None ->
+ sem_rel (load1 chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until rs.
+ intros REL ADDR LOAD.
+ unfold load1.
+ destruct in_dec.
+ {
+ apply kill_reg_sound; auto.
+ }
+ apply load2_notrap1_sound; auto.
+Qed.
+
+Lemma load1_notrap2_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = None ->
+ sem_rel (load1 chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until a.
+ intros REL ADDR LOAD.
+ unfold load1.
+ destruct in_dec.
+ {
+ apply kill_reg_sound; auto.
+ }
+ apply load2_notrap2_sound with (a := a); auto.
+Qed.
+
+Lemma load_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ forall v,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ sem_rel (load chunk addr dst args rel) (rs # dst <- v).
+Proof.
+ intros until v.
+ intros REL ADDR LOAD.
+ unfold load.
+ destruct find_load as [src | ] eqn:FIND.
+ {
+ assert (match eval_addressing genv sp addr rs## (map (forward_move rel) args) with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end) as FIND_LOAD.
+ {
+ apply (find_load_sound rel); trivial.
+ }
+ rewrite forward_move_map in FIND_LOAD by assumption.
+ destruct eval_addressing in *.
+ 2: discriminate.
+ replace v0 with a in * by congruence.
+ destruct Mem.loadv in *.
+ 2: discriminate.
+ replace v with (rs # src) by congruence.
+ apply move_sound; auto.
+ }
+ apply load1_sound with (a := a); trivial.
+Qed.
+
+Lemma load_notrap1_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = None ->
+ sem_rel (load chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until rs.
+ intros REL ADDR.
+ unfold load.
+ destruct find_load as [src | ] eqn:FIND.
+ {
+ assert (match eval_addressing genv sp addr rs## (map (forward_move rel) args) with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end) as FIND_LOAD.
+ {
+ apply (find_load_sound rel); trivial.
+ }
+ rewrite forward_move_map in FIND_LOAD by assumption.
+ destruct eval_addressing in *.
+ discriminate.
+ rewrite <- FIND_LOAD.
+ apply move_sound; auto.
+ }
+ apply load1_notrap1_sound; trivial.
+Qed.
+
+Lemma load_notrap2_sound :
+ forall rel : RELATION.t,
+ forall chunk : memory_chunk,
+ forall addr : addressing,
+ forall dst : reg,
+ forall args: list reg,
+ forall rs : regset,
+ forall a,
+ sem_rel rel rs ->
+ eval_addressing genv sp addr (rs ## args) = Some a ->
+ Mem.loadv chunk m a = None ->
+ sem_rel (load chunk addr dst args rel) (rs # dst <- Vundef).
+Proof.
+ intros until a.
+ intros REL ADDR.
+ unfold load.
+ destruct find_load as [src | ] eqn:FIND.
+ {
+ assert (match eval_addressing genv sp addr rs## (map (forward_move rel) args) with
+ | Some a => match Mem.loadv chunk m a with
+ | Some dat => rs#src = dat
+ | None => rs#src = Vundef
+ end
+ | None => rs#src = Vundef
+ end) as FIND_LOAD.
+ {
+ apply (find_load_sound rel); trivial.
+ }
+ rewrite forward_move_map in FIND_LOAD by assumption.
+ rewrite ADDR in FIND_LOAD.
+ destruct Mem.loadv; intro.
+ discriminate.
+ rewrite <- FIND_LOAD.
+ apply move_sound; auto.
+ }
+ apply load1_notrap2_sound; trivial.
+Qed.
+
+Lemma kill_reg_weaken:
+ forall res mpc rs,
+ sem_rel mpc rs ->
+ sem_rel (kill_reg res mpc) rs.
+Proof.
+ intros until rs.
+ intros REL x.
+ pose proof (REL x) as RELx.
+ unfold kill_reg, sem_reg in *.
+ rewrite PTree.gfilter1.
+ destruct (peq res x).
+ { subst x.
+ rewrite PTree.grs.
+ reflexivity.
+ }
+ rewrite PTree.gro by congruence.
+ destruct (mpc ! x) as [sv | ]; trivial.
+ destruct negb; trivial.
+Qed.
+
+Lemma top_ok:
+ forall rs, sem_rel RELATION.top rs.
+Proof.
+ unfold sem_rel, sem_reg, RELATION.top.
+ intros.
+ rewrite PTree.gempty.
+ reflexivity.
+Qed.
+
+Lemma sem_rel_ge:
+ forall r1 r2 : RELATION.t,
+ (RELATION.ge r1 r2) ->
+ forall rs : regset,
+ (sem_rel r2 rs) -> (sem_rel r1 rs).
+Proof.
+ intros r1 r2 GE rs RE x.
+ pose proof (RE x) as REx.
+ pose proof (GE x) as GEx.
+ unfold sem_reg in *.
+ destruct (r1 ! x) as [r1x | ] in *;
+ destruct (r2 ! x) as [r2x | ] in *;
+ congruence.
+Qed.
+End SAME_MEMORY.
+
+Lemma kill_mem_sound :
+ forall m m' : mem,
+ forall rel : RELATION.t,
+ forall rs,
+ sem_rel m rel rs -> sem_rel m' (kill_mem rel) rs.
+Proof.
+ unfold sem_rel, sem_reg.
+ intros until rs.
+ intros SEM x.
+ pose proof (SEM x) as SEMx.
+ unfold kill_mem.
+ rewrite PTree.gfilter1.
+ unfold kill_sym_val_mem.
+ destruct (rel ! x) as [ sv | ].
+ 2: reflexivity.
+ destruct sv; simpl in *; trivial.
+ {
+ destruct op_depends_on_memory eqn:DEPENDS; simpl; trivial.
+ rewrite SEMx.
+ apply op_depends_on_memory_correct; auto.
+ }
+Qed.
+
+Lemma kill_store_sound :
+ forall m m' : mem,
+ forall rel : RELATION.t,
+ forall chunk addr args a v rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (Mem.storev chunk m a v) = Some m' ->
+ sem_rel m rel rs -> sem_rel m' (kill_store chunk addr args rel) rs.
+Proof.
+ unfold sem_rel, sem_reg.
+ intros until rs.
+ intros ADDR STORE SEM x.
+ pose proof (SEM x) as SEMx.
+ unfold kill_store, kill_store1.
+ rewrite PTree.gfilter1.
+ destruct (rel ! x) as [ sv | ].
+ 2: reflexivity.
+ destruct sv; simpl in *; trivial.
+ {
+ destruct op_depends_on_memory eqn:DEPENDS; simpl; trivial.
+ rewrite SEMx.
+ apply op_depends_on_memory_correct; auto.
+ }
+ destruct may_overlap eqn:OVERLAP; simpl; trivial.
+ destruct (eval_addressing genv sp addr0 rs ## args0) eqn:ADDR0.
+ {
+ erewrite may_overlap_sound with (args := (map (forward_move rel) args)).
+ all: try eassumption.
+
+ erewrite forward_move_map by eassumption.
+ assumption.
+ }
+ intuition congruence.
+Qed.
+End SOUNDNESS.
+
+Definition match_prog (p tp: RTL.program) :=
+ match_program (fun cu f tf => tf = transf_fundef f) eq p tp.
+
+Lemma transf_program_match:
+ forall p, match_prog p (transf_program p).
+Proof.
+ intros. apply match_transform_program; auto.
+Qed.
+
+Section PRESERVATION.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma functions_translated:
+ forall v f,
+ Genv.find_funct ge v = Some f ->
+ Genv.find_funct tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_transf TRANSL).
+
+Lemma function_ptr_translated:
+ forall v f,
+ Genv.find_funct_ptr ge v = Some f ->
+ Genv.find_funct_ptr tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_ptr_transf TRANSL).
+
+Lemma symbols_preserved:
+ forall id,
+ Genv.find_symbol tge id = Genv.find_symbol ge id.
+Proof (Genv.find_symbol_transf TRANSL).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_transf TRANSL).
+
+Lemma sig_preserved:
+ forall f, funsig (transf_fundef f) = funsig f.
+Proof.
+ destruct f; trivial.
+Qed.
+
+Lemma find_function_translated:
+ forall ros rs fd,
+ find_function ge ros rs = Some fd ->
+ find_function tge ros rs = Some (transf_fundef fd).
+Proof.
+ unfold find_function; intros. destruct ros as [r|id].
+ eapply functions_translated; eauto.
+ rewrite symbols_preserved. destruct (Genv.find_symbol ge id); try congruence.
+ eapply function_ptr_translated; eauto.
+Qed.
+
+Lemma transf_function_at:
+ forall (f : function) (pc : node) (i : instruction),
+ (fn_code f)!pc = Some i ->
+ (fn_code (transf_function f))!pc =
+ Some(transf_instr (forward_map f) pc i).
+Proof.
+ intros until i. intro CODE.
+ unfold transf_function; simpl.
+ rewrite PTree.gmap.
+ unfold option_map.
+ rewrite CODE.
+ reflexivity.
+Qed.
+
+Definition is_killed_in_map (map : PMap.t RB.t) pc res :=
+ match PMap.get pc map with
+ | None => True
+ | Some rel => exists rel', RELATION.ge rel (kill_reg res rel')
+ end.
+
+Definition is_killed_in_fmap fmap pc res :=
+ match fmap with
+ | None => True
+ | Some map => is_killed_in_map map pc res
+ end.
+
+Definition sem_rel_b' := sem_rel_b fundef unit ge.
+Definition fmap_sem' := fmap_sem fundef unit ge.
+Definition subst_arg_ok' := subst_arg_ok fundef unit ge.
+Definition subst_args_ok' := subst_args_ok fundef unit ge.
+Definition kill_mem_sound' := kill_mem_sound fundef unit ge.
+Definition kill_store_sound' := kill_store_sound fundef unit ge.
+
+Lemma sem_rel_b_ge:
+ forall rb1 rb2 : RB.t,
+ (RB.ge rb1 rb2) ->
+ forall sp m,
+ forall rs : regset,
+ (sem_rel_b' sp m rb2 rs) -> (sem_rel_b' sp m rb1 rs).
+Proof.
+ unfold sem_rel_b', sem_rel_b.
+ destruct rb1 as [r1 | ];
+ destruct rb2 as [r2 | ]; simpl;
+ intros GE sp m rs RE; try contradiction.
+ apply sem_rel_ge with (r2 := r2); assumption.
+Qed.
+
+Lemma apply_instr'_bot :
+ forall code,
+ forall pc,
+ RB.eq (apply_instr' code pc RB.bot) RB.bot.
+Proof.
+ reflexivity.
+Qed.
+
+Inductive match_frames: RTL.stackframe -> RTL.stackframe -> Prop :=
+| match_frames_intro: forall res f sp pc rs,
+ (forall m : mem,
+ forall vres, (fmap_sem' sp m (forward_map f) pc rs # res <- vres)) ->
+ match_frames (Stackframe res f sp pc rs)
+ (Stackframe res (transf_function f) sp pc rs).
+
+Inductive match_states: RTL.state -> RTL.state -> Prop :=
+ | match_regular_states: forall stk f sp pc rs m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ (fmap_sem' sp m (forward_map f) pc rs) ->
+ match_states (State stk f sp pc rs m)
+ (State stk' (transf_function f) sp pc rs m)
+ | match_callstates: forall stk f args m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Callstate stk f args m)
+ (Callstate stk' (transf_fundef f) args m)
+ | match_returnstates: forall stk v m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Returnstate stk v m)
+ (Returnstate stk' v m).
+
+Ltac TR_AT :=
+ match goal with
+ | [ A: (fn_code _)!_ = Some _ |- _ ] =>
+ generalize (transf_function_at _ _ _ A); intros
+ end.
+
+Lemma step_simulation:
+ forall S1 t S2, RTL.step ge S1 t S2 ->
+ forall S1', match_states S1 S1' ->
+ exists S2', RTL.step tge S1' t S2' /\ match_states S2 S2'.
+Proof.
+ induction 1; intros S1' MS; inv MS; try TR_AT.
+- (* nop *)
+ econstructor; split. eapply exec_Inop; eauto.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply sem_rel_b_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ unfold sem_rel_b in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+- (* op *)
+ unfold transf_instr in *.
+ destruct (if is_trivial_op op then None else find_op_in_fmap (forward_map f) pc op
+ (subst_args (forward_map f) pc args)) eqn:FIND_OP.
+ {
+ destruct (is_trivial_op op).
+ discriminate.
+ unfold find_op_in_fmap, fmap_sem', fmap_sem in *.
+ destruct (forward_map f) as [map |] eqn:MAP.
+ 2: discriminate.
+ change (@PMap.get (option RELATION.t) pc map) with (map # pc) in *.
+ destruct (map # pc) as [mpc | ] eqn:MPC.
+ 2: discriminate.
+ econstructor; split.
+ {
+ eapply exec_Iop with (v := v); eauto.
+ simpl.
+ rewrite <- subst_args_ok with (genv := ge) (f := f) (pc := pc) (sp := sp) (m := m) in H0.
+ {
+ rewrite MAP in H0.
+ rewrite find_op_sound with (rel := mpc) (src := r) in H0 by assumption.
+ assumption.
+ }
+ unfold fmap_sem. rewrite MAP. rewrite MPC. assumption.
+ }
+ constructor; eauto.
+ unfold fmap_sem', fmap_sem in *.
+ rewrite MAP.
+ apply sem_rel_b_ge with (rb2 := Some (gen_oper op res args mpc)).
+ {
+ replace (Some (gen_oper op res args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ unfold sem_rel_b', sem_rel_b.
+ apply gen_oper_sound; auto.
+ }
+ {
+ econstructor; split.
+ {
+ eapply exec_Iop with (v := v); eauto.
+ rewrite (subst_args_ok' sp m) by assumption.
+ rewrite <- H0.
+ apply eval_operation_preserved. exact symbols_preserved.
+ }
+ constructor; eauto.
+ unfold fmap_sem', fmap_sem in *.
+ unfold find_op_in_fmap, fmap_sem', fmap_sem in *.
+ destruct (forward_map f) as [map |] eqn:MAP.
+ 2: constructor.
+ change (@PMap.get (option RELATION.t) pc map) with (map # pc) in *.
+ destruct (map # pc) as [mpc | ] eqn:MPC.
+ 2: contradiction.
+
+ apply sem_rel_b_ge with (rb2 := Some (gen_oper op res args mpc)).
+ {
+ replace (Some (gen_oper op res args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ unfold sem_rel_b', sem_rel_b.
+ apply gen_oper_sound; auto.
+ }
+
+(* load *)
+- unfold transf_instr in *.
+ destruct find_load_in_fmap eqn:FIND_LOAD.
+ {
+ unfold find_load_in_fmap, fmap_sem', fmap_sem in *.
+ destruct (forward_map f) as [map |] eqn:MAP.
+ 2: discriminate.
+ change (@PMap.get (option RELATION.t) pc map) with (map # pc) in *.
+ destruct (map # pc) as [mpc | ] eqn:MPC.
+ 2: discriminate.
+ econstructor; split.
+ {
+ eapply exec_Iop with (v := v); eauto.
+ simpl.
+ rewrite <- subst_args_ok with (genv := ge) (f := f) (pc := pc) (sp := sp) (m := m) in H0.
+ {
+ f_equal.
+ symmetry.
+ rewrite MAP in H0.
+ eapply find_load_sound' with (genv := ge) (sp := sp) (addr := addr) (args := subst_args (Some map) pc args) (rel := mpc) (src := r) (rs := rs).
+ all: eassumption.
+ }
+ unfold fmap_sem. rewrite MAP. rewrite MPC. assumption.
+ }
+ constructor; eauto.
+ unfold fmap_sem', fmap_sem in *.
+ rewrite MAP.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ unfold sem_rel_b', sem_rel_b.
+ apply load_sound with (a := a); auto.
+ }
+ {
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0.
+ apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload; eauto.
+ rewrite (subst_args_ok' sp m); assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ apply load_sound with (a := a); assumption.
+ }
+
+- (* load notrap1 *)
+ unfold transf_instr in *.
+ destruct find_load_in_fmap eqn:FIND_LOAD.
+ {
+ unfold find_load_in_fmap, fmap_sem', fmap_sem in *.
+ destruct (forward_map f) as [map |] eqn:MAP.
+ 2: discriminate.
+ change (@PMap.get (option RELATION.t) pc map) with (map # pc) in *.
+ destruct (map # pc) as [mpc | ] eqn:MPC.
+ 2: discriminate.
+ econstructor; split.
+ {
+ eapply exec_Iop with (v := (default_notrap_load_value chunk)); eauto.
+ simpl.
+ rewrite <- subst_args_ok with (genv := ge) (f := f) (pc := pc) (sp := sp) (m := m) in H0.
+ {
+ f_equal.
+ rewrite MAP in H0.
+ eapply find_load_notrap1_sound' with (genv := ge) (sp := sp) (addr := addr) (args := subst_args (Some map) pc args) (rel := mpc) (src := r) (rs := rs).
+ all: eassumption.
+ }
+ unfold fmap_sem. rewrite MAP. rewrite MPC. assumption.
+ }
+ constructor; eauto.
+ unfold fmap_sem', fmap_sem in *.
+ rewrite MAP.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ unfold sem_rel_b', sem_rel_b.
+ apply load_notrap1_sound; auto.
+ }
+ {
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = None).
+ rewrite <- H0.
+ apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap1; eauto.
+ rewrite (subst_args_ok' sp m); assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ apply load_notrap1_sound; assumption.
+ }
+
+(* load notrap2 *)
+- unfold transf_instr in *.
+ destruct find_load_in_fmap eqn:FIND_LOAD.
+ {
+ unfold find_load_in_fmap, fmap_sem', fmap_sem in *.
+ destruct (forward_map f) as [map |] eqn:MAP.
+ 2: discriminate.
+ change (@PMap.get (option RELATION.t) pc map) with (map # pc) in *.
+ destruct (map # pc) as [mpc | ] eqn:MPC.
+ 2: discriminate.
+ econstructor; split.
+ {
+ eapply exec_Iop with (v := (default_notrap_load_value chunk)); eauto.
+ simpl.
+ rewrite <- subst_args_ok with (genv := ge) (f := f) (pc := pc) (sp := sp) (m := m) in H0.
+ {
+ f_equal.
+ rewrite MAP in H0.
+ eapply find_load_notrap2_sound' with (genv := ge) (sp := sp) (addr := addr) (args := subst_args (Some map) pc args) (rel := mpc) (src := r) (rs := rs).
+ all: try eassumption.
+ }
+ unfold fmap_sem. rewrite MAP. rewrite MPC. assumption.
+ }
+ constructor; eauto.
+ unfold fmap_sem', fmap_sem in *.
+ rewrite MAP.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ unfold sem_rel_b', sem_rel_b.
+ apply load_notrap2_sound with (a := a); auto.
+ }
+ {
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0.
+ apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap2; eauto.
+ rewrite (subst_args_ok' sp m); assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply sem_rel_b_ge with (rb2 := Some (load chunk addr dst args mpc)).
+ {
+ replace (Some (load chunk addr dst args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ simpl.
+ reflexivity.
+ }
+ apply load_notrap2_sound with (a := a); assumption.
+ }
+
+- (* store *)
+ econstructor. split.
+ {
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Istore; eauto.
+ rewrite (subst_args_ok' sp m); assumption.
+ }
+
+ constructor; auto.
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply sem_rel_b_ge with (rb2 := Some (kill_store chunk addr args mpc)); trivial.
+ {
+ replace (Some (kill_store chunk addr args mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ unfold sem_rel_b in *.
+ rewrite MPC.
+ rewrite H.
+ reflexivity.
+ }
+ eapply (kill_store_sound' sp m); eassumption.
+
+(* call *)
+- econstructor; split.
+ eapply exec_Icall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ rewrite (subst_args_ok' sp m) by assumption.
+ constructor. constructor; auto.
+
+ constructor.
+ {
+ intros m' vres.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply sem_rel_b_ge with (rb2 := Some (kill_reg res (kill_mem mpc))).
+ {
+ replace (Some (kill_reg res (kill_mem mpc))) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply kill_reg_sound.
+ apply (kill_mem_sound' sp m).
+ assumption.
+ }
+
+(* tailcall *)
+- econstructor; split.
+ eapply exec_Itailcall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ rewrite (subst_args_ok' (Vptr stk Ptrofs.zero) m) by assumption.
+ constructor. auto.
+
+(* builtin *)
+- econstructor; split.
+ eapply exec_Ibuiltin; eauto.
+ eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+
+ apply sem_rel_b_ge with (rb2 := Some RELATION.top).
+ {
+ replace (Some RELATION.top) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply top_ok.
+
+
+(* cond *)
+- econstructor; split.
+ eapply exec_Icond; eauto.
+ rewrite (subst_args_ok' sp m); eassumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply sem_rel_b_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl.
+ destruct b; tauto.
+ }
+ unfold apply_instr'.
+ unfold sem_rel_b in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+
+(* jumptbl *)
+- econstructor; split.
+ eapply exec_Ijumptable; eauto.
+ rewrite (subst_arg_ok' sp m); eassumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply sem_rel_b_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl.
+ apply list_nth_z_in with (n := Int.unsigned n).
+ assumption.
+ }
+ unfold apply_instr'.
+ unfold sem_rel_b in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+
+(* return *)
+- destruct or as [arg | ].
+ {
+ econstructor; split.
+ eapply exec_Ireturn; eauto.
+ unfold regmap_optget.
+ rewrite (subst_arg_ok' (Vptr stk Ptrofs.zero) m) by eassumption.
+ constructor; auto.
+ }
+ econstructor; split.
+ eapply exec_Ireturn; eauto.
+ constructor; auto.
+
+
+(* internal function *)
+- simpl. econstructor; split.
+ eapply exec_function_internal; eauto.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem', fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply sem_rel_b_ge with (rb2 := Some RELATION.top).
+ {
+ eapply DS.fixpoint_entry with (code := fn_code f) (successors := successors_instr); try eassumption.
+ }
+ apply top_ok.
+
+(* external function *)
+- econstructor; split.
+ eapply exec_function_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+
+(* return *)
+- inv STACKS. inv H1.
+ econstructor; split.
+ eapply exec_return; eauto.
+ constructor; auto.
+Qed.
+
+
+Lemma transf_initial_states:
+ forall S1, RTL.initial_state prog S1 ->
+ exists S2, RTL.initial_state tprog S2 /\ match_states S1 S2.
+Proof.
+ intros. inv H. econstructor; split.
+ econstructor.
+ eapply (Genv.init_mem_transf TRANSL); eauto.
+ rewrite symbols_preserved. rewrite (match_program_main TRANSL). eauto.
+ eapply function_ptr_translated; eauto.
+ rewrite <- H3; apply sig_preserved.
+ constructor. constructor.
+Qed.
+
+Lemma transf_final_states:
+ forall S1 S2 r, match_states S1 S2 -> RTL.final_state S1 r -> RTL.final_state S2 r.
+Proof.
+ intros. inv H0. inv H. inv STACKS. constructor.
+Qed.
+
+Theorem transf_program_correct:
+ forward_simulation (RTL.semantics prog) (RTL.semantics tprog).
+Proof.
+ eapply forward_simulation_step.
+ apply senv_preserved.
+ eexact transf_initial_states.
+ eexact transf_final_states.
+ exact step_simulation.
+Qed.
+
+End PRESERVATION.
diff --git a/backend/CSEdomain.v b/backend/CSEdomain.v
index 9b1243c8..34ec0118 100644
--- a/backend/CSEdomain.v
+++ b/backend/CSEdomain.v
@@ -43,7 +43,7 @@ Definition eq_list_valnum: forall (x y: list valnum), {x=y}+{x<>y} := list_eq_de
Definition eq_rhs (x y: rhs) : {x=y}+{x<>y}.
Proof.
- generalize chunk_eq eq_operation eq_addressing eq_valnum eq_list_valnum.
+ generalize trapping_mode_eq chunk_eq eq_operation eq_addressing eq_valnum eq_list_valnum.
decide equality.
Defined.
@@ -109,7 +109,16 @@ Inductive rhs_eval_to (valu: valuation) (ge: genv) (sp: val) (m: mem):
| load_eval_to: forall chunk addr vl a v,
eval_addressing ge sp addr (map valu vl) = Some a ->
Mem.loadv chunk m a = Some v ->
- rhs_eval_to valu ge sp m (Load chunk addr vl) v.
+ rhs_eval_to valu ge sp m (Load chunk addr vl) v
+(* | load_notrap1_eval_to: forall chunk addr vl,
+ eval_addressing ge sp addr (map valu vl) = None ->
+ rhs_eval_to valu ge sp m (Load NOTRAP chunk addr vl)
+ (default_notrap_load_value chunk)
+ | load_notrap2_eval_to: forall chunk addr vl a,
+ eval_addressing ge sp addr (map valu vl) = Some a ->
+ Mem.loadv chunk m a = None ->
+ rhs_eval_to valu ge sp m (Load NOTRAP chunk addr vl)
+ (default_notrap_load_value chunk) *).
Inductive equation_holds (valu: valuation) (ge: genv) (sp: val) (m: mem):
equation -> Prop :=
diff --git a/backend/CSEproof.v b/backend/CSEproof.v
index 03c7ecfc..5bbb7508 100644
--- a/backend/CSEproof.v
+++ b/backend/CSEproof.v
@@ -71,7 +71,11 @@ Lemma rhs_eval_to_exten:
Proof.
intros. inv H; simpl in *.
- constructor. rewrite valnums_val_exten by assumption. auto.
-- econstructor; eauto. rewrite valnums_val_exten by assumption. auto.
+- eapply load_eval_to; eauto. rewrite valnums_val_exten by assumption. auto.
+(*
+- apply load_notrap1_eval_to; auto. rewrite valnums_val_exten by assumption. assumption.
+- eapply load_notrap2_eval_to; eauto. rewrite valnums_val_exten by assumption. assumption.
+*)
Qed.
Lemma equation_holds_exten:
@@ -393,6 +397,39 @@ Proof.
+ intros. apply Regmap.gso; auto.
Qed.
+(*
+Lemma add_load_holds_none1:
+ forall valu1 ge sp rs m n addr (args: list reg) chunk dst,
+ numbering_holds valu1 ge sp rs m n ->
+ eval_addressing ge sp addr rs##args = None ->
+ exists valu2, numbering_holds valu2 ge sp (rs#dst <- (default_notrap_load_value chunk)) m (add_load n dst chunk addr args).
+Proof.
+ unfold add_load; intros.
+ destruct (valnum_regs n args) as [n1 vl] eqn:VN.
+ exploit valnum_regs_holds; eauto.
+ intros (valu2 & A & B & C & D & E).
+ eapply add_rhs_holds; eauto.
++ rewrite Regmap.gss; auto. eapply load_notrap1_eval_to. rewrite <- B; eauto.
++ intros. apply Regmap.gso; auto.
+Qed.
+
+Lemma add_load_holds_none2:
+ forall valu1 ge sp rs m n addr (args: list reg) a chunk dst,
+ numbering_holds valu1 ge sp rs m n ->
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = None ->
+ exists valu2, numbering_holds valu2 ge sp (rs#dst <- (default_notrap_load_value chunk)) m (add_load n dst NOTRAP chunk addr args).
+Proof.
+ unfold add_load; intros.
+ destruct (valnum_regs n args) as [n1 vl] eqn:VN.
+ exploit valnum_regs_holds; eauto.
+ intros (valu2 & A & B & C & D & E).
+ eapply add_rhs_holds; eauto.
++ rewrite Regmap.gss; auto. eapply load_notrap2_eval_to. rewrite <- B; eauto. assumption.
++ intros. apply Regmap.gso; auto.
+Qed.
+ *)
+
Lemma set_unknown_holds:
forall valu ge sp rs m n r v,
numbering_holds valu ge sp rs m n ->
@@ -456,8 +493,8 @@ Lemma kill_all_loads_hold:
Proof.
intros. eapply kill_equations_hold; eauto.
unfold filter_loads; intros. inv H1.
- constructor. rewrite <- H2. apply op_depends_on_memory_correct; auto.
- discriminate.
+ 1: constructor; rewrite <- H2; apply op_depends_on_memory_correct; auto.
+ all: discriminate.
Qed.
Lemma kill_loads_after_store_holds:
@@ -486,6 +523,20 @@ Proof.
apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto.
erewrite <- regs_valnums_sound by eauto. eauto with va.
apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto with va.
+(*
+- eapply load_notrap1_eval_to; assumption.
+- destruct (regs_valnums n vl) as [rl|] eqn:RV; try discriminate.
+ eapply load_notrap2_eval_to; eauto.
+ rewrite <- H9.
+ destruct a; simpl in H1; try discriminate.
+ destruct a0; simpl in H9; try discriminate; simpl; trivial.
+ rewrite negb_false_iff in H6. unfold aaddressing in H6.
+ eapply Mem.load_store_other. eauto.
+ eapply pdisjoint_sound; eauto.
+ apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto.
+ erewrite <- regs_valnums_sound by eauto. eauto with va.
+ apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto with va.
+*)
Qed.
Lemma store_normalized_range_sound:
@@ -562,6 +613,19 @@ Proof.
unfold aaddressing. apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto.
erewrite <- regs_valnums_sound by eauto. eauto with va.
auto.
+(*
+- eapply load_notrap1_eval_to; assumption.
+- destruct (regs_valnums n vl) as [rl|] eqn:RV; try discriminate.
+ eapply load_notrap2_eval_to; eauto. rewrite <- H11.
+ destruct a; simpl in H10; try discriminate; simpl; trivial.
+ rewrite negb_false_iff in H8.
+ eapply Mem.load_storebytes_other. eauto.
+ rewrite H6. rewrite Z2Nat.id by omega.
+ eapply pdisjoint_sound. eauto.
+ unfold aaddressing. apply match_aptr_of_aval. eapply eval_static_addressing_sound; eauto.
+ erewrite <- regs_valnums_sound by eauto. eauto with va.
+ auto.
+*)
Qed.
Lemma load_memcpy:
@@ -1034,6 +1098,10 @@ Proof.
destruct (valnum_regs approx!!pc args) as [n1 vl] eqn:?.
destruct SAT as [valu1 NH1].
exploit valnum_regs_holds; eauto. intros (valu2 & NH2 & EQ & AG & P & Q).
+ destruct trap.
+
+ (* TRAP *)
+ {
destruct (find_rhs n1 (Load chunk addr vl)) as [r|] eqn:?.
+ (* replaced by move *)
exploit find_rhs_sound; eauto. intros (v' & EV & LD).
@@ -1063,7 +1131,103 @@ Proof.
unfold transfer; rewrite H.
eapply add_load_holds; eauto.
apply set_reg_lessdef; auto.
+ }
+
+ (* NOTRAP *)
+ {
+ assert (exists a' : val,
+ eval_addressing ge sp addr rs' ## args = Some a' /\ Val.lessdef a a')
+ as Haa'.
+ apply eval_addressing_lessdef with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ destruct Haa' as [a' [Ha'1 Ha'2]].
+
+ assert (
+ exists v' : val,
+ Mem.loadv chunk m' a' = Some v' /\ Val.lessdef v v') as Hload' by
+ (apply Mem.loadv_extends with (m1 := m) (addr1 := a); assumption).
+ destruct Hload' as [v' [Hv'1 Hv'2]].
+
+ econstructor. split.
+ eapply exec_Iload; eauto.
+ try (rewrite eval_addressing_preserved with (ge1 := ge); auto; exact symbols_preserved).
+
+ econstructor; eauto.
+ eapply analysis_correct_1; eauto. simpl; eauto.
+ unfold transfer. rewrite H.
+ exists valu1.
+ apply set_unknown_holds.
+ assumption.
+ apply set_reg_lessdef; assumption.
+ }
+
+- (* Iload notrap 1*)
+ destruct (valnum_regs approx!!pc args) as [n1 vl] eqn:?.
+ destruct SAT as [valu1 NH1].
+ exploit valnum_regs_holds; eauto. intros (valu2 & NH2 & EQ & AG & P & Q).
+
+ econstructor. split.
+ eapply exec_Iload_notrap1; eauto.
+ rewrite eval_addressing_preserved with (ge1 := ge).
+ apply eval_addressing_lessdef_none with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ exact symbols_preserved.
+
+ econstructor; eauto.
+ eapply analysis_correct_1; eauto. simpl; eauto.
+ unfold transfer. rewrite H.
+ exists valu1.
+ apply set_unknown_holds.
+ assumption.
+ apply set_reg_lessdef.
+ constructor. assumption.
+
+- (* Iload notrap 2*)
+ destruct (valnum_regs approx!!pc args) as [n1 vl] eqn:?.
+ destruct SAT as [valu1 NH1].
+ exploit valnum_regs_holds; eauto. intros (valu2 & NH2 & EQ & AG & P & Q).
+ assert (exists a' : val,
+ eval_addressing ge sp addr rs' ## args = Some a' /\ Val.lessdef a a')
+ as Haa'.
+ apply eval_addressing_lessdef with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ destruct Haa' as [a' [Ha'1 Ha'2]].
+
+ destruct (Mem.loadv chunk m' a') eqn:Hload'.
+
+ {
+ econstructor. split.
+ eapply exec_Iload; eauto.
+ try (rewrite eval_addressing_preserved with (ge1 := ge); auto; exact symbols_preserved).
+
+ econstructor; eauto.
+ eapply analysis_correct_1; eauto. simpl; eauto.
+ unfold transfer. rewrite H.
+ exists valu1.
+ apply set_unknown_holds.
+ assumption.
+ unfold default_notrap_load_value.
+ apply set_reg_lessdef; eauto.
+ }
+ {
+ econstructor. split.
+ eapply exec_Iload_notrap2; eauto.
+ try (rewrite eval_addressing_preserved with (ge1 := ge); auto; exact symbols_preserved).
+
+ econstructor; eauto.
+ eapply analysis_correct_1; eauto. simpl; eauto.
+ unfold transfer. rewrite H.
+ exists valu1.
+ apply set_unknown_holds.
+ assumption.
+ apply set_reg_lessdef.
+ constructor. assumption.
+ }
+
- (* Istore *)
destruct (valnum_regs approx!!pc args) as [n1 vl] eqn:?.
destruct SAT as [valu1 NH1].
diff --git a/backend/CleanupLabelsproof.v b/backend/CleanupLabelsproof.v
index e92be2b4..84ca403e 100644
--- a/backend/CleanupLabelsproof.v
+++ b/backend/CleanupLabelsproof.v
@@ -255,6 +255,18 @@ Proof.
left; econstructor; split.
econstructor; eauto.
econstructor; eauto with coqlib.
+(* Lload notrap1 *)
+ assert (eval_addressing tge sp addr (LTL.reglist rs args) = None).
+ rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
+ left; econstructor; split.
+ eapply exec_Lload_notrap1; eauto.
+ econstructor; eauto with coqlib.
+(* Lload notrap2 *)
+ assert (eval_addressing tge sp addr (LTL.reglist rs args) = Some a).
+ rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
+ left; econstructor; split.
+ eapply exec_Lload_notrap2; eauto.
+ econstructor; eauto with coqlib.
(* Lstore *)
assert (eval_addressing tge sp addr (LTL.reglist rs args) = Some a).
rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
diff --git a/backend/Cminor.v b/backend/Cminor.v
index ca01ad50..91a4c104 100644
--- a/backend/Cminor.v
+++ b/backend/Cminor.v
@@ -676,12 +676,24 @@ Definition outcome_block (out: outcome) : outcome :=
| out => out
end.
+(*
Definition outcome_result_value
- (out: outcome) (retsig: option typ) (vres: val) : Prop :=
+ (out: outcome) (retsig: rettype) (vres: val) : Prop :=
match out with
| Out_normal => vres = Vundef
| Out_return None => vres = Vundef
- | Out_return (Some v) => retsig <> None /\ vres = v
+ | Out_return (Some v) => retsig <> Tvoid /\ vres = v
+ | Out_tailcall_return v => vres = v
+ | _ => False
+ end.
+*)
+
+Definition outcome_result_value
+ (out: outcome) (vres: val) : Prop :=
+ match out with
+ | Out_normal => vres = Vundef
+ | Out_return None => vres = Vundef
+ | Out_return (Some v) => vres = v
| Out_tailcall_return v => vres = v
| _ => False
end.
@@ -711,7 +723,7 @@ Inductive eval_funcall:
Mem.alloc m 0 f.(fn_stackspace) = (m1, sp) ->
set_locals f.(fn_vars) (set_params vargs f.(fn_params)) = e ->
exec_stmt f (Vptr sp Ptrofs.zero) e m1 f.(fn_body) t e2 m2 out ->
- outcome_result_value out f.(fn_sig).(sig_res) vres ->
+ outcome_result_value out vres ->
outcome_free_mem out m2 sp f.(fn_stackspace) m3 ->
eval_funcall m (Internal f) vargs t m3 vres
| eval_funcall_external:
@@ -995,7 +1007,7 @@ Proof.
subst vres. replace k with (call_cont k') by congruence.
apply star_one. apply step_return_0; auto.
(* Out_return Some *)
- destruct H3. subst vres.
+ subst vres.
replace k with (call_cont k') by congruence.
apply star_one. eapply step_return_1; eauto.
(* Out_tailcall_return *)
diff --git a/backend/Cminortyping.v b/backend/Cminortyping.v
index fccbda27..92ec45f2 100644
--- a/backend/Cminortyping.v
+++ b/backend/Cminortyping.v
@@ -130,7 +130,7 @@ Definition opt_set (e: S.typenv) (optid: option ident) (ty: typ) : res S.typenv
| Some id => S.set e id ty
end.
-Fixpoint type_stmt (tret: option typ) (e: S.typenv) (s: stmt) : res S.typenv :=
+Fixpoint type_stmt (tret: rettype) (e: S.typenv) (s: stmt) : res S.typenv :=
match s with
| Sskip => OK e
| Sassign id a => type_assign e id a
@@ -141,7 +141,7 @@ Fixpoint type_stmt (tret: option typ) (e: S.typenv) (s: stmt) : res S.typenv :=
do e2 <- type_exprlist e1 args sg.(sig_args);
opt_set e2 optid (proj_sig_res sg)
| Stailcall sg fn args =>
- assertion (opt_typ_eq sg.(sig_res) tret);
+ assertion (rettype_eq sg.(sig_res) tret);
do e1 <- type_expr e fn Tptr;
type_exprlist e1 args sg.(sig_args)
| Sbuiltin optid ef args =>
@@ -163,10 +163,14 @@ Fixpoint type_stmt (tret: option typ) (e: S.typenv) (s: stmt) : res S.typenv :=
| Sswitch sz a tbl dfl =>
type_expr e a (if sz then Tlong else Tint)
| Sreturn opta =>
- match opta, tret with
- | None, _ => OK e
- | Some a, Some t => type_expr e a t
- | _, _ => Error (msg "inconsistent return")
+ match opta with
+ | None => OK e
+ | Some a => type_expr e a (proj_rettype tret)
+(*
+ if rettype_eq tret Tvoid
+ then Error (msg "inconsistent return")
+ else type_expr e a (proj_rettype tret)
+*)
end
| Slabel lbl s1 =>
type_stmt tret e s1
@@ -186,7 +190,7 @@ Definition type_function (f: function) : res typenv :=
Section SPEC.
Variable env: ident -> typ.
-Variable tret: option typ.
+Variable tret: rettype.
Inductive wt_expr: expr -> typ -> Prop :=
| wt_Evar: forall id,
@@ -205,9 +209,9 @@ Inductive wt_expr: expr -> typ -> Prop :=
wt_expr a1 Tptr ->
wt_expr (Eload chunk a1) (type_of_chunk chunk).
-Definition wt_opt_assign (optid: option ident) (optty: option typ) : Prop :=
+Definition wt_opt_assign (optid: option ident) (ty: rettype) : Prop :=
match optid with
- | Some id => match optty with Some ty => ty | None => Tint end = env id
+ | Some id => proj_rettype ty = env id
| _ => True
end.
@@ -251,8 +255,8 @@ Inductive wt_stmt: stmt -> Prop :=
wt_stmt (Sswitch sz a tbl dfl)
| wt_Sreturn_none:
wt_stmt (Sreturn None)
- | wt_Sreturn_some: forall a t,
- tret = Some t -> wt_expr a t ->
+ | wt_Sreturn_some: forall a,
+ wt_expr a (proj_rettype tret) ->
wt_stmt (Sreturn (Some a))
| wt_Slabel: forall lbl s1,
wt_stmt s1 ->
@@ -393,7 +397,7 @@ Proof.
- constructor; eauto.
- constructor.
- constructor; eauto using type_expr_sound with ty.
-- destruct tret, o; try (monadInv T); econstructor; eauto using type_expr_sound with ty.
+- destruct o; try (monadInv T); econstructor; eauto using type_expr_sound with ty.
- constructor; eauto.
- constructor.
Qed.
@@ -414,9 +418,9 @@ Definition wt_env (env: typenv) (e: Cminor.env) : Prop :=
Definition def_env (f: function) (e: Cminor.env) : Prop :=
forall id, In id f.(fn_params) \/ In id f.(fn_vars) -> exists v, e!id = Some v.
-Inductive wt_cont_call: cont -> option typ -> Prop :=
+Inductive wt_cont_call: cont -> rettype -> Prop :=
| wt_cont_Kstop:
- wt_cont_call Kstop (Some Tint)
+ wt_cont_call Kstop Tint
| wt_cont_Kcall: forall optid f sp e k tret env
(WT_FN: wt_function env f)
(WT_CONT: wt_cont env f.(fn_sig).(sig_res) k)
@@ -425,7 +429,7 @@ Inductive wt_cont_call: cont -> option typ -> Prop :=
(WT_DEST: wt_opt_assign env optid tret),
wt_cont_call (Kcall optid f sp e k) tret
-with wt_cont: typenv -> option typ -> cont -> Prop :=
+with wt_cont: typenv -> rettype -> cont -> Prop :=
| wt_cont_Kseq: forall env tret s k,
wt_stmt env tret s ->
wt_cont env tret k ->
@@ -451,7 +455,7 @@ Inductive wt_state: state -> Prop :=
(WT_CONT: wt_cont_call k (funsig f).(sig_res)),
wt_state (Callstate f args k m)
| wt_return_state: forall v k m tret
- (WT_RES: Val.has_type v (match tret with None => Tint | Some t => t end))
+ (WT_RES: Val.has_type v (proj_rettype tret))
(WT_CONT: wt_cont_call k tret),
wt_state (Returnstate v k m).
@@ -651,9 +655,8 @@ Proof.
rewrite H8; eapply call_cont_wt; eauto.
- inv WT_STMT. exploit external_call_well_typed; eauto. intros TRES.
econstructor; eauto using wt_Sskip.
- unfold proj_sig_res in TRES; red in H5.
- destruct optid. rewrite H5 in TRES. apply wt_env_assign; auto. assumption.
- destruct optid. apply def_env_assign; auto. assumption.
+ destruct optid; auto. apply wt_env_assign; auto. rewrite <- H5; auto.
+ destruct optid; auto. apply def_env_assign; auto.
- inv WT_STMT. econstructor; eauto. econstructor; eauto.
- inv WT_STMT. destruct b; econstructor; eauto.
- inv WT_STMT. econstructor; eauto. econstructor; eauto. constructor; auto.
@@ -664,7 +667,7 @@ Proof.
- econstructor; eauto using wt_Sexit.
- inv WT_STMT. econstructor; eauto using call_cont_wt. exact I.
- inv WT_STMT. econstructor; eauto using call_cont_wt.
- rewrite H2. eapply wt_eval_expr; eauto.
+ eapply wt_eval_expr; eauto.
- inv WT_STMT. econstructor; eauto.
- inversion WT_FN; subst.
assert (WT_CK: wt_cont env (sig_res (fn_sig f)) (call_cont k)).
@@ -675,7 +678,7 @@ Proof.
constructor; auto.
apply wt_env_set_locals. apply wt_env_set_params. rewrite H2; auto.
red; intros. apply def_set_locals. destruct H4; auto. left; apply def_set_params; auto.
-- exploit external_call_well_typed; eauto. unfold proj_sig_res. simpl in *. intros.
+- exploit external_call_well_typed; eauto. intros.
econstructor; eauto.
- inv WT_CONT. econstructor; eauto using wt_Sskip.
red in WT_DEST.
diff --git a/backend/Constprop.v b/backend/Constprop.v
index 4aab7677..0be9438c 100644
--- a/backend/Constprop.v
+++ b/backend/Constprop.v
@@ -69,7 +69,7 @@ Fixpoint successor_rec (n: nat) (f: function) (ae: AE.t) (pc: node) : node :=
match f.(fn_code)!pc with
| Some (Inop s) =>
successor_rec n' f ae s
- | Some (Icond cond args s1 s2) =>
+ | Some (Icond cond args s1 s2 _) =>
match resolve_branch (eval_static_condition cond (aregs ae args)) with
| Some b => successor_rec n' f ae (if b then s1 else s2)
| None => pc
@@ -181,7 +181,7 @@ Definition transf_instr (f: function) (an: PMap.t VA.t) (rm: romem)
let (op', args') := op_strength_reduction op args aargs in
Iop op' args' res s'
end
- | Iload chunk addr args dst s =>
+ | Iload TRAP chunk addr args dst s =>
let aargs := aregs ae args in
let a := ValueDomain.loadv chunk rm am (eval_static_addressing addr aargs) in
match const_for_result a with
@@ -189,7 +189,7 @@ Definition transf_instr (f: function) (an: PMap.t VA.t) (rm: romem)
Iop cop nil dst s
| None =>
let (addr', args') := addr_strength_reduction addr args aargs in
- Iload chunk addr' args' dst s
+ Iload TRAP chunk addr' args' dst s
end
| Istore chunk addr args src s =>
let aargs := aregs ae args in
@@ -217,14 +217,14 @@ Definition transf_instr (f: function) (an: PMap.t VA.t) (rm: romem)
end
| _, _ => dfl
end
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 i =>
let aargs := aregs ae args in
match resolve_branch (eval_static_condition cond aargs) with
| Some b =>
if b then Inop s1 else Inop s2
| None =>
let (cond', args') := cond_strength_reduction cond args aargs in
- Icond cond' args' s1 s2
+ Icond cond' args' s1 s2 i
end
| Ijumptable arg tbl =>
match areg ae arg with
diff --git a/backend/Constpropproof.v b/backend/Constpropproof.v
index a5d08a0f..60663503 100644
--- a/backend/Constpropproof.v
+++ b/backend/Constpropproof.v
@@ -142,8 +142,8 @@ Inductive match_pc (f: function) (rs: regset) (m: mem): nat -> node -> node -> P
f.(fn_code)!pc = Some (Inop s) ->
match_pc f rs m n s pcx ->
match_pc f rs m (S n) pc pcx
- | match_pc_cond: forall n pc cond args s1 s2 pcx,
- f.(fn_code)!pc = Some (Icond cond args s1 s2) ->
+ | match_pc_cond: forall n pc cond args s1 s2 pcx i,
+ f.(fn_code)!pc = Some (Icond cond args s1 s2 i) ->
(forall b,
eval_condition cond rs##args m = Some b ->
match_pc f rs m n (if b then s1 else s2) pcx) ->
@@ -406,6 +406,8 @@ Proof.
assert (VM1: vmatch bc a aa) by (eapply eval_static_addressing_sound; eauto with va).
set (av := loadv chunk (romem_for cu) am aa).
assert (VM2: vmatch bc v av) by (eapply loadv_sound; eauto).
+ destruct trap.
+ {
destruct (const_for_result av) as [cop|] eqn:?; intros.
+ (* constant-propagated *)
exploit const_for_result_correct; eauto. intros (v' & A & B).
@@ -431,6 +433,59 @@ Proof.
left; econstructor; econstructor; split.
eapply exec_Iload; eauto.
eapply match_states_succ; eauto. apply set_reg_lessdef; auto.
+ }
+ {
+ assert (exists v2 : val,
+ eval_addressing ge (Vptr sp0 Ptrofs.zero) addr (rs' ## args) = Some v2 /\ Val.lessdef a v2) as Hexist2.
+ apply eval_addressing_lessdef with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ destruct Hexist2 as [v2 [Heval2 Hlessdef2]].
+ destruct (Mem.loadv_extends chunk m m' a v2 v MEM H1 Hlessdef2) as [vX [Hvx1 Hvx2]].
+ left; econstructor; econstructor; split.
+ eapply exec_Iload with (a := v2); eauto.
+ try (erewrite eval_addressing_preserved with (ge1:=ge); auto;
+ exact symbols_preserved).
+ eapply match_states_succ; eauto. apply set_reg_lessdef; auto.
+
+ }
+
+- (* Iload notrap1 *)
+ rename pc'0 into pc. TransfInstr.
+ assert (eval_addressing tge (Vptr sp0 Ptrofs.zero) addr (rs' ## args) = None).
+ rewrite eval_addressing_preserved with (ge1 := ge); eauto.
+ apply eval_addressing_lessdef_none with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ exact symbols_preserved.
+
+ left; econstructor; econstructor; split.
+ eapply exec_Iload_notrap1; eauto.
+ eapply match_states_succ; eauto. apply set_reg_lessdef; auto.
+
+- (* Iload notrap2 *)
+ rename pc'0 into pc. TransfInstr.
+ assert (exists v2 : val,
+ eval_addressing ge (Vptr sp0 Ptrofs.zero) addr (rs' ## args) = Some v2 /\ Val.lessdef a v2) as Hexist2.
+ apply eval_addressing_lessdef with (vl1 := rs ## args).
+ apply regs_lessdef_regs; assumption.
+ assumption.
+ destruct Hexist2 as [a' [Heval' Hlessdef']].
+ destruct (Mem.loadv chunk m' a') eqn:Hload'.
+ {
+ left; econstructor; econstructor; split.
+ eapply exec_Iload; eauto.
+
+ try (rewrite eval_addressing_preserved with (ge1 := ge); auto; exact symbols_preserved).
+ eapply match_states_succ; eauto. apply set_reg_lessdef; auto.
+ }
+ {
+ left; econstructor; econstructor; split.
+ eapply exec_Iload_notrap2; eauto.
+
+ try (rewrite eval_addressing_preserved with (ge1 := ge); auto; exact symbols_preserved).
+ eapply match_states_succ; eauto. apply set_reg_lessdef; auto.
+ }
- (* Istore *)
rename pc'0 into pc. TransfInstr.
diff --git a/backend/Conventions.v b/backend/Conventions.v
index 6025c6b4..14ffb587 100644
--- a/backend/Conventions.v
+++ b/backend/Conventions.v
@@ -34,6 +34,73 @@ Proof.
apply IHpl; auto.
Qed.
+(** ** Stack size of function arguments *)
+
+(** [size_arguments s] returns the number of [Outgoing] slots used
+ to call a function with signature [s]. *)
+
+Definition max_outgoing_1 (accu: Z) (l: loc) : Z :=
+ match l with
+ | S Outgoing ofs ty => Z.max accu (ofs + typesize ty)
+ | _ => accu
+ end.
+
+Definition max_outgoing_2 (accu: Z) (rl: rpair loc) : Z :=
+ match rl with
+ | One l => max_outgoing_1 accu l
+ | Twolong l1 l2 => max_outgoing_1 (max_outgoing_1 accu l1) l2
+ end.
+
+Definition size_arguments (s: signature) : Z :=
+ List.fold_left max_outgoing_2 (loc_arguments s) 0.
+
+(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
+
+Remark fold_max_outgoing_above:
+ forall l n, fold_left max_outgoing_2 l n >= n.
+Proof.
+ assert (A: forall n l, max_outgoing_1 n l >= n).
+ { intros; unfold max_outgoing_1. destruct l as [_ | []]; xomega. }
+ induction l; simpl; intros.
+ - omega.
+ - eapply Zge_trans. eauto.
+ destruct a; simpl. apply A. eapply Zge_trans; eauto.
+Qed.
+
+Lemma size_arguments_above:
+ forall s, size_arguments s >= 0.
+Proof.
+ intros. apply fold_max_outgoing_above.
+Qed.
+
+Lemma loc_arguments_bounded:
+ forall (s: signature) (ofs: Z) (ty: typ),
+ In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
+ ofs + typesize ty <= size_arguments s.
+Proof.
+ intros until ty.
+ assert (A: forall n l, n <= max_outgoing_1 n l).
+ { intros; unfold max_outgoing_1. destruct l as [_ | []]; xomega. }
+ assert (B: forall p n,
+ In (S Outgoing ofs ty) (regs_of_rpair p) ->
+ ofs + typesize ty <= max_outgoing_2 n p).
+ { intros. destruct p; simpl in H; intuition; subst; simpl.
+ - xomega.
+ - eapply Z.le_trans. 2: apply A. xomega.
+ - xomega. }
+ assert (C: forall l n,
+ In (S Outgoing ofs ty) (regs_of_rpairs l) ->
+ ofs + typesize ty <= fold_left max_outgoing_2 l n).
+ { induction l; simpl; intros.
+ - contradiction.
+ - rewrite in_app_iff in H. destruct H.
+ + eapply Z.le_trans. eapply B; eauto.
+ apply Z.ge_le. apply fold_max_outgoing_above.
+ + apply IHl; auto.
+ }
+ apply C.
+Qed.
+
(** ** Location of function parameters *)
(** A function finds the values of its parameter in the same locations
diff --git a/backend/Deadcode.v b/backend/Deadcode.v
index 2286876e..3412a6fa 100644
--- a/backend/Deadcode.v
+++ b/backend/Deadcode.v
@@ -123,7 +123,7 @@ Definition transfer (f: function) (approx: PMap.t VA.t)
if is_dead nres then after
else if is_int_zero nres then (kill res ne, nm)
else (add_needs args (needs_of_operation op nres) (kill res ne), nm)
- | Some (Iload chunk addr args dst s) =>
+ | Some (Iload trap chunk addr args dst s) =>
let ndst := nreg ne dst in
if is_dead ndst then after
else if is_int_zero ndst then (kill dst ne, nm)
@@ -142,7 +142,7 @@ Definition transfer (f: function) (approx: PMap.t VA.t)
nmem_dead_stack f.(fn_stacksize))
| Some(Ibuiltin ef args res s) =>
transfer_builtin approx!!pc ef args res ne nm
- | Some(Icond cond args s1 s2) =>
+ | Some(Icond cond args s1 s2 _) =>
if peq s1 s2 then after else
(add_needs args (needs_of_condition cond) ne, nm)
| Some(Ijumptable arg tbl) =>
@@ -175,7 +175,7 @@ Definition transf_instr (approx: PMap.t VA.t) (an: PMap.t NA.t)
end
else
instr
- | Iload chunk addr args dst s =>
+ | Iload trap chunk addr args dst s =>
let ndst := nreg (fst an!!pc) dst in
if is_dead ndst then
Inop s
@@ -192,7 +192,7 @@ Definition transf_instr (approx: PMap.t VA.t) (an: PMap.t NA.t)
if nmem_contains (snd an!!pc) (aaddr_arg approx!!pc dst) sz
then instr
else Inop s
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 _ =>
if peq s1 s2 then Inop s1 else instr
| _ =>
instr
diff --git a/backend/Deadcodeproof.v b/backend/Deadcodeproof.v
index 2edc0395..6919fe78 100644
--- a/backend/Deadcodeproof.v
+++ b/backend/Deadcodeproof.v
@@ -829,6 +829,83 @@ Ltac UseTransfer :=
apply eagree_update; eauto 2 with na.
eapply magree_monotone; eauto. intros. apply incl_nmem_add; auto.
+- (* load notrap1 *)
+ TransfInstr; UseTransfer.
+ destruct (is_dead (nreg ne dst)) eqn:DEAD;
+ [idtac|destruct (is_int_zero (nreg ne dst)) eqn:INTZERO];
+ simpl in *.
++ (* dead instruction, turned into a nop *)
+ econstructor; split.
+ eapply exec_Inop; eauto.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update_dead; auto with na.
++ (* instruction with needs = [I Int.zero], turned into a load immediate of zero. *)
+ econstructor; split.
+ eapply exec_Iop with (v := Vint Int.zero); eauto.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update; auto.
+ rewrite is_int_zero_sound by auto.
+ unfold default_notrap_load_value.
+ constructor.
++ (* preserved *)
+ exploit eval_addressing_lessdef_none. eapply add_needs_all_lessdef; eauto. eassumption.
+ intro Hnone'.
+ assert (eval_addressing tge (Vptr sp0 Ptrofs.zero) addr te ## args = None) as Hnone2'.
+ erewrite eval_addressing_preserved with (ge1 := ge).
+ assumption.
+ exact symbols_preserved.
+
+ econstructor; split.
+ eapply exec_Iload_notrap1; eauto.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update; eauto 2 with na.
+ eapply magree_monotone; eauto. intros. apply incl_nmem_add; auto.
+
+- (* load notrap2 *)
+ TransfInstr; UseTransfer.
+
+ destruct (is_dead (nreg ne dst)) eqn:DEAD;
+ [idtac|destruct (is_int_zero (nreg ne dst)) eqn:INTZERO];
+ simpl in *.
++ (* dead instruction, turned into a nop *)
+ econstructor; split.
+ eapply exec_Inop; eauto.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update_dead; auto with na.
++ (* instruction with needs = [I Int.zero], turned into a load immediate of zero. *)
+ econstructor; split.
+ eapply exec_Iop with (v := Vint Int.zero); eauto.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update; auto.
+ rewrite is_int_zero_sound by auto.
+ unfold default_notrap_load_value.
+ constructor.
++ (* preserved *)
+ exploit eval_addressing_lessdef. eapply add_needs_all_lessdef; eauto. eauto.
+ intros (ta & U & V).
+ destruct (Mem.loadv chunk tm ta) eqn:Hchunk2.
+ {
+ econstructor; split.
+ eapply exec_Iload. eauto.
+ erewrite eval_addressing_preserved with (ge1 := ge).
+ eassumption.
+ exact symbols_preserved.
+ eassumption.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update; eauto 2 with na.
+ eapply magree_monotone; eauto. intros. apply incl_nmem_add; auto.
+ }
+ {
+ econstructor; split.
+ eapply exec_Iload_notrap2. eauto.
+ erewrite eval_addressing_preserved with (ge1 := ge).
+ eassumption.
+ exact symbols_preserved.
+ eassumption.
+ eapply match_succ_states; eauto. simpl; auto.
+ apply eagree_update; eauto 2 with na.
+ eapply magree_monotone; eauto. intros. apply incl_nmem_add; auto.
+ }
- (* store *)
TransfInstr; UseTransfer.
destruct (nmem_contains nm (aaddressing (vanalyze cu f) # pc addr args)
diff --git a/backend/Debugvar.v b/backend/Debugvar.v
index 1f361030..56908855 100644
--- a/backend/Debugvar.v
+++ b/backend/Debugvar.v
@@ -233,7 +233,7 @@ Definition transfer (lm: labelmap) (before: option avail) (i: instruction):
(lm, Some (kill (S sl ofs ty) s))
| Lop op args dst =>
(lm, Some (kill (R dst) s))
- | Lload chunk addr args dst =>
+ | Lload trap chunk addr args dst =>
(lm, Some (kill (R dst) s))
| Lstore chunk addr args src =>
(lm, before)
diff --git a/backend/Debugvarproof.v b/backend/Debugvarproof.v
index d31c63ec..95020637 100644
--- a/backend/Debugvarproof.v
+++ b/backend/Debugvarproof.v
@@ -449,6 +449,22 @@ Proof.
eauto. eauto.
apply eval_add_delta_ranges. traceEq.
constructor; auto.
+- (* load notrap1 *)
+ econstructor; split.
+ eapply plus_left.
+ eapply exec_Lload_notrap1.
+ rewrite <- H; apply eval_addressing_preserved; exact symbols_preserved.
+ eauto. eauto.
+ apply eval_add_delta_ranges. traceEq.
+ constructor; auto.
+- (* load notrap2 *)
+ econstructor; split.
+ eapply plus_left.
+ eapply exec_Lload_notrap2.
+ rewrite <- H; apply eval_addressing_preserved; exact symbols_preserved.
+ eauto. eauto.
+ apply eval_add_delta_ranges. traceEq.
+ constructor; auto.
- (* store *)
econstructor; split.
eapply plus_left.
diff --git a/backend/Duplicate.v b/backend/Duplicate.v
index 3ad37c83..af85efe4 100644
--- a/backend/Duplicate.v
+++ b/backend/Duplicate.v
@@ -72,17 +72,19 @@ Definition verify_match_inst dupmap inst tinst :=
else Error(msg "Different operations in Iop")
| _ => Error(msg "verify_match_inst Inop") end
- | Iload m a lr r n => match tinst with
- | Iload m' a' lr' r' n' =>
+ | Iload tm m a lr r n => match tinst with
+ | Iload tm' m' a' lr' r' n' =>
do u <- verify_is_copy dupmap n n';
- if (chunk_eq m m') then
- if (eq_addressing a a') then
- if (list_eq_dec Pos.eq_dec lr lr') then
- if (Pos.eq_dec r r') then OK tt
- else Error (msg "Different r in Iload")
- else Error (msg "Different lr in Iload")
- else Error (msg "Different addressing in Iload")
- else Error (msg "Different mchunk in Iload")
+ if (trapping_mode_eq tm tm') then
+ if (chunk_eq m m') then
+ if (eq_addressing a a') then
+ if (list_eq_dec Pos.eq_dec lr lr') then
+ if (Pos.eq_dec r r') then OK tt
+ else Error (msg "Different r in Iload")
+ else Error (msg "Different lr in Iload")
+ else Error (msg "Different addressing in Iload")
+ else Error (msg "Different mchunk in Iload")
+ else Error (msg "Different trapping_mode in Iload")
| _ => Error (msg "verify_match_inst Iload") end
| Istore m a lr r n => match tinst with
@@ -132,14 +134,17 @@ Definition verify_match_inst dupmap inst tinst :=
else Error (msg "Different ef in Ibuiltin")
| _ => Error (msg "verify_match_inst Ibuiltin") end
- | Icond cond lr n1 n2 => match tinst with
- | Icond cond' lr' n1' n2' =>
- do u1 <- verify_is_copy dupmap n1 n1';
- do u2 <- verify_is_copy dupmap n2 n2';
- if (eq_condition cond cond') then
- if (list_eq_dec Pos.eq_dec lr lr') then OK tt
- else Error (msg "Different lr in Icond")
- else Error (msg "Different cond in Icond")
+ | Icond cond lr n1 n2 i => match tinst with
+ | Icond cond' lr' n1' n2' i' =>
+ if (list_eq_dec Pos.eq_dec lr lr') then
+ if (eq_condition cond cond') then
+ do u1 <- verify_is_copy dupmap n1 n1';
+ do u2 <- verify_is_copy dupmap n2 n2'; OK tt
+ else if (eq_condition (negate_condition cond) cond') then
+ do u1 <- verify_is_copy dupmap n1 n2';
+ do u2 <- verify_is_copy dupmap n2 n1'; OK tt
+ else Error (msg "Incompatible conditions in Icond")
+ else Error (msg "Different lr in Icond")
| _ => Error (msg "verify_match_inst Icond") end
| Ijumptable r ln => match tinst with
@@ -195,4 +200,4 @@ Definition transf_fundef (f: fundef) : res fundef :=
transf_partial_fundef transf_function f.
Definition transf_program (p: program) : res program :=
- transform_partial_program transf_fundef p. \ No newline at end of file
+ transform_partial_program transf_fundef p.
diff --git a/backend/Duplicateaux.ml b/backend/Duplicateaux.ml
index a64f4862..28ad4266 100644
--- a/backend/Duplicateaux.ml
+++ b/backend/Duplicateaux.ml
@@ -1,13 +1,632 @@
open RTL
open Maps
+open Camlcoq
+
+let get_some = function
+| None -> failwith "Did not get some"
+| Some thing -> thing
+
+let bfs code entrypoint = begin
+ Printf.printf "bfs\n"; flush stdout;
+ let visited = ref (PTree.map (fun n i -> false) code)
+ and bfs_list = ref []
+ and to_visit = Queue.create ()
+ and node = ref entrypoint
+ in begin
+ Queue.add entrypoint to_visit;
+ while not (Queue.is_empty to_visit) do
+ node := Queue.pop to_visit;
+ if not (get_some @@ PTree.get !node !visited) then begin
+ visited := PTree.set !node true !visited;
+ match PTree.get !node code with
+ | None -> failwith "No such node"
+ | Some i ->
+ bfs_list := !node :: !bfs_list;
+ match i with
+ | Icall(_, _, _, _, n) -> Queue.add n to_visit
+ | Ibuiltin(_, _, _, n) -> Queue.add n to_visit
+ | Ijumptable(_, ln) -> List.iter (fun n -> Queue.add n to_visit) ln
+ | Itailcall _ | Ireturn _ -> ()
+ | Icond (_, _, n1, n2, _) -> Queue.add n1 to_visit; Queue.add n2 to_visit
+ | Inop n | Iop (_, _, _, n) | Iload (_, _, _, _, _, n) | Istore (_, _, _, _, n) -> Queue.add n to_visit
+ end
+ done;
+ List.rev !bfs_list
+ end
+end
+
+let optbool o = match o with Some _ -> true | None -> false
+
+let ptree_get_some n ptree = get_some @@ PTree.get n ptree
+
+let get_predecessors_rtl code = begin
+ Printf.printf "get_predecessors_rtl\n"; flush stdout;
+ let preds = ref (PTree.map (fun n i -> []) code) in
+ let process_inst (node, i) =
+ let succ = match i with
+ | Inop n | Iop (_,_,_,n) | Iload (_, _,_,_,_,n) | Istore (_,_,_,_,n)
+ | Icall (_,_,_,_,n) | Ibuiltin (_, _, _, n) -> [n]
+ | Icond (_,_,n1,n2,_) -> [n1;n2]
+ | Ijumptable (_,ln) -> ln
+ | Itailcall _ | Ireturn _ -> []
+ in List.iter (fun s ->
+ let previous_preds = ptree_get_some s !preds in
+ if optbool @@ List.find_opt (fun e -> e == node) previous_preds then ()
+ else preds := PTree.set s (node::previous_preds) !preds) succ
+ in begin
+ List.iter process_inst (PTree.elements code);
+ !preds
+ end
+end
+
+module PInt = struct
+ type t = P.t
+ let compare x y = compare (P.to_int x) (P.to_int y)
+end
+
+module PSet = Set.Make(PInt)
+
+let print_intlist l =
+ let rec f = function
+ | [] -> ()
+ | n::ln -> (Printf.printf "%d " (P.to_int n); f ln)
+ in begin
+ Printf.printf "[";
+ f l;
+ Printf.printf "]"
+ end
+
+let print_intset s =
+ let seq = PSet.to_seq s
+ in begin
+ Printf.printf "{";
+ Seq.iter (fun n ->
+ Printf.printf "%d " (P.to_int n)
+ ) seq;
+ Printf.printf "}"
+ end
+
+type vstate = Unvisited | Processed | Visited
+
+(** Getting loop branches with a DFS visit :
+ * Each node is either Unvisited, Visited, or Processed
+ * pre-order: node becomes Processed
+ * post-order: node becomes Visited
+ *
+ * If we come accross an edge to a Processed node, it's a loop!
+ *)
+let get_loop_headers code entrypoint = begin
+ Printf.printf "get_loop_headers\n"; flush stdout;
+ let visited = ref (PTree.map (fun n i -> Unvisited) code)
+ and is_loop_header = ref (PTree.map (fun n i -> false) code)
+ in let rec dfs_visit code = function
+ | [] -> ()
+ | node :: ln ->
+ match (get_some @@ PTree.get node !visited) with
+ | Visited -> ()
+ | Processed -> begin
+ is_loop_header := PTree.set node true !is_loop_header;
+ visited := PTree.set node Visited !visited
+ end
+ | Unvisited -> begin
+ visited := PTree.set node Processed !visited;
+ match PTree.get node code with
+ | None -> failwith "No such node"
+ | Some i -> let next_visits = (match i with
+ | Icall (_, _, _, _, n) | Ibuiltin (_, _, _, n) | Inop n | Iop (_, _, _, n)
+ | Iload (_, _, _, _, _, n) | Istore (_, _, _, _, n) -> [n]
+ | Icond (_, _, n1, n2, _) -> [n1; n2]
+ | Itailcall _ | Ireturn _ -> []
+ | Ijumptable (_, ln) -> ln
+ ) in dfs_visit code next_visits;
+ visited := PTree.set node Visited !visited;
+ dfs_visit code ln
+ end
+ in begin
+ dfs_visit code [entrypoint];
+ !is_loop_header
+ end
+end
+
+let ptree_printbool pt =
+ let elements = PTree.elements pt
+ in begin
+ Printf.printf "[";
+ List.iter (fun (n, b) ->
+ if b then Printf.printf "%d, " (P.to_int n) else ()
+ ) elements;
+ Printf.printf "]"
+ end
+
+(* Looks ahead (until a branch) to see if a node further down verifies
+ * the given predicate *)
+let rec look_ahead code node is_loop_header predicate =
+ if (predicate node) then true
+ else match (get_some @@ PTree.get node code) with
+ | Ireturn _ | Itailcall _ | Icond _ | Ijumptable _ -> false
+ | Inop n | Iop (_, _, _, n) | Iload (_, _, _, _, _, n)
+ | Istore (_, _, _, _, n) | Icall (_, _, _, _, n)
+ | Ibuiltin (_, _, _, n) ->
+ if (predicate n) then true
+ else (
+ if (get_some @@ PTree.get n is_loop_header) then false
+ else look_ahead code n is_loop_header predicate
+ )
+
+let do_call_heuristic code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tCall heuristic..\n";
+ let predicate n = (function
+ | Icall _ -> true
+ | _ -> false) @@ get_some @@ PTree.get n code
+ in let ifso_call = look_ahead code ifso is_loop_header predicate
+ in let ifnot_call = look_ahead code ifnot is_loop_header predicate
+ in if ifso_call && ifnot_call then None
+ else if ifso_call then Some false
+ else if ifnot_call then Some true
+ else None
+ end
+
+let do_opcode_heuristic code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tOpcode heuristic..\n";
+ DuplicateOpcodeHeuristic.opcode_heuristic code cond ifso ifnot is_loop_header
+ end
+
+let do_return_heuristic code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tReturn heuristic..\n";
+ let predicate n = (function
+ | Ireturn _ -> true
+ | _ -> false) @@ get_some @@ PTree.get n code
+ in let ifso_return = look_ahead code ifso is_loop_header predicate
+ in let ifnot_return = look_ahead code ifnot is_loop_header predicate
+ in if ifso_return && ifnot_return then None
+ else if ifso_return then Some false
+ else if ifnot_return then Some true
+ else None
+ end
+
+let do_store_heuristic code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tStore heuristic..\n";
+ let predicate n = (function
+ | Istore _ -> true
+ | _ -> false) @@ get_some @@ PTree.get n code
+ in let ifso_store = look_ahead code ifso is_loop_header predicate
+ in let ifnot_store = look_ahead code ifnot is_loop_header predicate
+ in if ifso_store && ifnot_store then None
+ else if ifso_store then Some false
+ else if ifnot_store then Some true
+ else None
+ end
+
+let do_loop_heuristic code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tLoop heuristic..\n";
+ let predicate n = get_some @@ PTree.get n is_loop_header in
+ let ifso_loop = look_ahead code ifso is_loop_header predicate in
+ let ifnot_loop = look_ahead code ifnot is_loop_header predicate in
+ if ifso_loop && ifnot_loop then None (* TODO - take the innermost loop ? *)
+ else if ifso_loop then Some true
+ else if ifnot_loop then Some false
+ else None
+ end
+
+let do_loop2_heuristic loop_info n code cond ifso ifnot is_loop_header =
+ begin
+ Printf.printf "\tLoop2 heuristic..\n";
+ match get_some @@ PTree.get n loop_info with
+ | None -> None
+ | Some b -> Some b
+ end
+
+(* Returns a PTree of either None or Some b where b determines the node following the loop, for a cb instruction *)
+(* It uses the fact that loops in CompCert are done by a branch (backedge) instruction followed by a cb *)
+let get_loop_info is_loop_header bfs_order code =
+ let loop_info = ref (PTree.map (fun n i -> None) code) in
+ let mark_path s n =
+ let visited = ref (PTree.map (fun n i -> false) code) in
+ let rec explore src dest =
+ if (get_some @@ PTree.get src !visited) then false
+ else if src == dest then true
+ else begin
+ visited := PTree.set src true !visited;
+ match get_some @@ PTree.get src code with
+ | Inop s | Iop (_, _, _, s) | Iload (_,_,_,_,_,s) | Istore (_,_,_,_,s) | Icall (_,_,_,_,s)
+ | Ibuiltin (_,_,_,s) -> explore s dest
+ | Icond (_,_,s1,s2,_) -> (explore s1 dest) || (explore s2 dest)
+ | Ijumptable _ | Itailcall _ | Ireturn _ -> false
+ end
+ in match get_some @@ PTree.get s !loop_info with
+ | None -> begin
+ match get_some @@ PTree.get s code with
+ | Icond (_, _, n1, n2, _) ->
+ let b1 = explore n1 n in
+ let b2 = explore n2 n in
+ if (b1 && b2) then ()
+ else if b1 then loop_info := PTree.set s (Some true) !loop_info
+ else if b2 then loop_info := PTree.set s (Some false) !loop_info
+ else ()
+ | _ -> ()
+ end
+ | Some _ -> ()
+ in begin
+ List.iter (fun n ->
+ match get_some @@ PTree.get n code with
+ | Inop s | Iop (_,_,_,s) | Iload (_,_,_,_,_,s) | Istore (_,_,_,_,s) | Icall (_,_,_,_,s)
+ | Ibuiltin (_, _, _, s) ->
+ if get_some @@ PTree.get s is_loop_header then mark_path s n
+ | Icond _ -> () (* loop backedges are never Icond in CompCert *)
+ | Ijumptable _ -> ()
+ | Itailcall _ | Ireturn _ -> ()
+ ) bfs_order;
+ !loop_info
+ end
+
+ (* Remark - compared to the original paper, we don't use the store heuristic *)
+let get_directions code entrypoint = begin
+ Printf.printf "get_directions\n"; flush stdout;
+ let bfs_order = bfs code entrypoint in
+ let is_loop_header = get_loop_headers code entrypoint in
+ let loop_info = get_loop_info is_loop_header bfs_order code in
+ let directions = ref (PTree.map (fun n i -> None) code) in (* None <=> no predicted direction *)
+ begin
+ (* ptree_printbool is_loop_header; *)
+ (* Printf.printf "\n"; *)
+ List.iter (fun n ->
+ match (get_some @@ PTree.get n code) with
+ | Icond (cond, lr, ifso, ifnot, _) ->
+ (* Printf.printf "Analyzing %d.." (P.to_int n); *)
+ let heuristics = [ do_opcode_heuristic;
+ do_return_heuristic; do_loop2_heuristic loop_info n; do_loop_heuristic; do_call_heuristic;
+ (* do_store_heuristic *) ] in
+ let preferred = ref None in
+ begin
+ Printf.printf "Deciding condition for RTL node %d\n" (P.to_int n);
+ List.iter (fun do_heur ->
+ match !preferred with
+ | None -> preferred := do_heur code cond ifso ifnot is_loop_header
+ | Some _ -> ()
+ ) heuristics;
+ directions := PTree.set n !preferred !directions;
+ (match !preferred with | Some false -> Printf.printf "\tFALLTHROUGH\n"
+ | Some true -> Printf.printf "\tBRANCH\n"
+ | None -> Printf.printf "\tUNSURE\n");
+ Printf.printf "---------------------------------------\n"
+ end
+ | _ -> ()
+ ) bfs_order;
+ !directions
+ end
+end
+
+let update_direction direction = function
+| Icond (cond, lr, n, n', _) -> Icond (cond, lr, n, n', direction)
+| i -> i
+
+let rec update_direction_rec directions = function
+| [] -> PTree.empty
+| m::lm -> let (n, i) = m
+ in let direction = get_some @@ PTree.get n directions
+ in PTree.set n (update_direction direction i) (update_direction_rec directions lm)
+
+(* Uses branch prediction to write prediction annotations in Icond *)
+let update_directions code entrypoint = begin
+ Printf.printf "Update_directions\n"; flush stdout;
+ let directions = get_directions code entrypoint
+ in begin
+ (* Printf.printf "Ifso directions: ";
+ ptree_printbool directions;
+ Printf.printf "\n"; *)
+ update_direction_rec directions (PTree.elements code)
+ end
+end
+
+(** Trace selection *)
+
+let rec exists_false_rec = function
+ | [] -> false
+ | m::lm -> let (_, b) = m in if b then exists_false_rec lm else true
+
+let exists_false boolmap = exists_false_rec (PTree.elements boolmap)
+
+(* DFS using prediction info to guide the exploration *)
+let dfs code entrypoint = begin
+ Printf.printf "dfs\n"; flush stdout;
+ let visited = ref (PTree.map (fun n i -> false) code) in
+ let rec dfs_list code = function
+ | [] -> []
+ | node :: ln ->
+ if get_some @@ PTree.get node !visited then dfs_list code ln
+ else begin
+ visited := PTree.set node true !visited;
+ let next_nodes = (match get_some @@ PTree.get node code with
+ | Icall(_, _, _, _, n) | Ibuiltin (_, _, _, n) | Iop (_, _, _, n)
+ | Iload (_, _, _, _, _, n) | Istore (_, _, _, _, n) | Inop n -> [n]
+ | Ijumptable (_, ln) -> ln
+ | Itailcall _ | Ireturn _ -> []
+ | Icond (_, _, n1, n2, info) -> (match info with
+ | Some false -> [n2; n1]
+ | _ -> [n1; n2]
+ )
+ ) in node :: dfs_list code (next_nodes @ ln)
+ end
+ in dfs_list code [entrypoint]
+end
+
+(*
+let get_predecessors_ttl code =
+ let preds = ref (PTree.map (fun n i -> []) code) in
+ let process_inst (node, ti) = match ti with
+ | Tleaf _ -> ()
+ | Tnext (_, i) -> let succ = match i with
+ | Inop n | Iop (_,_,_,n) | Iload (_, _,_,_,_,n) | Istore (_,_,_,_,n)
+ | Icall (_,_,_,_,n) | Ibuiltin (_, _, _, n) -> [n]
+ | Icond (_,_,n1,n2,_) -> [n1;n2]
+ | Ijumptable (_,ln) -> ln
+ | _ -> []
+ in List.iter (fun s -> preds := PTree.set s (node::(get_some @@ PTree.get s !preds)) !preds) succ
+ in begin
+ List.iter process_inst (PTree.elements code);
+ !preds
+ end
+*)
+
+let rec select_unvisited_node is_visited = function
+| [] -> failwith "Empty list"
+| n :: ln -> if not (ptree_get_some n is_visited) then n else select_unvisited_node is_visited ln
+
+let best_successor_of node code is_visited =
+ match (PTree.get node code) with
+ | None -> failwith "No such node in the code"
+ | Some i ->
+ let next_node = match i with
+ | Inop n -> Some n
+ | Iop (_, _, _, n) -> Some n
+ | Iload (_, _, _, _, _, n) -> Some n
+ | Istore (_, _, _, _, n) -> Some n
+ | Icall (_, _, _, _, n) -> Some n
+ | Ibuiltin (_, _, _, n) -> Some n
+ | Icond (_, _, n1, n2, ob) -> (match ob with None -> None | Some false -> Some n2 | Some true -> Some n1)
+ | _ -> None
+ in match next_node with
+ | None -> None
+ | Some n -> if not (ptree_get_some n is_visited) then Some n else None
+
+(* FIXME - could be improved by selecting in priority the predicted paths *)
+let best_predecessor_of node predecessors order is_visited =
+ match (PTree.get node predecessors) with
+ | None -> failwith "No predecessor list found"
+ | Some lp -> try Some (List.find (fun n -> (List.mem n lp) && (not (ptree_get_some n is_visited))) order)
+ with Not_found -> None
+
+let print_trace t = print_intlist t
+
+let print_traces traces =
+ let rec f = function
+ | [] -> ()
+ | t::lt -> Printf.printf "\n\t"; print_trace t; Printf.printf ",\n"; f lt
+ in begin
+ Printf.printf "Traces: {";
+ f traces;
+ Printf.printf "}\n";
+ end
+
+(* Dumb (but linear) trace selection *)
+let select_traces_linear code entrypoint =
+ let is_visited = ref (PTree.map (fun n i -> false) code) in
+ let bfs_order = bfs code entrypoint in
+ let rec go_through node = begin
+ is_visited := PTree.set node true !is_visited;
+ let next_node = match (get_some @@ PTree.get node code) with
+ | Icall(_, _, _, _, n) | Ibuiltin (_, _, _, n) | Iop (_, _, _, n)
+ | Iload (_, _, _, _, _, n) | Istore (_, _, _, _, n) | Inop n -> Some n
+ | Ijumptable _ | Itailcall _ | Ireturn _ -> None
+ | Icond (_, _, n1, n2, info) -> (match info with
+ | Some false -> Some n2
+ | Some true -> Some n1
+ | None -> None
+ )
+ in match next_node with
+ | None -> [node]
+ | Some n ->
+ if not (get_some @@ PTree.get n !is_visited) then node :: go_through n
+ else [node]
+ end
+ in let traces = ref [] in begin
+ List.iter (fun n ->
+ if not (get_some @@ PTree.get n !is_visited) then
+ traces := (go_through n) :: !traces
+ ) bfs_order;
+ !traces
+ end
+
+
+(* Algorithm mostly inspired from Chang and Hwu 1988
+ * "Trace Selection for Compiling Large C Application Programs to Microcode" *)
+let select_traces_chang code entrypoint = begin
+ Printf.printf "select_traces\n"; flush stdout;
+ let order = dfs code entrypoint in
+ let predecessors = get_predecessors_rtl code in
+ let traces = ref [] in
+ let is_visited = ref (PTree.map (fun n i -> false) code) in begin (* mark all nodes visited *)
+ Printf.printf "Length: %d\n" (List.length order); flush stdout;
+ while exists_false !is_visited do (* while (there are unvisited nodes) *)
+ let seed = select_unvisited_node !is_visited order in
+ let trace = ref [seed] in
+ let current = ref seed in begin
+ is_visited := PTree.set seed true !is_visited; (* mark seed visited *)
+ let quit_loop = ref false in begin
+ while not !quit_loop do
+ let s = best_successor_of !current code !is_visited in
+ match s with
+ | None -> quit_loop := true (* if (s==0) exit loop *)
+ | Some succ -> begin
+ trace := !trace @ [succ];
+ is_visited := PTree.set succ true !is_visited; (* mark s visited *)
+ current := succ
+ end
+ done;
+ current := seed;
+ quit_loop := false;
+ while not !quit_loop do
+ let s = best_predecessor_of !current predecessors order !is_visited in
+ match s with
+ | None -> quit_loop := true (* if (s==0) exit loop *)
+ | Some pred -> begin
+ trace := pred :: !trace;
+ is_visited := PTree.set pred true !is_visited; (* mark s visited *)
+ current := pred
+ end
+ done;
+ traces := !trace :: !traces;
+ end
+ end
+ done;
+ (* Printf.printf "DFS: \t"; print_intlist order; Printf.printf "\n"; *)
+ Printf.printf "Traces: "; print_traces !traces;
+ !traces
+ end
+end
+
+let select_traces code entrypoint =
+ let length = List.length @@ PTree.elements code in
+ if (length < 5000) then select_traces_chang code entrypoint
+ else select_traces_linear code entrypoint
let rec make_identity_ptree_rec = function
| [] -> PTree.empty
| m::lm -> let (n, _) = m in PTree.set n n (make_identity_ptree_rec lm)
-let make_identity_ptree f = make_identity_ptree_rec (PTree.elements f.fn_code)
+let make_identity_ptree code = make_identity_ptree_rec (PTree.elements code)
+
+(* Change the pointers of preds nodes to point to n' instead of n *)
+let rec change_pointers code n n' = function
+ | [] -> code
+ | pred :: preds ->
+ let new_pred_inst = match ptree_get_some pred code with
+ | Icall(a, b, c, d, n0) -> assert (n0 == n); Icall(a, b, c, d, n')
+ | Ibuiltin(a, b, c, n0) -> assert (n0 == n); Ibuiltin(a, b, c, n')
+ | Ijumptable(a, ln) -> assert (optbool @@ List.find_opt (fun e -> e == n) ln);
+ Ijumptable(a, List.map (fun e -> if (e == n) then n' else e) ln)
+ | Icond(a, b, n1, n2, i) -> assert (n1 == n || n2 == n);
+ let n1' = if (n1 == n) then n' else n1
+ in let n2' = if (n2 == n) then n' else n2
+ in Icond(a, b, n1', n2', i)
+ | Inop n0 -> assert (n0 == n); Inop n'
+ | Iop (a, b, c, n0) -> assert (n0 == n); Iop (a, b, c, n')
+ | Iload (a, b, c, d, e, n0) -> assert (n0 == n); Iload (a, b, c, d, e, n')
+ | Istore (a, b, c, d, n0) -> assert (n0 == n); Istore (a, b, c, d, n')
+ | Itailcall _ | Ireturn _ -> failwith "That instruction cannot be a predecessor"
+ in let new_code = PTree.set pred new_pred_inst code
+ in change_pointers new_code n n' preds
+
+(* parent: parent of n to keep as parent
+ * preds: all the other parents of n
+ * n': the integer which should contain the duplicate of n
+ * returns: new code, new ptree *)
+let duplicate code ptree parent n preds n' =
+ (* Printf.printf "Duplicating node %d into %d..\n" (P.to_int n) (P.to_int n'); *)
+ match PTree.get n' code with
+ | Some _ -> failwith "The PTree already has a node n'"
+ | None ->
+ let c' = change_pointers code n n' preds
+ in let new_code = PTree.set n' (ptree_get_some n code) c'
+ and new_ptree = PTree.set n' n ptree
+ in (new_code, new_ptree)
+
+let rec maxint = function
+ | [] -> 0
+ | i :: l -> assert (i >= 0); let m = maxint l in if i > m then i else m
+
+let is_empty = function
+ | [] -> true
+ | _ -> false
+
+(* code: RTL code
+ * preds: mapping node -> predecessors
+ * ptree: the revmap
+ * trace: the trace to follow tail duplication on *)
+let tail_duplicate code preds ptree trace =
+ (* next_int: unused integer that can be used for the next duplication *)
+ let next_int = ref (maxint (List.map (fun e -> let (n, _) = e in P.to_int n) (PTree.elements code)) + 1)
+ (* last_node and last_duplicate store resp. the last processed node of the trace, and its duplication *)
+ in let last_node = ref None
+ in let last_duplicate = ref None
+ in let nb_duplicated = ref 0
+ (* recursive function on a trace *)
+ in let rec f code ptree is_first = function
+ | [] -> (code, ptree)
+ | n :: t ->
+ let (new_code, new_ptree) =
+ if is_first then (code, ptree) (* first node is never duplicated regardless of its inputs *)
+ else
+ let node_preds = ptree_get_some n preds
+ in let node_preds_nolast = List.filter (fun e -> e <> get_some !last_node) node_preds
+ in let final_node_preds = match !last_duplicate with
+ | None -> node_preds_nolast
+ | Some n' -> n' :: node_preds_nolast
+ in if not (is_empty final_node_preds) then
+ let n' = !next_int
+ in let (newc, newp) = duplicate code ptree !last_node n final_node_preds (P.of_int n')
+ in begin
+ next_int := !next_int + 1;
+ nb_duplicated := !nb_duplicated + 1;
+ last_duplicate := Some (P.of_int n');
+ (newc, newp)
+ end
+ else (code, ptree)
+ in begin
+ last_node := Some n;
+ f new_code new_ptree false t
+ end
+ in let new_code, new_ptree = f code ptree true trace
+ in (new_code, new_ptree, !nb_duplicated)
+
+let superblockify_traces code preds traces =
+ let max_nb_duplicated = !Clflags.option_fduplicate (* FIXME - should be architecture dependent *)
+ in let ptree = make_identity_ptree code
+ in let rec f code ptree = function
+ | [] -> (code, ptree, 0)
+ | trace :: traces ->
+ let new_code, new_ptree, nb_duplicated = tail_duplicate code preds ptree trace
+ in if (nb_duplicated < max_nb_duplicated) then f new_code new_ptree traces
+ else (Printf.printf "Too many duplicated nodes, aborting tail duplication\n"; (code, ptree, 0))
+ in let new_code, new_ptree, _ = f code ptree traces
+ in (new_code, new_ptree)
+
+let rec invert_iconds_trace code = function
+ | [] -> code
+ | n :: ln ->
+ let code' = match ptree_get_some n code with
+ | Icond (c, lr, ifso, ifnot, info) -> (match info with
+ | Some true -> begin
+ (* Printf.printf "Reversing ifso/ifnot for node %d\n" (P.to_int n); *)
+ PTree.set n (Icond (Op.negate_condition c, lr, ifnot, ifso, Some false)) code
+ end
+ | _ -> code)
+ | _ -> code
+ in invert_iconds_trace code' ln
+
+let rec invert_iconds code = function
+ | [] -> code
+ | t :: ts ->
+ let code' = if !Clflags.option_finvertcond then invert_iconds_trace code t
+ else code
+ in invert_iconds code' ts
-(* For now, identity function *)
let duplicate_aux f =
- let pTreeId = make_identity_ptree f
- in ((f.fn_code, f.fn_entrypoint), pTreeId)
+ let entrypoint = f.fn_entrypoint in
+ if !Clflags.option_fduplicate < 0 then
+ ((f.fn_code, entrypoint), make_identity_ptree f.fn_code)
+ else
+ let code = update_directions (f.fn_code) entrypoint in
+ let traces = select_traces code entrypoint in
+ let icond_code = invert_iconds code traces in
+ let preds = get_predecessors_rtl icond_code in
+ if !Clflags.option_fduplicate >= 1 then
+ let (new_code, pTreeId) = ((* print_traces traces; *) superblockify_traces icond_code preds traces) in
+ ((new_code, f.fn_entrypoint), pTreeId)
+ else
+ ((icond_code, entrypoint), make_identity_ptree code)
diff --git a/backend/Duplicateproof.v b/backend/Duplicateproof.v
index 9d56e86f..6b598dc7 100644
--- a/backend/Duplicateproof.v
+++ b/backend/Duplicateproof.v
@@ -13,8 +13,8 @@ Inductive match_inst (dupmap: PTree.t node): instruction -> instruction -> Prop
dupmap!n' = (Some n) -> match_inst dupmap (Inop n) (Inop n')
| match_inst_op: forall n n' op lr r,
dupmap!n' = (Some n) -> match_inst dupmap (Iop op lr r n) (Iop op lr r n')
- | match_inst_load: forall n n' m a lr r,
- dupmap!n' = (Some n) -> match_inst dupmap (Iload m a lr r n) (Iload m a lr r n')
+ | match_inst_load: forall n n' tm m a lr r,
+ dupmap!n' = (Some n) -> match_inst dupmap (Iload tm m a lr r n) (Iload tm m a lr r n')
| match_inst_store: forall n n' m a lr r,
dupmap!n' = (Some n) -> match_inst dupmap (Istore m a lr r n) (Istore m a lr r n')
| match_inst_call: forall n n' s ri lr r,
@@ -23,9 +23,12 @@ Inductive match_inst (dupmap: PTree.t node): instruction -> instruction -> Prop
match_inst dupmap (Itailcall s ri lr) (Itailcall s ri lr)
| match_inst_builtin: forall n n' ef la br,
dupmap!n' = (Some n) -> match_inst dupmap (Ibuiltin ef la br n) (Ibuiltin ef la br n')
- | match_inst_cond: forall ifso ifso' ifnot ifnot' c lr,
+ | match_inst_cond: forall ifso ifso' ifnot ifnot' c lr i i',
dupmap!ifso' = (Some ifso) -> dupmap!ifnot' = (Some ifnot) ->
- match_inst dupmap (Icond c lr ifso ifnot) (Icond c lr ifso' ifnot')
+ match_inst dupmap (Icond c lr ifso ifnot i) (Icond c lr ifso' ifnot' i')
+ | match_inst_revcond: forall ifso ifso' ifnot ifnot' c lr i i',
+ dupmap!ifso' = (Some ifso) -> dupmap!ifnot' = (Some ifnot) ->
+ match_inst dupmap (Icond c lr ifso ifnot i) (Icond (negate_condition c) lr ifnot' ifso' i')
| match_inst_jumptable: forall ln ln' r,
list_forall2 (fun n n' => (dupmap!n' = (Some n))) ln ln' ->
match_inst dupmap (Ijumptable r ln) (Ijumptable r ln')
@@ -137,6 +140,7 @@ Proof.
(* Iload *)
- destruct i'; try (inversion H; fail). monadInv H.
destruct x. eapply verify_is_copy_correct in EQ.
+ destruct (trapping_mode_eq _ _); try discriminate.
destruct (chunk_eq _ _); try discriminate.
destruct (eq_addressing _ _); try discriminate.
destruct (list_eq_dec _ _ _); try discriminate.
@@ -172,12 +176,16 @@ Proof.
destruct (builtin_res_eq_pos _ _); try discriminate. subst.
constructor. assumption.
(* Icond *)
- - destruct i'; try (inversion H; fail). monadInv H.
- destruct x. eapply verify_is_copy_correct in EQ.
- destruct x0. eapply verify_is_copy_correct in EQ1.
- destruct (eq_condition _ _); try discriminate.
+ - destruct i'; try (inversion H; fail).
destruct (list_eq_dec _ _ _); try discriminate. subst.
- constructor; assumption.
+ destruct (eq_condition _ _); try discriminate.
+ + monadInv H. destruct x. eapply verify_is_copy_correct in EQ.
+ destruct x0. eapply verify_is_copy_correct in EQ1.
+ constructor; assumption.
+ + destruct (eq_condition _ _); try discriminate.
+ monadInv H. destruct x. eapply verify_is_copy_correct in EQ.
+ destruct x0. eapply verify_is_copy_correct in EQ1.
+ constructor; assumption.
(* Ijumptable *)
- destruct i'; try (inversion H; fail). monadInv H.
destruct x. eapply verify_is_copy_list_correct in EQ.
@@ -344,15 +352,16 @@ Proof.
intros. inv H.
exploit function_ptr_translated; eauto. intros (tf & FIND & TRANSF).
eexists. split.
- - econstructor.
+ - econstructor; eauto.
+ eapply (Genv.init_mem_transf_partial TRANSL); eauto.
+ replace (prog_main tprog) with (prog_main prog). rewrite symbols_preserved. eauto.
symmetry. eapply match_program_main. eauto.
- + exploit function_ptr_translated; eauto.
+ destruct f.
* monadInv TRANSF. rewrite <- H3. symmetry; eapply transf_function_preserves. assumption.
* monadInv TRANSF. assumption.
- - constructor; eauto. constructor. apply transf_fundef_correct; auto.
+ - constructor; eauto.
+ + constructor.
+ + apply transf_fundef_correct; auto.
Qed.
Theorem transf_final_states:
@@ -369,7 +378,7 @@ Theorem step_simulation:
step tge s2 t s2'
/\ match_states s1' s2'.
Proof.
- Local Hint Resolve transf_fundef_correct.
+ Local Hint Resolve transf_fundef_correct: core.
induction 1; intros; inv MS.
(* Inop *)
- eapply dupmap_correct in DUPLIC; eauto.
@@ -390,14 +399,29 @@ Proof.
destruct DUPLIC as (i' & H2 & H3). inv H3.
pose symbols_preserved as SYMPRES.
eexists. split.
- + eapply exec_Iload; eauto. erewrite eval_addressing_preserved; eauto.
+ + eapply exec_Iload; eauto; (* is the follow still needed?*) erewrite eval_addressing_preserved; eauto.
+ + econstructor; eauto.
+(* Iload notrap1 *)
+ - eapply dupmap_correct in DUPLIC; eauto.
+ destruct DUPLIC as (i' & H2 & H3). inv H3.
+ pose symbols_preserved as SYMPRES.
+ eexists. split.
+ + eapply exec_Iload_notrap1; eauto; erewrite eval_addressing_preserved; eauto.
+ + econstructor; eauto.
+(* Iload notrap2 *)
+ - eapply dupmap_correct in DUPLIC; eauto.
+ destruct DUPLIC as (i' & H2 & H3). inv H3.
+ pose symbols_preserved as SYMPRES.
+ eexists. split.
+ + eapply exec_Iload_notrap2; eauto; erewrite eval_addressing_preserved; eauto.
+ econstructor; eauto.
+
(* Istore *)
- eapply dupmap_correct in DUPLIC; eauto.
destruct DUPLIC as (i' & H2 & H3). inv H3.
pose symbols_preserved as SYMPRES.
eexists. split.
- + eapply exec_Istore; eauto. erewrite eval_addressing_preserved; eauto.
+ + eapply exec_Istore; eauto; erewrite eval_addressing_preserved; eauto.
+ econstructor; eauto.
(* Icall *)
- eapply dupmap_correct in DUPLIC; eauto.
@@ -446,10 +470,16 @@ Proof.
(* Icond *)
- eapply dupmap_correct in DUPLIC; eauto.
destruct DUPLIC as (i' & H2 & H3). inv H3.
- pose symbols_preserved as SYMPRES.
- eexists. split.
- + eapply exec_Icond; eauto.
- + econstructor; eauto. destruct b; auto.
+ * (* match_inst_cond *)
+ pose symbols_preserved as SYMPRES.
+ eexists. split.
+ + eapply exec_Icond; eauto.
+ + econstructor; eauto. destruct b; auto.
+ * (* match_inst_revcond *)
+ pose symbols_preserved as SYMPRES.
+ eexists. split.
+ + eapply exec_Icond; eauto. rewrite eval_negate_condition. rewrite H0. simpl. eauto.
+ + econstructor; eauto. destruct b; auto.
(* Ijumptable *)
- eapply dupmap_correct in DUPLIC; eauto.
destruct DUPLIC as (i' & H2 & H3). inv H3.
diff --git a/backend/ForwardMoves.v b/backend/ForwardMoves.v
new file mode 100644
index 00000000..7cfd411f
--- /dev/null
+++ b/backend/ForwardMoves.v
@@ -0,0 +1,333 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+(* Static analysis *)
+
+Module RELATION.
+
+Definition t := (PTree.t reg).
+Definition eq (r1 r2 : t) :=
+ forall x, (PTree.get x r1) = (PTree.get x r2).
+
+Definition top : t := PTree.empty reg.
+
+Lemma eq_refl: forall x, eq x x.
+Proof.
+ unfold eq.
+ intros; reflexivity.
+Qed.
+
+Lemma eq_sym: forall x y, eq x y -> eq y x.
+Proof.
+ unfold eq.
+ intros; eauto.
+Qed.
+
+Lemma eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+Proof.
+ unfold eq.
+ intros; congruence.
+Qed.
+
+Definition reg_beq (x y : reg) :=
+ if Pos.eq_dec x y then true else false.
+
+Definition beq (r1 r2 : t) := PTree.beq reg_beq r1 r2.
+
+Lemma beq_correct: forall r1 r2, beq r1 r2 = true -> eq r1 r2.
+Proof.
+ unfold beq, eq. intros r1 r2 EQ x.
+ pose proof (PTree.beq_correct reg_beq r1 r2) as CORRECT.
+ destruct CORRECT as [CORRECTF CORRECTB].
+ pose proof (CORRECTF EQ x) as EQx.
+ clear CORRECTF CORRECTB EQ.
+ unfold reg_beq in *.
+ destruct (r1 ! x) as [R1x | ] in *;
+ destruct (r2 ! x) as [R2x | ] in *;
+ trivial; try contradiction.
+ destruct (Pos.eq_dec R1x R2x) in *; congruence.
+Qed.
+
+Definition ge (r1 r2 : t) :=
+ forall x,
+ match PTree.get x r1 with
+ | None => True
+ | Some v => (PTree.get x r2) = Some v
+ end.
+
+Lemma ge_refl: forall r1 r2, eq r1 r2 -> ge r1 r2.
+Proof.
+ unfold eq, ge.
+ intros r1 r2 EQ x.
+ pose proof (EQ x) as EQx.
+ clear EQ.
+ destruct (r1 ! x).
+ - congruence.
+ - trivial.
+Qed.
+
+Lemma ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+Proof.
+ unfold ge.
+ intros r1 r2 r3 GE12 GE23 x.
+ pose proof (GE12 x) as GE12x; clear GE12.
+ pose proof (GE23 x) as GE23x; clear GE23.
+ destruct (r1 ! x); trivial.
+ destruct (r2 ! x); congruence.
+Qed.
+
+Definition lub (r1 r2 : t) :=
+ PTree.combine
+ (fun ov1 ov2 =>
+ match ov1, ov2 with
+ | (Some v1), (Some v2) =>
+ if Pos.eq_dec v1 v2
+ then ov1
+ else None
+ | None, _
+ | _, None => None
+ end)
+ r1 r2.
+
+Lemma ge_lub_left: forall x y, ge (lub x y) x.
+Proof.
+ unfold ge, lub.
+ intros r1 r2 x.
+ rewrite PTree.gcombine by reflexivity.
+ destruct (_ ! _); trivial.
+ destruct (_ ! _); trivial.
+ destruct (Pos.eq_dec _ _); trivial.
+Qed.
+
+Lemma ge_lub_right: forall x y, ge (lub x y) y.
+Proof.
+ unfold ge, lub.
+ intros r1 r2 x.
+ rewrite PTree.gcombine by reflexivity.
+ destruct (_ ! _); trivial.
+ destruct (_ ! _); trivial.
+ destruct (Pos.eq_dec _ _); trivial.
+ congruence.
+Qed.
+
+End RELATION.
+
+Module Type SEMILATTICE_WITHOUT_BOTTOM.
+
+ Parameter t: Type.
+ Parameter eq: t -> t -> Prop.
+ Axiom eq_refl: forall x, eq x x.
+ Axiom eq_sym: forall x y, eq x y -> eq y x.
+ Axiom eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+ Parameter beq: t -> t -> bool.
+ Axiom beq_correct: forall x y, beq x y = true -> eq x y.
+ Parameter ge: t -> t -> Prop.
+ Axiom ge_refl: forall x y, eq x y -> ge x y.
+ Axiom ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+ Parameter lub: t -> t -> t.
+ Axiom ge_lub_left: forall x y, ge (lub x y) x.
+ Axiom ge_lub_right: forall x y, ge (lub x y) y.
+
+End SEMILATTICE_WITHOUT_BOTTOM.
+
+Module ADD_BOTTOM(L : SEMILATTICE_WITHOUT_BOTTOM).
+ Definition t := option L.t.
+ Definition eq (a b : t) :=
+ match a, b with
+ | None, None => True
+ | Some x, Some y => L.eq x y
+ | Some _, None | None, Some _ => False
+ end.
+
+ Lemma eq_refl: forall x, eq x x.
+ Proof.
+ unfold eq; destruct x; trivial.
+ apply L.eq_refl.
+ Qed.
+
+ Lemma eq_sym: forall x y, eq x y -> eq y x.
+ Proof.
+ unfold eq; destruct x; destruct y; trivial.
+ apply L.eq_sym.
+ Qed.
+
+ Lemma eq_trans: forall x y z, eq x y -> eq y z -> eq x z.
+ Proof.
+ unfold eq; destruct x; destruct y; destruct z; trivial.
+ - apply L.eq_trans.
+ - contradiction.
+ Qed.
+
+ Definition beq (x y : t) :=
+ match x, y with
+ | None, None => true
+ | Some x, Some y => L.beq x y
+ | Some _, None | None, Some _ => false
+ end.
+
+ Lemma beq_correct: forall x y, beq x y = true -> eq x y.
+ Proof.
+ unfold beq, eq.
+ destruct x; destruct y; trivial; try congruence.
+ apply L.beq_correct.
+ Qed.
+
+ Definition ge (x y : t) :=
+ match x, y with
+ | None, Some _ => False
+ | _, None => True
+ | Some a, Some b => L.ge a b
+ end.
+
+ Lemma ge_refl: forall x y, eq x y -> ge x y.
+ Proof.
+ unfold eq, ge.
+ destruct x; destruct y; trivial.
+ apply L.ge_refl.
+ Qed.
+
+ Lemma ge_trans: forall x y z, ge x y -> ge y z -> ge x z.
+ Proof.
+ unfold ge.
+ destruct x; destruct y; destruct z; trivial; try contradiction.
+ apply L.ge_trans.
+ Qed.
+
+ Definition bot: t := None.
+ Lemma ge_bot: forall x, ge x bot.
+ Proof.
+ unfold ge, bot.
+ destruct x; trivial.
+ Qed.
+
+ Definition lub (a b : t) :=
+ match a, b with
+ | None, _ => b
+ | _, None => a
+ | (Some x), (Some y) => Some (L.lub x y)
+ end.
+
+ Lemma ge_lub_left: forall x y, ge (lub x y) x.
+ Proof.
+ unfold ge, lub.
+ destruct x; destruct y; trivial.
+ - apply L.ge_lub_left.
+ - apply L.ge_refl.
+ apply L.eq_refl.
+ Qed.
+
+ Lemma ge_lub_right: forall x y, ge (lub x y) y.
+ Proof.
+ unfold ge, lub.
+ destruct x; destruct y; trivial.
+ - apply L.ge_lub_right.
+ - apply L.ge_refl.
+ apply L.eq_refl.
+ Qed.
+End ADD_BOTTOM.
+
+Module RB := ADD_BOTTOM(RELATION).
+Module DS := Dataflow_Solver(RB)(NodeSetForward).
+
+Definition kill (dst : reg) (rel : RELATION.t) :=
+ PTree.filter1 (fun x => if Pos.eq_dec dst x then false else true)
+ (PTree.remove dst rel).
+
+Definition move (src dst : reg) (rel : RELATION.t) :=
+ PTree.set dst (match PTree.get src rel with
+ | Some src' => src'
+ | None => src
+ end) (kill dst rel).
+
+Fixpoint kill_builtin_res (res : builtin_res reg) (rel : RELATION.t) :=
+ match res with
+ | BR z => kill z rel
+ | BR_none => rel
+ | BR_splitlong hi lo => kill_builtin_res hi (kill_builtin_res lo rel)
+ end.
+
+Definition apply_instr instr x :=
+ match instr with
+ | Inop _
+ | Icond _ _ _ _ _
+ | Ijumptable _ _
+ | Istore _ _ _ _ _ => Some x
+ | Iop Omove (src :: nil) dst _ => Some (move src dst x)
+ | Iop _ _ dst _
+ | Iload _ _ _ _ dst _
+ | Icall _ _ _ dst _ => Some (kill dst x)
+ | Ibuiltin _ _ res _ => Some (RELATION.top) (* TODO (kill_builtin_res res x) *)
+ | Itailcall _ _ _ | Ireturn _ => RB.bot
+ end.
+
+Definition apply_instr' code (pc : node) (ro : RB.t) : RB.t :=
+ match ro with
+ | None => None
+ | Some x =>
+ match code ! pc with
+ | None => RB.bot
+ | Some instr => apply_instr instr x
+ end
+ end.
+
+Definition forward_map (f : RTL.function) := DS.fixpoint
+ (RTL.fn_code f) RTL.successors_instr
+ (apply_instr' (RTL.fn_code f)) (RTL.fn_entrypoint f) (Some RELATION.top).
+
+Definition get_r (rel : RELATION.t) (x : reg) :=
+ match PTree.get x rel with
+ | None => x
+ | Some src => src
+ end.
+
+Definition get_rb (rb : RB.t) (x : reg) :=
+ match rb with
+ | None => x
+ | Some rel => get_r rel x
+ end.
+
+Definition subst_arg (fmap : option (PMap.t RB.t)) (pc : node) (x : reg) : reg :=
+ match fmap with
+ | None => x
+ | Some inv => get_rb (PMap.get pc inv) x
+ end.
+
+Definition subst_args fmap pc := List.map (subst_arg fmap pc).
+
+(* Transform *)
+Definition transf_instr (fmap : option (PMap.t RB.t))
+ (pc: node) (instr: instruction) :=
+ match instr with
+ | Iop op args dst s =>
+ Iop op (subst_args fmap pc args) dst s
+ | Iload trap chunk addr args dst s =>
+ Iload trap chunk addr (subst_args fmap pc args) dst s
+ | Istore chunk addr args src s =>
+ Istore chunk addr (subst_args fmap pc args) src s
+ | Icall sig ros args dst s =>
+ Icall sig ros (subst_args fmap pc args) dst s
+ | Itailcall sig ros args =>
+ Itailcall sig ros (subst_args fmap pc args)
+ | Icond cond args s1 s2 i =>
+ Icond cond (subst_args fmap pc args) s1 s2 i
+ | Ijumptable arg tbl =>
+ Ijumptable (subst_arg fmap pc arg) tbl
+ | Ireturn (Some arg) =>
+ Ireturn (Some (subst_arg fmap pc arg))
+ | _ => instr
+ end.
+
+Definition transf_function (f: function) : function :=
+ {| fn_sig := f.(fn_sig);
+ fn_params := f.(fn_params);
+ fn_stacksize := f.(fn_stacksize);
+ fn_code := PTree.map (transf_instr (forward_map f)) f.(fn_code);
+ fn_entrypoint := f.(fn_entrypoint) |}.
+
+
+Definition transf_fundef (fd: fundef) : fundef :=
+ AST.transf_fundef transf_function fd.
+
+Definition transf_program (p: program) : program :=
+ transform_program transf_fundef p.
diff --git a/backend/ForwardMovesproof.v b/backend/ForwardMovesproof.v
new file mode 100644
index 00000000..826d4250
--- /dev/null
+++ b/backend/ForwardMovesproof.v
@@ -0,0 +1,801 @@
+Require Import FunInd.
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import ForwardMoves.
+
+
+Definition match_prog (p tp: RTL.program) :=
+ match_program (fun ctx f tf => tf = transf_fundef f) eq p tp.
+
+Lemma transf_program_match:
+ forall p, match_prog p (transf_program p).
+Proof.
+ intros. eapply match_transform_program; eauto.
+Qed.
+
+Section PRESERVATION.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma functions_translated:
+ forall v f,
+ Genv.find_funct ge v = Some f ->
+ Genv.find_funct tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_transf TRANSL).
+
+Lemma function_ptr_translated:
+ forall v f,
+ Genv.find_funct_ptr ge v = Some f ->
+ Genv.find_funct_ptr tge v = Some (transf_fundef f).
+Proof (Genv.find_funct_ptr_transf TRANSL).
+
+Lemma symbols_preserved:
+ forall id,
+ Genv.find_symbol tge id = Genv.find_symbol ge id.
+Proof (Genv.find_symbol_transf TRANSL).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_transf TRANSL).
+
+Lemma sig_preserved:
+ forall f, funsig (transf_fundef f) = funsig f.
+Proof.
+ destruct f; trivial.
+Qed.
+
+Lemma find_function_translated:
+ forall ros rs fd,
+ find_function ge ros rs = Some fd ->
+ find_function tge ros rs = Some (transf_fundef fd).
+Proof.
+ unfold find_function; intros. destruct ros as [r|id].
+ eapply functions_translated; eauto.
+ rewrite symbols_preserved. destruct (Genv.find_symbol ge id); try congruence.
+ eapply function_ptr_translated; eauto.
+Qed.
+
+Lemma transf_function_at:
+ forall f pc i,
+ f.(fn_code)!pc = Some i ->
+ (transf_function f).(fn_code)!pc =
+ Some(transf_instr (forward_map f) pc i).
+Proof.
+ intros until i. intro CODE.
+ unfold transf_function; simpl.
+ rewrite PTree.gmap.
+ unfold option_map.
+ rewrite CODE.
+ reflexivity.
+Qed.
+
+(*
+Definition fmap_sem (fmap : option (PMap.t RB.t)) (pc : node) (rs : regset) :=
+ forall x : reg,
+ (rs # (subst_arg fmap pc x)) = (rs # x).
+ *)
+
+Lemma apply_instr'_bot :
+ forall code,
+ forall pc,
+ RB.eq (apply_instr' code pc RB.bot) RB.bot.
+Proof.
+ reflexivity.
+Qed.
+
+Definition get_rb_sem (rb : RB.t) (rs : regset) :=
+ match rb with
+ | None => False
+ | Some rel =>
+ forall x : reg,
+ (rs # (get_r rel x)) = (rs # x)
+ end.
+
+Lemma get_rb_sem_ge:
+ forall rb1 rb2 : RB.t,
+ (RB.ge rb1 rb2) ->
+ forall rs : regset,
+ (get_rb_sem rb2 rs) -> (get_rb_sem rb1 rs).
+Proof.
+ destruct rb1 as [r1 | ];
+ destruct rb2 as [r2 | ];
+ unfold get_rb_sem;
+ simpl;
+ intros GE rs RB2RS;
+ try contradiction.
+ unfold RELATION.ge in GE.
+ unfold get_r in *.
+ intro x.
+ pose proof (GE x) as GEx.
+ pose proof (RB2RS x) as RB2RSx.
+ destruct (r1 ! x) as [r1x | ] in *;
+ destruct (r2 ! x) as [r2x | ] in *;
+ congruence.
+Qed.
+
+Definition fmap_sem (fmap : option (PMap.t RB.t))
+ (pc : node) (rs : regset) :=
+ match fmap with
+ | None => True
+ | Some m => get_rb_sem (PMap.get pc m) rs
+ end.
+
+Lemma subst_arg_ok:
+ forall f,
+ forall pc,
+ forall rs,
+ forall arg,
+ fmap_sem (forward_map f) pc rs ->
+ rs # (subst_arg (forward_map f) pc arg) = rs # arg.
+Proof.
+ intros until arg.
+ intro SEM.
+ unfold fmap_sem in SEM.
+ destruct (forward_map f) as [map |]in *; trivial.
+ simpl.
+ unfold get_rb_sem in *.
+ destruct (map # pc).
+ 2: contradiction.
+ apply SEM.
+Qed.
+
+Lemma subst_args_ok:
+ forall f,
+ forall pc,
+ forall rs,
+ fmap_sem (forward_map f) pc rs ->
+ forall args,
+ rs ## (subst_args (forward_map f) pc args) = rs ## args.
+Proof.
+ induction args; trivial.
+ simpl.
+ f_equal.
+ apply subst_arg_ok; assumption.
+ assumption.
+Qed.
+
+Lemma kill_ok:
+ forall dst,
+ forall mpc,
+ forall rs,
+ forall v,
+ get_rb_sem (Some mpc) rs ->
+ get_rb_sem (Some (kill dst mpc)) rs # dst <- v.
+Proof.
+ unfold get_rb_sem.
+ intros until v.
+ intros SEM x.
+ destruct (Pos.eq_dec x dst) as [EQ | NEQ].
+ {
+ subst dst.
+ rewrite Regmap.gss.
+ unfold kill, get_r.
+ rewrite PTree.gfilter1.
+ rewrite PTree.grs.
+ apply Regmap.gss.
+ }
+ rewrite (Regmap.gso v rs NEQ).
+ unfold kill, get_r in *.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by assumption.
+ pose proof (SEM x) as SEMx.
+ destruct (mpc ! x).
+ {
+ destruct (Pos.eq_dec dst r).
+ {
+ subst dst.
+ rewrite Regmap.gso by assumption.
+ reflexivity.
+ }
+ rewrite Regmap.gso by congruence.
+ assumption.
+ }
+ rewrite Regmap.gso by assumption.
+ reflexivity.
+Qed.
+
+Lemma kill_weaken:
+ forall dst,
+ forall mpc,
+ forall rs,
+ get_rb_sem (Some mpc) rs ->
+ get_rb_sem (Some (kill dst mpc)) rs.
+Proof.
+ unfold get_rb_sem.
+ intros until rs.
+ intros SEM x.
+ destruct (Pos.eq_dec x dst) as [EQ | NEQ].
+ {
+ subst dst.
+ unfold kill, get_r.
+ rewrite PTree.gfilter1.
+ rewrite PTree.grs.
+ reflexivity.
+ }
+ unfold kill, get_r in *.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by assumption.
+ pose proof (SEM x) as SEMx.
+ destruct (mpc ! x).
+ {
+ destruct (Pos.eq_dec dst r).
+ {
+ reflexivity.
+ }
+ assumption.
+ }
+ reflexivity.
+Qed.
+
+Lemma top_ok :
+ forall rs, get_rb_sem (Some RELATION.top) rs.
+Proof.
+ unfold get_rb_sem, RELATION.top.
+ intros.
+ unfold get_r.
+ rewrite PTree.gempty.
+ reflexivity.
+Qed.
+
+Lemma move_ok:
+ forall mpc : RELATION.t,
+ forall src res : reg,
+ forall rs : regset,
+ get_rb_sem (Some mpc) rs ->
+ get_rb_sem (Some (move src res mpc)) (rs # res <- (rs # src)).
+Proof.
+ unfold get_rb_sem, move.
+ intros until rs.
+ intros SEM x.
+ unfold get_r in *.
+ destruct (Pos.eq_dec res x).
+ {
+ subst res.
+ rewrite PTree.gss.
+ rewrite Regmap.gss.
+ pose proof (SEM src) as SEMsrc.
+ destruct (mpc ! src) as [mpcsrc | ] in *.
+ {
+ destruct (Pos.eq_dec x mpcsrc).
+ {
+ subst mpcsrc.
+ rewrite Regmap.gss.
+ reflexivity.
+ }
+ rewrite Regmap.gso by congruence.
+ assumption.
+ }
+ destruct (Pos.eq_dec x src).
+ {
+ subst src.
+ rewrite Regmap.gss.
+ reflexivity.
+ }
+ rewrite Regmap.gso by congruence.
+ reflexivity.
+ }
+ rewrite PTree.gso by congruence.
+ rewrite Regmap.gso with (i := x) by congruence.
+ unfold kill.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by congruence.
+ pose proof (SEM x) as SEMx.
+ destruct (mpc ! x) as [ r |].
+ {
+ destruct (Pos.eq_dec res r).
+ {
+ subst r.
+ rewrite Regmap.gso by congruence.
+ trivial.
+ }
+ rewrite Regmap.gso by congruence.
+ assumption.
+ }
+ rewrite Regmap.gso by congruence.
+ reflexivity.
+Qed.
+
+Ltac TR_AT :=
+ match goal with
+ | [ A: (fn_code _)!_ = Some _ |- _ ] =>
+ generalize (transf_function_at _ _ _ A); intros
+ end.
+
+Definition is_killed_in_map (map : PMap.t RB.t) pc res :=
+ match PMap.get pc map with
+ | None => True
+ | Some rel => exists rel', RELATION.ge rel (kill res rel')
+ end.
+
+Definition is_killed_in_fmap fmap pc res :=
+ match fmap with
+ | None => True
+ | Some map => is_killed_in_map map pc res
+ end.
+
+Definition killed_twice:
+ forall rel : RELATION.t,
+ forall res,
+ RELATION.eq (kill res rel) (kill res (kill res rel)).
+Proof.
+ unfold kill, RELATION.eq.
+ intros.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gfilter1.
+ destruct (Pos.eq_dec res x).
+ {
+ subst res.
+ rewrite PTree.grs.
+ rewrite PTree.grs.
+ reflexivity.
+ }
+ rewrite PTree.gro by congruence.
+ rewrite PTree.gro by congruence.
+ rewrite PTree.gfilter1.
+ rewrite PTree.gro by congruence.
+ destruct (rel ! x) as [relx | ]; trivial.
+ destruct (Pos.eq_dec res relx); trivial.
+ destruct (Pos.eq_dec res relx); congruence.
+Qed.
+
+Lemma get_rb_killed:
+ forall mpc,
+ forall rs,
+ forall rel,
+ forall res,
+ forall vres,
+ (get_rb_sem (Some mpc) rs) ->
+ (RELATION.ge mpc (kill res rel)) ->
+ (get_rb_sem (Some mpc) rs # res <- vres).
+Proof.
+ simpl.
+ intros until vres.
+ intros SEM GE x.
+ pose proof (GE x) as GEx.
+ pose proof (SEM x) as SEMx.
+ unfold get_r in *.
+ destruct (mpc ! x) as [mpcx | ] in *; trivial.
+ unfold kill in GEx.
+ rewrite PTree.gfilter1 in GEx.
+ destruct (Pos.eq_dec res x) as [ | res_NE_x].
+ {
+ subst res.
+ rewrite PTree.grs in GEx.
+ discriminate.
+ }
+ rewrite PTree.gro in GEx by congruence.
+ rewrite Regmap.gso with (i := x) by congruence.
+ destruct (rel ! x) as [relx | ]; try discriminate.
+ destruct (Pos.eq_dec res relx) as [ res_EQ_relx | res_NE_relx] in *; try discriminate.
+ rewrite Regmap.gso by congruence.
+ congruence.
+Qed.
+
+Inductive match_frames: RTL.stackframe -> RTL.stackframe -> Prop :=
+| match_frames_intro: forall res f sp pc rs,
+ (fmap_sem (forward_map f) pc rs) ->
+ (is_killed_in_fmap (forward_map f) pc res) ->
+ match_frames (Stackframe res f sp pc rs)
+ (Stackframe res (transf_function f) sp pc rs).
+
+Inductive match_states: RTL.state -> RTL.state -> Prop :=
+ | match_regular_states: forall stk f sp pc rs m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ (fmap_sem (forward_map f) pc rs) ->
+ match_states (State stk f sp pc rs m)
+ (State stk' (transf_function f) sp pc rs m)
+ | match_callstates: forall stk f args m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Callstate stk f args m)
+ (Callstate stk' (transf_fundef f) args m)
+ | match_returnstates: forall stk v m stk'
+ (STACKS: list_forall2 match_frames stk stk'),
+ match_states (Returnstate stk v m)
+ (Returnstate stk' v m).
+
+Lemma op_cases:
+ forall op,
+ forall args,
+ forall dst,
+ forall s,
+ forall x,
+ (exists src, op=Omove /\ args = src :: nil /\
+ (apply_instr (Iop op args dst s) x) = Some (move src dst x))
+ \/
+ (apply_instr (Iop op args dst s) x) = Some (kill dst x).
+Proof.
+ destruct op; try (right; simpl; reflexivity).
+ destruct args as [| arg0 args0t]; try (right; simpl; reflexivity).
+ destruct args0t as [| arg1 args1t]; try (right; simpl; reflexivity).
+ left.
+ eauto.
+Qed.
+
+Lemma step_simulation:
+ forall S1 t S2, RTL.step ge S1 t S2 ->
+ forall S1', match_states S1 S1' ->
+ exists S2', RTL.step tge S1' t S2' /\ match_states S2 S2'.
+Proof.
+ induction 1; intros S1' MS; inv MS; try TR_AT.
+- (* nop *)
+ econstructor; split. eapply exec_Inop; eauto.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply get_rb_sem_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ unfold get_rb_sem in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+- (* op *)
+ econstructor; split.
+ eapply exec_Iop with (v := v); eauto.
+ rewrite <- H0.
+ rewrite subst_args_ok by assumption.
+ apply eval_operation_preserved. exact symbols_preserved.
+ constructor; auto.
+
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ assert (RB.ge (map # pc') (apply_instr' (fn_code f) pc (map # pc))) as GE.
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr' in GE.
+ rewrite MPC in GE.
+ rewrite H in GE.
+
+ destruct (op_cases op args res pc' mpc) as [[src [OP [ARGS MOVE]]] | KILL].
+ {
+ subst op.
+ subst args.
+ rewrite MOVE in GE.
+ simpl in H0.
+ simpl in GE.
+ apply get_rb_sem_ge with (rb2 := Some (move src res mpc)).
+ assumption.
+ replace v with (rs # src) by congruence.
+ apply move_ok.
+ assumption.
+ }
+ rewrite KILL in GE.
+ apply get_rb_sem_ge with (rb2 := Some (kill res mpc)).
+ assumption.
+ apply kill_ok.
+ assumption.
+
+(* load *)
+- econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0.
+ apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload; eauto.
+ rewrite subst_args_ok; assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply get_rb_sem_ge with (rb2 := Some (kill dst mpc)).
+ {
+ replace (Some (kill dst mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply kill_ok.
+ assumption.
+
+- (* load notrap1 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = None).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap1; eauto.
+ rewrite subst_args_ok; assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply get_rb_sem_ge with (rb2 := Some (kill dst mpc)).
+ {
+ replace (Some (kill dst mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply kill_ok.
+ assumption.
+
+- (* load notrap2 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap2; eauto.
+ rewrite subst_args_ok; assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply get_rb_sem_ge with (rb2 := Some (kill dst mpc)).
+ {
+ replace (Some (kill dst mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply kill_ok.
+ assumption.
+
+- (* store *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Istore; eauto.
+ rewrite subst_args_ok; assumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply get_rb_sem_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ unfold get_rb_sem in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+
+(* call *)
+- econstructor; split.
+ eapply exec_Icall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ rewrite subst_args_ok by assumption.
+ constructor. constructor; auto. constructor.
+
+ {
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+ apply get_rb_sem_ge with (rb2 := Some (kill res mpc)).
+ {
+ replace (Some (kill res mpc)) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply kill_weaken.
+ assumption.
+ }
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ assert (RB.ge (map # pc') (apply_instr' (fn_code f) pc (map # pc))) as GE.
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr' in GE.
+ unfold fmap_sem in *.
+ destruct (map # pc) as [mpc |] in *; try contradiction.
+ rewrite H in GE.
+ simpl in GE.
+ unfold is_killed_in_fmap, is_killed_in_map.
+ unfold RB.ge in GE.
+ destruct (map # pc') as [mpc'|] eqn:MPC' in *; trivial.
+ eauto.
+
+(* tailcall *)
+- econstructor; split.
+ eapply exec_Itailcall with (fd := transf_fundef fd); eauto.
+ eapply find_function_translated; eauto.
+ apply sig_preserved.
+ rewrite subst_args_ok by assumption.
+ constructor. auto.
+
+(* builtin *)
+- econstructor; split.
+ eapply exec_Ibuiltin; eauto.
+ eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ destruct (map # pc) as [mpc |] eqn:MPC in *; try contradiction.
+
+ apply get_rb_sem_ge with (rb2 := Some RELATION.top).
+ {
+ replace (Some RELATION.top) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl. tauto.
+ }
+ unfold apply_instr'.
+ rewrite H.
+ rewrite MPC.
+ reflexivity.
+ }
+ apply top_ok.
+
+(* cond *)
+- econstructor; split.
+ eapply exec_Icond; eauto.
+ rewrite subst_args_ok; eassumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply get_rb_sem_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl.
+ destruct b; tauto.
+ }
+ unfold apply_instr'.
+ unfold get_rb_sem in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+
+(* jumptbl *)
+- econstructor; split.
+ eapply exec_Ijumptable; eauto.
+ rewrite subst_arg_ok; eassumption.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply get_rb_sem_ge with (rb2 := map # pc); trivial.
+ replace (map # pc) with (apply_instr' (fn_code f) pc (map # pc)).
+ {
+ eapply DS.fixpoint_solution with (code := fn_code f) (successors := successors_instr); try eassumption.
+ 2: apply apply_instr'_bot.
+ simpl.
+ apply list_nth_z_in with (n := Int.unsigned n).
+ assumption.
+ }
+ unfold apply_instr'.
+ unfold get_rb_sem in *.
+ destruct (map # pc) in *; try contradiction.
+ rewrite H.
+ reflexivity.
+
+(* return *)
+- destruct or as [arg | ].
+ {
+ econstructor; split.
+ eapply exec_Ireturn; eauto.
+ unfold regmap_optget.
+ rewrite subst_arg_ok by eassumption.
+ constructor; auto.
+ }
+ econstructor; split.
+ eapply exec_Ireturn; eauto.
+ constructor; auto.
+
+
+(* internal function *)
+- simpl. econstructor; split.
+ eapply exec_function_internal; eauto.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ apply get_rb_sem_ge with (rb2 := Some RELATION.top).
+ {
+ eapply DS.fixpoint_entry with (code := fn_code f) (successors := successors_instr); try eassumption.
+ }
+ apply top_ok.
+
+(* external function *)
+- econstructor; split.
+ eapply exec_function_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ constructor; auto.
+
+(* return *)
+- inv STACKS. inv H1.
+ econstructor; split.
+ eapply exec_return; eauto.
+ constructor; auto.
+
+ simpl in *.
+ unfold fmap_sem in *.
+ destruct (forward_map _) as [map |] eqn:MAP in *; trivial.
+ unfold is_killed_in_fmap in H8.
+ unfold is_killed_in_map in H8.
+ destruct (map # pc) as [mpc |] in *; try contradiction.
+ destruct H8 as [rel' RGE].
+ eapply get_rb_killed; eauto.
+Qed.
+
+
+Lemma transf_initial_states:
+ forall S1, RTL.initial_state prog S1 ->
+ exists S2, RTL.initial_state tprog S2 /\ match_states S1 S2.
+Proof.
+ intros. inv H. econstructor; split.
+ econstructor.
+ eapply (Genv.init_mem_transf TRANSL); eauto.
+ rewrite symbols_preserved. rewrite (match_program_main TRANSL). eauto.
+ eapply function_ptr_translated; eauto.
+ rewrite <- H3; apply sig_preserved.
+ constructor. constructor.
+Qed.
+
+Lemma transf_final_states:
+ forall S1 S2 r, match_states S1 S2 -> RTL.final_state S1 r -> RTL.final_state S2 r.
+Proof.
+ intros. inv H0. inv H. inv STACKS. constructor.
+Qed.
+
+Theorem transf_program_correct:
+ forward_simulation (RTL.semantics prog) (RTL.semantics tprog).
+Proof.
+ eapply forward_simulation_step.
+ apply senv_preserved.
+ eexact transf_initial_states.
+ eexact transf_final_states.
+ exact step_simulation.
+Qed.
+
+End PRESERVATION.
diff --git a/backend/IRC.ml b/backend/IRC.ml
index 67da47da..785b0a2d 100644
--- a/backend/IRC.ml
+++ b/backend/IRC.ml
@@ -238,7 +238,6 @@ type graph = {
according to their types. A variable can be forced into class 2
by giving it a negative spill cost. *)
-
let class_of_reg r =
if Conventions1.is_float_reg r then 1 else 0
diff --git a/backend/Inlining.v b/backend/Inlining.v
index f7ee4166..8c7e1898 100644
--- a/backend/Inlining.v
+++ b/backend/Inlining.v
@@ -364,9 +364,9 @@ Definition expand_instr (ctx: context) (pc: node) (i: instruction): mon unit :=
| Iop op args res s =>
set_instr (spc ctx pc)
(Iop (sop ctx op) (sregs ctx args) (sreg ctx res) (spc ctx s))
- | Iload chunk addr args dst s =>
+ | Iload trap chunk addr args dst s =>
set_instr (spc ctx pc)
- (Iload chunk (saddr ctx addr) (sregs ctx args) (sreg ctx dst) (spc ctx s))
+ (Iload trap chunk (saddr ctx addr) (sregs ctx args) (sreg ctx dst) (spc ctx s))
| Istore chunk addr args src s =>
set_instr (spc ctx pc)
(Istore chunk (saddr ctx addr) (sregs ctx args) (sreg ctx src) (spc ctx s))
@@ -397,9 +397,9 @@ Definition expand_instr (ctx: context) (pc: node) (i: instruction): mon unit :=
| Ibuiltin ef args res s =>
set_instr (spc ctx pc)
(Ibuiltin ef (map (sbuiltinarg ctx) args) (sbuiltinres ctx res) (spc ctx s))
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 info =>
set_instr (spc ctx pc)
- (Icond cond (sregs ctx args) (spc ctx s1) (spc ctx s2))
+ (Icond cond (sregs ctx args) (spc ctx s1) (spc ctx s2) info)
| Ijumptable r tbl =>
set_instr (spc ctx pc)
(Ijumptable (sreg ctx r) (List.map (spc ctx) tbl))
diff --git a/backend/Inliningaux.ml b/backend/Inliningaux.ml
index 842e0c93..cf308962 100644
--- a/backend/Inliningaux.ml
+++ b/backend/Inliningaux.ml
@@ -16,8 +16,9 @@ open FSetAVL
open Maps
open Op
open Ordered
-open !RTL
-
+open! RTL
+open Camlcoq
+
module PSet = Make(OrderedPositive)
type inlining_info = {
@@ -57,7 +58,7 @@ let used_in_globvar io gv =
let fun_inline_analysis id io fn =
let inst io nid = function
| Iop (op, args, dest, succ) -> used_id io (globals_operation op)
- | Iload (chunk, addr, args, dest, succ)
+ | Iload (_, chunk, addr, args, dest, succ)
| Istore (chunk, addr, args, dest, succ) -> used_id io (globals_addressing addr)
| Ibuiltin (ef, args, dest, succ) -> used_id io (globals_of_builtin_args args)
| Icall (_, Coq_inr cid, _, _, _)
@@ -83,13 +84,15 @@ let static_called_once id io =
else
false
-(* To be considered: heuristics based on size of function? *)
+(* D. Monniaux: attempt at heuristic based on size *)
+let small_enough (f : coq_function) =
+ P.to_int (RTL.max_pc_function f) <= !Clflags.option_inline_auto_threshold
let should_inline (io: inlining_info) (id: ident) (f: coq_function) =
if !Clflags.option_finline then begin
match C2C.atom_inline id with
| C2C.Inline -> true
| C2C.Noinline -> false
- | C2C.No_specifier -> static_called_once id io
+ | C2C.No_specifier -> static_called_once id io || small_enough f
end else
false
diff --git a/backend/Inliningproof.v b/backend/Inliningproof.v
index cc84b1cc..c4efaf18 100644
--- a/backend/Inliningproof.v
+++ b/backend/Inliningproof.v
@@ -929,6 +929,15 @@ Proof.
intros. inv H. eauto.
Qed.
+Lemma eval_addressing_none:
+ forall sp' ctx addr rs,
+ eval_addressing ge (Vptr sp' (Ptrofs.repr (dstk ctx))) addr rs = None ->
+ eval_addressing ge (Vptr sp' Ptrofs.zero) (saddr ctx addr) rs = None.
+Proof.
+ intros until rs; intro Heval.
+ destruct addr; destruct rs as [| r0 rs1]; simpl in *; trivial; discriminate.
+Qed.
+
Theorem step_simulation:
forall S1 t S2,
step ge S1 t S2 ->
@@ -976,6 +985,51 @@ Proof.
apply match_stacks_inside_set_reg; auto.
apply agree_set_reg; auto.
+- (* load notrap1 *)
+ exploit tr_funbody_inv; eauto. intros TR; inv TR.
+ left; econstructor; split.
+ eapply plus_one. eapply exec_Iload_notrap1. eassumption.
+ rewrite eval_addressing_preserved with (ge1:=ge) (ge2:=tge).
+ exploit eval_addressing_inj_none.
+ 4: eassumption.
+ intros. eapply symbol_address_inject.
+ eapply match_stacks_inside_globals; eauto.
+ eauto.
+ instantiate (1 := rs'##(sregs ctx args)). eapply agree_val_regs; eauto.
+ rewrite Ptrofs.add_zero_l.
+ apply eval_addressing_none.
+ exact symbols_preserved.
+ econstructor; eauto.
+ apply match_stacks_inside_set_reg; auto.
+ apply agree_set_reg; auto.
+
+- (* load notrap2 *)
+ exploit tr_funbody_inv; eauto. intros TR; inv TR.
+
+ exploit eval_addressing_inject.
+ eapply match_stacks_inside_globals; eauto.
+ eexact SP.
+ instantiate (2 := rs##args). instantiate (1 := rs'##(sregs ctx args)). eapply agree_val_regs; eauto.
+ eauto.
+ fold (saddr ctx addr). intros [a' [P Q]].
+
+ destruct (Mem.loadv chunk m' a') eqn:Hload'.
+ + left; econstructor; split.
+ eapply plus_one.
+ eapply exec_Iload; eauto.
+ try (rewrite <- P; apply eval_addressing_preserved; exact symbols_preserved).
+ econstructor; eauto.
+ apply match_stacks_inside_set_reg; auto.
+ apply agree_set_reg; auto.
+
+ + left; econstructor; split.
+ eapply plus_one.
+ eapply exec_Iload_notrap2; eauto.
+ try (rewrite <- P; apply eval_addressing_preserved; exact symbols_preserved).
+ econstructor; eauto.
+ apply match_stacks_inside_set_reg; auto.
+ apply agree_set_reg; auto.
+
- (* store *)
exploit tr_funbody_inv; eauto. intros TR; inv TR.
exploit eval_addressing_inject.
diff --git a/backend/Inliningspec.v b/backend/Inliningspec.v
index c345c942..eba026ec 100644
--- a/backend/Inliningspec.v
+++ b/backend/Inliningspec.v
@@ -270,10 +270,10 @@ Inductive tr_instr: context -> node -> instruction -> code -> Prop :=
Ple res ctx.(mreg) ->
c!(spc ctx pc) = Some (Iop (sop ctx op) (sregs ctx args) (sreg ctx res) (spc ctx s)) ->
tr_instr ctx pc (Iop op args res s) c
- | tr_load: forall ctx pc c chunk addr args res s,
+ | tr_load: forall ctx pc c trap chunk addr args res s,
Ple res ctx.(mreg) ->
- c!(spc ctx pc) = Some (Iload chunk (saddr ctx addr) (sregs ctx args) (sreg ctx res) (spc ctx s)) ->
- tr_instr ctx pc (Iload chunk addr args res s) c
+ c!(spc ctx pc) = Some (Iload trap chunk (saddr ctx addr) (sregs ctx args) (sreg ctx res) (spc ctx s)) ->
+ tr_instr ctx pc (Iload trap chunk addr args res s) c
| tr_store: forall ctx pc c chunk addr args src s,
c!(spc ctx pc) = Some (Istore chunk (saddr ctx addr) (sregs ctx args) (sreg ctx src) (spc ctx s)) ->
tr_instr ctx pc (Istore chunk addr args src s) c
@@ -312,9 +312,9 @@ Inductive tr_instr: context -> node -> instruction -> code -> Prop :=
match res with BR r => Ple r ctx.(mreg) | _ => True end ->
c!(spc ctx pc) = Some (Ibuiltin ef (map (sbuiltinarg ctx) args) (sbuiltinres ctx res) (spc ctx s)) ->
tr_instr ctx pc (Ibuiltin ef args res s) c
- | tr_cond: forall ctx pc cond args s1 s2 c,
- c!(spc ctx pc) = Some (Icond cond (sregs ctx args) (spc ctx s1) (spc ctx s2)) ->
- tr_instr ctx pc (Icond cond args s1 s2) c
+ | tr_cond: forall ctx pc cond args s1 s2 c i,
+ c!(spc ctx pc) = Some (Icond cond (sregs ctx args) (spc ctx s1) (spc ctx s2) i) ->
+ tr_instr ctx pc (Icond cond args s1 s2 i) c
| tr_jumptable: forall ctx pc r tbl c,
c!(spc ctx pc) = Some (Ijumptable (sreg ctx r) (List.map (spc ctx) tbl)) ->
tr_instr ctx pc (Ijumptable r tbl) c
diff --git a/backend/LTL.v b/backend/LTL.v
index 5e7eec8c..3edd60a2 100644
--- a/backend/LTL.v
+++ b/backend/LTL.v
@@ -29,7 +29,7 @@ Definition node := positive.
Inductive instruction: Type :=
| Lop (op: operation) (args: list mreg) (res: mreg)
- | Lload (chunk: memory_chunk) (addr: addressing) (args: list mreg) (dst: mreg)
+ | Lload (trap : trapping_mode) (chunk: memory_chunk) (addr: addressing) (args: list mreg) (dst: mreg)
| Lgetstack (sl: slot) (ofs: Z) (ty: typ) (dst: mreg)
| Lsetstack (src: mreg) (sl: slot) (ofs: Z) (ty: typ)
| Lstore (chunk: memory_chunk) (addr: addressing) (args: list mreg) (src: mreg)
@@ -37,7 +37,7 @@ Inductive instruction: Type :=
| Ltailcall (sg: signature) (ros: mreg + ident)
| Lbuiltin (ef: external_function) (args: list (builtin_arg loc)) (res: builtin_res mreg)
| Lbranch (s: node)
- | Lcond (cond: condition) (args: list mreg) (s1 s2: node)
+ | Lcond (cond: condition) (args: list mreg) (s1 s2: node) (info: option bool)
| Ljumptable (arg: mreg) (tbl: list node)
| Lreturn.
@@ -209,11 +209,24 @@ Inductive step: state -> trace -> state -> Prop :=
rs' = Locmap.set (R res) v (undef_regs (destroyed_by_op op) rs) ->
step (Block s f sp (Lop op args res :: bb) rs m)
E0 (Block s f sp bb rs' m)
- | exec_Lload: forall s f sp chunk addr args dst bb rs m a v rs',
+ | exec_Lload: forall s f sp trap chunk addr args dst bb rs m a v rs',
eval_addressing ge sp addr (reglist rs args) = Some a ->
Mem.loadv chunk m a = Some v ->
rs' = Locmap.set (R dst) v (undef_regs (destroyed_by_load chunk addr) rs) ->
- step (Block s f sp (Lload chunk addr args dst :: bb) rs m)
+ step (Block s f sp (Lload trap chunk addr args dst :: bb) rs m)
+ E0 (Block s f sp bb rs' m)
+ | exec_Lload_notrap1: forall s f sp chunk addr args dst bb rs m rs',
+ eval_addressing ge sp addr (reglist rs args) = None ->
+ rs' = Locmap.set (R dst) (default_notrap_load_value chunk)
+ (undef_regs (destroyed_by_load chunk addr) rs) ->
+ step (Block s f sp (Lload NOTRAP chunk addr args dst :: bb) rs m)
+ E0 (Block s f sp bb rs' m)
+ | exec_Lload_notrap2: forall s f sp chunk addr args dst bb rs m a rs',
+ eval_addressing ge sp addr (reglist rs args) = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs' = Locmap.set (R dst) (default_notrap_load_value chunk)
+ (undef_regs (destroyed_by_load chunk addr) rs) ->
+ step (Block s f sp (Lload NOTRAP chunk addr args dst :: bb) rs m)
E0 (Block s f sp bb rs' m)
| exec_Lgetstack: forall s f sp sl ofs ty dst bb rs m rs',
rs' = Locmap.set (R dst) (rs (S sl ofs ty)) (undef_regs (destroyed_by_getstack sl) rs) ->
@@ -250,11 +263,11 @@ Inductive step: state -> trace -> state -> Prop :=
| exec_Lbranch: forall s f sp pc bb rs m,
step (Block s f sp (Lbranch pc :: bb) rs m)
E0 (State s f sp pc rs m)
- | exec_Lcond: forall s f sp cond args pc1 pc2 bb rs b pc rs' m,
+ | exec_Lcond: forall s f sp cond args pc1 pc2 bb rs b pc rs' m i,
eval_condition cond (reglist rs args) m = Some b ->
pc = (if b then pc1 else pc2) ->
rs' = undef_regs (destroyed_by_cond cond) rs ->
- step (Block s f sp (Lcond cond args pc1 pc2 :: bb) rs m)
+ step (Block s f sp (Lcond cond args pc1 pc2 i :: bb) rs m)
E0 (State s f sp pc rs' m)
| exec_Ljumptable: forall s f sp arg tbl bb rs m n pc rs',
rs (R arg) = Vint n ->
@@ -315,7 +328,7 @@ Fixpoint successors_block (b: bblock) : list node :=
| nil => nil (**r should never happen *)
| Ltailcall _ _ :: _ => nil
| Lbranch s :: _ => s :: nil
- | Lcond _ _ s1 s2 :: _ => s1 :: s2 :: nil
+ | Lcond _ _ s1 s2 _ :: _ => s1 :: s2 :: nil
| Ljumptable _ tbl :: _ => tbl
| Lreturn :: _ => nil
| instr :: b' => successors_block b'
diff --git a/backend/Linear.v b/backend/Linear.v
index 447c6ba6..1443f795 100644
--- a/backend/Linear.v
+++ b/backend/Linear.v
@@ -28,7 +28,7 @@ Inductive instruction: Type :=
| Lgetstack: slot -> Z -> typ -> mreg -> instruction
| Lsetstack: mreg -> slot -> Z -> typ -> instruction
| Lop: operation -> list mreg -> mreg -> instruction
- | Lload: memory_chunk -> addressing -> list mreg -> mreg -> instruction
+ | Lload: trapping_mode -> memory_chunk -> addressing -> list mreg -> mreg -> instruction
| Lstore: memory_chunk -> addressing -> list mreg -> mreg -> instruction
| Lcall: signature -> mreg + ident -> instruction
| Ltailcall: signature -> mreg + ident -> instruction
@@ -160,11 +160,28 @@ Inductive step: state -> trace -> state -> Prop :=
step (State s f sp (Lop op args res :: b) rs m)
E0 (State s f sp b rs' m)
| exec_Lload:
- forall s f sp chunk addr args dst b rs m a v rs',
+ forall s f sp trap chunk addr args dst b rs m a v rs',
eval_addressing ge sp addr (reglist rs args) = Some a ->
Mem.loadv chunk m a = Some v ->
rs' = Locmap.set (R dst) v (undef_regs (destroyed_by_load chunk addr) rs) ->
- step (State s f sp (Lload chunk addr args dst :: b) rs m)
+ step (State s f sp (Lload trap chunk addr args dst :: b) rs m)
+ E0 (State s f sp b rs' m)
+ | exec_Lload_notrap1:
+ forall s f sp chunk addr args dst b rs m rs',
+ eval_addressing ge sp addr (reglist rs args) = None ->
+ rs' = Locmap.set (R dst)
+ (default_notrap_load_value chunk)
+ (undef_regs (destroyed_by_load chunk addr) rs) ->
+ step (State s f sp (Lload NOTRAP chunk addr args dst :: b) rs m)
+ E0 (State s f sp b rs' m)
+ | exec_Lload_notrap2:
+ forall s f sp chunk addr args dst b rs m a rs',
+ eval_addressing ge sp addr (reglist rs args) = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs' = Locmap.set (R dst)
+ (default_notrap_load_value chunk)
+ (undef_regs (destroyed_by_load chunk addr) rs) ->
+ step (State s f sp (Lload NOTRAP chunk addr args dst :: b) rs m)
E0 (State s f sp b rs' m)
| exec_Lstore:
forall s f sp chunk addr args src b rs m m' a rs',
diff --git a/backend/Linearize.v b/backend/Linearize.v
index 2cfa4d3c..66b36428 100644
--- a/backend/Linearize.v
+++ b/backend/Linearize.v
@@ -163,8 +163,8 @@ Fixpoint linearize_block (b: LTL.bblock) (k: code) : code :=
| nil => k
| LTL.Lop op args res :: b' =>
Lop op args res :: linearize_block b' k
- | LTL.Lload chunk addr args dst :: b' =>
- Lload chunk addr args dst :: linearize_block b' k
+ | LTL.Lload trap chunk addr args dst :: b' =>
+ Lload trap chunk addr args dst :: linearize_block b' k
| LTL.Lgetstack sl ofs ty dst :: b' =>
Lgetstack sl ofs ty dst :: linearize_block b' k
| LTL.Lsetstack src sl ofs ty :: b' =>
@@ -179,7 +179,7 @@ Fixpoint linearize_block (b: LTL.bblock) (k: code) : code :=
Lbuiltin ef args res :: linearize_block b' k
| LTL.Lbranch s :: b' =>
add_branch s k
- | LTL.Lcond cond args s1 s2 :: b' =>
+ | LTL.Lcond cond args s1 s2 _ :: b' =>
if starts_with s1 k then
Lcond (negate_condition cond) args s2 :: add_branch s1 k
else
diff --git a/backend/Linearizeaux.ml b/backend/Linearizeaux.ml
index 902724e0..bfa056ca 100644
--- a/backend/Linearizeaux.ml
+++ b/backend/Linearizeaux.ml
@@ -1,4 +1,4 @@
-(* *********************************************************************)
+
(* *)
(* The Compcert verified compiler *)
(* *)
@@ -12,7 +12,6 @@
open LTL
open Maps
-open Camlcoq
(* Trivial enumeration, in decreasing order of PC *)
@@ -29,6 +28,8 @@ let enumerate_aux f reach =
(* More clever enumeration that flattens basic blocks *)
+open Camlcoq
+
module IntSet = Set.Make(struct type t = int let compare = compare end)
(* Determine join points: reachable nodes that have > 1 predecessor *)
@@ -80,7 +81,7 @@ let basic_blocks f joins =
| [] -> assert false
| Lbranch s :: _ -> next_in_block blk minpc s
| Ltailcall (sig0, ros) :: _ -> end_block blk minpc
- | Lcond (cond, args, ifso, ifnot) :: _ ->
+ | Lcond (cond, args, ifso, ifnot, _) :: _ ->
end_block blk minpc; start_block ifso; start_block ifnot
| Ljumptable(arg, tbl) :: _ ->
end_block blk minpc; List.iter start_block tbl
@@ -110,5 +111,405 @@ let flatten_blocks blks =
(* Build the enumeration *)
-let enumerate_aux f reach =
+let enumerate_aux_flat f reach =
flatten_blocks (basic_blocks f (join_points f))
+
+(**
+ * Enumeration based on traces as identified by Duplicate.v
+ *
+ * The Duplicate phase heuristically identifies the most frequented paths. Each
+ * Icond is modified so that the preferred condition is a fallthrough (ifnot)
+ * rather than a branch (ifso).
+ *
+ * The enumeration below takes advantage of this - preferring to layout nodes
+ * following the fallthroughs of the Lcond branches.
+ *
+ * It is slightly adapted from the work of Petris and Hansen 90 on intraprocedural
+ * code positioning - only we do it on a broader grain, since we don't have the exact
+ * frequencies (we only know which branch is the preferred one)
+ *)
+
+let get_some = function
+| None -> failwith "Did not get some"
+| Some thing -> thing
+
+exception EmptyList
+
+let rec last_element = function
+ | [] -> raise EmptyList
+ | e :: [] -> e
+ | e' :: e :: l -> last_element (e::l)
+
+let print_plist l =
+ let rec f = function
+ | [] -> ()
+ | n :: l -> Printf.printf "%d, " (P.to_int n); f l
+ in begin
+ Printf.printf "[";
+ f l;
+ Printf.printf "]"
+ end
+
+(* adapted from the above join_points function, but with PTree *)
+let get_join_points code entry =
+ let reached = ref (PTree.map (fun n i -> false) code) in
+ let reached_twice = ref (PTree.map (fun n i -> false) code) in
+ let rec traverse pc =
+ if get_some @@ PTree.get pc !reached then begin
+ if not (get_some @@ PTree.get pc !reached_twice) then
+ reached_twice := PTree.set pc true !reached_twice
+ end else begin
+ reached := PTree.set pc true !reached;
+ traverse_succs (successors_block @@ get_some @@ PTree.get pc code)
+ end
+ and traverse_succs = function
+ | [] -> ()
+ | [pc] -> traverse pc
+ | pc :: l -> traverse pc; traverse_succs l
+ in traverse entry; !reached_twice
+
+let forward_sequences code entry =
+ let visited = ref (PTree.map (fun n i -> false) code) in
+ let join_points = get_join_points code entry in
+ (* returns the list of traversed nodes, and a list of nodes to start traversing next *)
+ let rec traverse_fallthrough code node =
+ (* Printf.printf "Traversing %d..\n" (P.to_int node); *)
+ if not (get_some @@ PTree.get node !visited) then begin
+ visited := PTree.set node true !visited;
+ match PTree.get node code with
+ | None -> failwith "No such node"
+ | Some bb ->
+ let ln, rem = match (last_element bb) with
+ | Lop _ | Lload _ | Lgetstack _ | Lsetstack _ | Lstore _ | Lcall _
+ | Lbuiltin _ -> assert false
+ | Ltailcall _ | Lreturn -> begin (* Printf.printf "STOP tailcall/return\n"; *) ([], []) end
+ | Lbranch n ->
+ if get_some @@ PTree.get n join_points then ([], [n])
+ else let ln, rem = traverse_fallthrough code n in (ln, rem)
+ | Lcond (_, _, ifso, ifnot, info) -> (match info with
+ | None -> begin (* Printf.printf "STOP Lcond None\n"; *) ([], [ifso; ifnot]) end
+ | Some false ->
+ if get_some @@ PTree.get ifnot join_points then ([], [ifso; ifnot])
+ else let ln, rem = traverse_fallthrough code ifnot in (ln, [ifso] @ rem)
+ | Some true ->
+ let errstr = Printf.sprintf ("Inconsistency detected in node %d: ifnot is not the preferred branch") (P.to_int node) in
+ failwith errstr)
+ | Ljumptable(_, ln) -> begin (* Printf.printf "STOP Ljumptable\n"; *) ([], ln) end
+ in ([node] @ ln, rem)
+ end
+ else ([], [])
+ in let rec f code = function
+ | [] -> []
+ | node :: ln ->
+ let fs, rem_from_node = traverse_fallthrough code node
+ in [fs] @ ((f code rem_from_node) @ (f code ln))
+ in (f code [entry])
+
+(** Unused code
+module PInt = struct
+ type t = P.t
+ let compare x y = compare (P.to_int x) (P.to_int y)
+end
+
+module PSet = Set.Make(PInt)
+
+module LPInt = struct
+ type t = P.t list
+ let rec compare x y =
+ match x with
+ | [] -> ( match y with
+ | [] -> 0
+ | _ -> 1 )
+ | e :: l -> match y with
+ | [] -> -1
+ | e' :: l' ->
+ let e_cmp = PInt.compare e e' in
+ if e_cmp == 0 then compare l l' else e_cmp
+end
+
+module LPSet = Set.Make(LPInt)
+
+let iter_lpset f s = Seq.iter f (LPSet.to_seq s)
+
+let first_of = function
+ | [] -> None
+ | e :: l -> Some e
+
+let rec last_of = function
+ | [] -> None
+ | e :: l -> (match l with [] -> Some e | e :: l -> last_of l)
+
+let can_be_merged code s s' =
+ let last_s = get_some @@ last_of s in
+ let first_s' = get_some @@ first_of s' in
+ match get_some @@ PTree.get last_s code with
+ | Lop _ | Lload _ | Lgetstack _ | Lsetstack _ | Lstore _ | Lcall _
+ | Lbuiltin _ | Ltailcall _ | Lreturn -> false
+ | Lbranch n -> n == first_s'
+ | Lcond (_, _, ifso, ifnot, info) -> (match info with
+ | None -> false
+ | Some false -> ifnot == first_s'
+ | Some true -> failwith "Inconsistency detected - ifnot is not the preferred branch")
+ | Ljumptable (_, ln) ->
+ match ln with
+ | [] -> false
+ | n :: ln -> n == first_s'
+
+let merge s s' = Some s
+
+let try_merge code (fs: (BinNums.positive list) list) =
+ let seqs = ref (LPSet.of_list fs) in
+ let oldLength = ref (LPSet.cardinal !seqs) in
+ let continue = ref true in
+ let found = ref false in
+ while !continue do
+ begin
+ found := false;
+ iter_lpset (fun s ->
+ if !found then ()
+ else iter_lpset (fun s' ->
+ if (!found || s == s') then ()
+ else if (can_be_merged code s s') then
+ begin
+ seqs := LPSet.remove s !seqs;
+ seqs := LPSet.remove s' !seqs;
+ seqs := LPSet.add (get_some (merge s s')) !seqs;
+ found := true;
+ end
+ else ()
+ ) !seqs
+ ) !seqs;
+ if !oldLength == LPSet.cardinal !seqs then
+ continue := false
+ else
+ oldLength := LPSet.cardinal !seqs
+ end
+ done;
+ !seqs
+*)
+
+(** Code adapted from Duplicateaux.get_loop_headers
+ *
+ * Getting loop branches with a DFS visit :
+ * Each node is either Unvisited, Visited, or Processed
+ * pre-order: node becomes Processed
+ * post-order: node becomes Visited
+ *
+ * If we come accross an edge to a Processed node, it's a loop!
+ *)
+type pos = BinNums.positive
+
+module PP = struct
+ type t = pos * pos
+ let compare a b =
+ let ax, ay = a in
+ let bx, by = b in
+ let dx = compare ax bx in
+ if (dx == 0) then compare ay by
+ else dx
+end
+
+module PPMap = Map.Make(PP)
+
+type vstate = Unvisited | Processed | Visited
+
+let get_loop_edges code entry =
+ let visited = ref (PTree.map (fun n i -> Unvisited) code) in
+ let is_loop_edge = ref PPMap.empty
+ in let rec dfs_visit code from = function
+ | [] -> ()
+ | node :: ln ->
+ match (get_some @@ PTree.get node !visited) with
+ | Visited -> ()
+ | Processed -> begin
+ let from_node = get_some from in
+ is_loop_edge := PPMap.add (from_node, node) true !is_loop_edge;
+ visited := PTree.set node Visited !visited
+ end
+ | Unvisited -> begin
+ visited := PTree.set node Processed !visited;
+ let bb = get_some @@ PTree.get node code in
+ let next_visits = (match (last_element bb) with
+ | Lop _ | Lload _ | Lgetstack _ | Lsetstack _ | Lstore _ | Lcall _
+ | Lbuiltin _ -> assert false
+ | Ltailcall _ | Lreturn -> []
+ | Lbranch n -> [n]
+ | Lcond (_, _, ifso, ifnot, _) -> [ifso; ifnot]
+ | Ljumptable(_, ln) -> ln
+ ) in dfs_visit code (Some node) next_visits;
+ visited := PTree.set node Visited !visited;
+ dfs_visit code from ln
+ end
+ in begin
+ dfs_visit code None [entry];
+ !is_loop_edge
+ end
+
+let ppmap_is_true pp ppmap = PPMap.mem pp ppmap && PPMap.find pp ppmap
+
+module Int = struct
+ type t = int
+ let compare x y = compare x y
+end
+
+module ISet = Set.Make(Int)
+
+let print_iset s = begin
+ Printf.printf "{";
+ ISet.iter (fun e -> Printf.printf "%d, " e) s;
+ Printf.printf "}"
+end
+
+let print_depmap dm = begin
+ Printf.printf "[|";
+ Array.iter (fun s -> print_iset s; Printf.printf ", ") dm;
+ Printf.printf "|]\n"
+end
+
+let construct_depmap code entry fs =
+ let is_loop_edge = get_loop_edges code entry in
+ let visited = ref (PTree.map (fun n i -> false) code) in
+ let depmap = Array.map (fun e -> ISet.empty) fs in
+ let find_index_of_node n =
+ let index = ref 0 in
+ begin
+ Array.iteri (fun i s ->
+ match List.find_opt (fun e -> e == n) s with
+ | Some _ -> index := i
+ | None -> ()
+ ) fs;
+ !index
+ end
+ in let check_and_update_depmap from target =
+ (* Printf.printf "From %d to %d\n" (P.to_int from) (P.to_int target); *)
+ if not (ppmap_is_true (from, target) is_loop_edge) then
+ let in_index_fs = find_index_of_node from in
+ let out_index_fs = find_index_of_node target in
+ if out_index_fs != in_index_fs then
+ depmap.(out_index_fs) <- ISet.add in_index_fs depmap.(out_index_fs)
+ else ()
+ else ()
+ in let rec dfs_visit code = function
+ | [] -> ()
+ | node :: ln ->
+ begin
+ match (get_some @@ PTree.get node !visited) with
+ | true -> ()
+ | false -> begin
+ visited := PTree.set node true !visited;
+ let bb = get_some @@ PTree.get node code in
+ let next_visits =
+ match (last_element bb) with
+ | Ltailcall _ | Lreturn -> []
+ | Lbranch n -> (check_and_update_depmap node n; [n])
+ | Lcond (_, _, ifso, ifnot, _) -> begin
+ check_and_update_depmap node ifso;
+ check_and_update_depmap node ifnot;
+ [ifso; ifnot]
+ end
+ | Ljumptable(_, ln) -> begin
+ List.iter (fun n -> check_and_update_depmap node n) ln;
+ ln
+ end
+ (* end of bblocks should not be another value than one of the above *)
+ | _ -> failwith "last_element gave an invalid output"
+ in dfs_visit code next_visits
+ end;
+ dfs_visit code ln
+ end
+ in begin
+ dfs_visit code [entry];
+ depmap
+ end
+
+let print_sequence s =
+ Printf.printf "[";
+ List.iter (fun n -> Printf.printf "%d, " (P.to_int n)) s;
+ Printf.printf "]\n"
+
+let print_ssequence ofs =
+ Printf.printf "[";
+ List.iter (fun s -> print_sequence s) ofs;
+ Printf.printf "]\n"
+
+let order_sequences code entry fs =
+ let fs_a = Array.of_list fs in
+ let depmap = construct_depmap code entry fs_a in
+ let fs_evaluated = Array.map (fun e -> false) fs_a in
+ let ordered_fs = ref [] in
+ let evaluate s_id =
+ begin
+ assert (not fs_evaluated.(s_id));
+ ordered_fs := fs_a.(s_id) :: !ordered_fs;
+ fs_evaluated.(s_id) <- true;
+ (* Printf.printf "++++++\n";
+ Printf.printf "Scheduling %d\n" s_id;
+ Printf.printf "Initial depmap: "; print_depmap depmap; *)
+ Array.iteri (fun i deps ->
+ depmap.(i) <- ISet.remove s_id deps
+ ) depmap;
+ (* Printf.printf "Final depmap: "; print_depmap depmap; *)
+ end
+ in let choose_best_of candidates =
+ let current_best_id = ref None in
+ let current_best_score = ref None in
+ begin
+ List.iter (fun id ->
+ match !current_best_id with
+ | None -> begin
+ current_best_id := Some id;
+ match fs_a.(id) with
+ | [] -> current_best_score := None
+ | n::l -> current_best_score := Some (P.to_int n)
+ end
+ | Some b -> begin
+ match fs_a.(id) with
+ | [] -> ()
+ | n::l -> let nscore = P.to_int n in
+ match !current_best_score with
+ | None -> (current_best_id := Some id; current_best_score := Some nscore)
+ | Some bs -> if nscore > bs then (current_best_id := Some id; current_best_score := Some nscore)
+ end
+ ) candidates;
+ !current_best_id
+ end
+ in let select_next () =
+ let candidates = ref [] in
+ begin
+ Array.iteri (fun i deps ->
+ begin
+ (* Printf.printf "Deps of %d: " i; print_iset deps; Printf.printf "\n"; *)
+ (* FIXME - if we keep it that way (no dependency check), remove all the unneeded stuff *)
+ if ((* deps == ISet.empty && *) not fs_evaluated.(i)) then
+ candidates := i :: !candidates
+ end
+ ) depmap;
+ if not (List.length !candidates > 0) then begin
+ Array.iteri (fun i deps ->
+ if (not fs_evaluated.(i)) then candidates := i :: !candidates
+ ) depmap;
+ end;
+ get_some (choose_best_of !candidates)
+ end
+ in begin
+ Printf.printf "-------------------------------\n";
+ Printf.printf "depmap: "; print_depmap depmap;
+ Printf.printf "forward sequences identified: "; print_ssequence fs;
+ while List.length !ordered_fs != List.length fs do
+ let next_id = select_next () in
+ evaluate next_id
+ done;
+ Printf.printf "forward sequences ordered: "; print_ssequence (List.rev (!ordered_fs));
+ List.rev (!ordered_fs)
+ end
+
+let enumerate_aux_trace f reach =
+ let code = f.fn_code in
+ let entry = f.fn_entrypoint in
+ let fs = forward_sequences code entry in
+ let ofs = order_sequences code entry fs in
+ List.flatten ofs
+
+let enumerate_aux f reach =
+ if !Clflags.option_ftracelinearize then enumerate_aux_trace f reach
+ else enumerate_aux_flat f reach
diff --git a/backend/Linearizeproof.v b/backend/Linearizeproof.v
index 10a3d8b2..18dc52a5 100644
--- a/backend/Linearizeproof.v
+++ b/backend/Linearizeproof.v
@@ -585,45 +585,61 @@ Proof.
intros; eapply reachable_successors; eauto.
eapply is_tail_lin_block; eauto. eapply is_tail_find_label; eauto.
- (* Lop *)
+- (* Lop *)
left; econstructor; split. simpl.
apply plus_one. econstructor; eauto.
instantiate (1 := v); rewrite <- H; apply eval_operation_preserved.
exact symbols_preserved.
econstructor; eauto.
- (* Lload *)
+- (* Lload *)
left; econstructor; split. simpl.
- apply plus_one. econstructor.
+ apply plus_one. eapply exec_Lload.
instantiate (1 := a). rewrite <- H; apply eval_addressing_preserved.
exact symbols_preserved. eauto. eauto.
econstructor; eauto.
- (* Lgetstack *)
+- (* Lload notrap1 *)
+ left; econstructor; split. simpl.
+ apply plus_one. eapply exec_Lload_notrap1.
+ rewrite <- H.
+ apply eval_addressing_preserved.
+ exact symbols_preserved. eauto.
+ econstructor; eauto.
+
+- (* Lload notrap2 *)
+ left; econstructor; split. simpl.
+ apply plus_one. eapply exec_Lload_notrap2.
+ rewrite <- H.
+ apply eval_addressing_preserved.
+ exact symbols_preserved. eauto. eauto.
+ econstructor; eauto.
+
+- (* Lgetstack *)
left; econstructor; split. simpl.
apply plus_one. econstructor; eauto.
econstructor; eauto.
- (* Lsetstack *)
+- (* Lsetstack *)
left; econstructor; split. simpl.
apply plus_one. econstructor; eauto.
econstructor; eauto.
- (* Lstore *)
+- (* Lstore *)
left; econstructor; split. simpl.
apply plus_one. econstructor.
instantiate (1 := a). rewrite <- H; apply eval_addressing_preserved.
exact symbols_preserved. eauto. eauto.
econstructor; eauto.
- (* Lcall *)
+- (* Lcall *)
exploit find_function_translated; eauto. intros [tfd [A B]].
left; econstructor; split. simpl.
apply plus_one. econstructor; eauto.
symmetry; eapply sig_preserved; eauto.
econstructor; eauto. constructor; auto. econstructor; eauto.
- (* Ltailcall *)
+- (* Ltailcall *)
exploit find_function_translated; eauto. intros [tfd [A B]].
left; econstructor; split. simpl.
apply plus_one. econstructor; eauto.
@@ -633,18 +649,18 @@ Proof.
rewrite (match_parent_locset _ _ STACKS).
econstructor; eauto.
- (* Lbuiltin *)
+- (* Lbuiltin *)
left; econstructor; split. simpl.
apply plus_one. eapply exec_Lbuiltin; eauto.
eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
eapply external_call_symbols_preserved; eauto. apply senv_preserved.
econstructor; eauto.
- (* Lbranch *)
+- (* Lbranch *)
assert ((reachable f)!!pc = true). apply REACH; simpl; auto.
right; split. simpl; omega. split. auto. simpl. econstructor; eauto.
- (* Lcond *)
+- (* Lcond *)
assert (REACH1: (reachable f)!!pc1 = true) by (apply REACH; simpl; auto).
assert (REACH2: (reachable f)!!pc2 = true) by (apply REACH; simpl; auto).
simpl linearize_block.
@@ -670,18 +686,18 @@ Proof.
apply plus_one. eapply exec_Lcond_false. eauto. eauto.
econstructor; eauto.
- (* Ljumptable *)
+- (* Ljumptable *)
assert (REACH': (reachable f)!!pc = true).
apply REACH. simpl. eapply list_nth_z_in; eauto.
right; split. simpl; omega. split. auto. econstructor; eauto.
- (* Lreturn *)
+- (* Lreturn *)
left; econstructor; split.
simpl. apply plus_one. econstructor; eauto.
rewrite (stacksize_preserved _ _ TRF). eauto.
rewrite (match_parent_locset _ _ STACKS). econstructor; eauto.
- (* internal functions *)
+- (* internal functions *)
assert (REACH: (reachable f)!!(LTL.fn_entrypoint f) = true).
apply reachable_entrypoint.
monadInv H7.
@@ -691,13 +707,13 @@ Proof.
generalize EQ; intro EQ'; monadInv EQ'. simpl.
econstructor; eauto. simpl. eapply is_tail_add_branch. constructor.
- (* external function *)
+- (* external function *)
monadInv H8. left; econstructor; split.
apply plus_one. eapply exec_function_external; eauto.
eapply external_call_symbols_preserved; eauto. apply senv_preserved.
econstructor; eauto.
- (* return *)
+- (* return *)
inv H3. inv H1.
left; econstructor; split.
apply plus_one. econstructor.
diff --git a/backend/Lineartyping.v b/backend/Lineartyping.v
index 18594be8..22658fb7 100644
--- a/backend/Lineartyping.v
+++ b/backend/Lineartyping.v
@@ -76,7 +76,7 @@ Definition wt_instr (i: instruction) : bool :=
let (targs, tres) := type_of_operation op in
subtype tres (mreg_type res)
end
- | Lload chunk addr args dst =>
+ | Lload trap chunk addr args dst =>
subtype (type_of_chunk chunk) (mreg_type dst)
| Ltailcall sg ros =>
zeq (size_arguments sg) 0
@@ -326,13 +326,28 @@ Local Opaque mreg_type.
eapply Val.has_subtype; eauto.
change ty_res with (snd (ty_args, ty_res)). rewrite <- TYOP. eapply type_of_operation_sound; eauto.
red; intros; subst op. simpl in ISMOVE.
- destruct args; try discriminate. destruct args; discriminate.
+ destruct args; try discriminate. destruct args; discriminate.
+ (* no longer needed apply wt_undef_regs; auto. *)
- (* load *)
simpl in *; InvBooleans.
econstructor; eauto.
apply wt_setreg. eapply Val.has_subtype; eauto.
destruct a; simpl in H0; try discriminate. eapply Mem.load_type; eauto.
apply wt_undef_regs; auto.
+- (* load notrap1 *)
+ simpl in *; InvBooleans.
+ econstructor; eauto.
+ apply wt_setreg. eapply Val.has_subtype; eauto.
+ unfold default_notrap_load_value.
+ constructor.
+ apply wt_undef_regs; auto.
+- (* load notrap2 *)
+ simpl in *; InvBooleans.
+ econstructor; eauto.
+ apply wt_setreg. eapply Val.has_subtype; eauto.
+ unfold default_notrap_load_value.
+ constructor.
+ apply wt_undef_regs; auto.
- (* store *)
simpl in *; InvBooleans.
econstructor. eauto. eauto. eauto.
diff --git a/backend/Liveness.v b/backend/Liveness.v
index 16533158..9652b363 100644
--- a/backend/Liveness.v
+++ b/backend/Liveness.v
@@ -79,7 +79,7 @@ Definition transfer
reg_list_live args (reg_dead res after)
else
after
- | Iload chunk addr args dst s =>
+ | Iload trap chunk addr args dst s =>
if Regset.mem dst after then
reg_list_live args (reg_dead dst after)
else
@@ -94,7 +94,7 @@ Definition transfer
| Ibuiltin ef args res s =>
reg_list_live (params_of_builtin_args args)
(reg_list_dead (params_of_builtin_res res) after)
- | Icond cond args ifso ifnot =>
+ | Icond cond args ifso ifnot _ =>
reg_list_live args after
| Ijumptable arg tbl =>
reg_live arg after
diff --git a/backend/Mach.v b/backend/Mach.v
index 9fdee9eb..1c6fdb18 100644
--- a/backend/Mach.v
+++ b/backend/Mach.v
@@ -56,7 +56,7 @@ Inductive instruction: Type :=
| Msetstack: mreg -> ptrofs -> typ -> instruction
| Mgetparam: ptrofs -> typ -> mreg -> instruction
| Mop: operation -> list mreg -> mreg -> instruction
- | Mload: memory_chunk -> addressing -> list mreg -> mreg -> instruction
+ | Mload: trapping_mode -> memory_chunk -> addressing -> list mreg -> mreg -> instruction
| Mstore: memory_chunk -> addressing -> list mreg -> mreg -> instruction
| Mcall: signature -> mreg + ident -> instruction
| Mtailcall: signature -> mreg + ident -> instruction
@@ -321,11 +321,24 @@ Inductive step: state -> trace -> state -> Prop :=
step (State s f sp (Mop op args res :: c) rs m)
E0 (State s f sp c rs' m)
| exec_Mload:
- forall s f sp chunk addr args dst c rs m a v rs',
+ forall s f sp trap chunk addr args dst c rs m a v rs',
eval_addressing ge sp addr rs##args = Some a ->
Mem.loadv chunk m a = Some v ->
rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- v) ->
- step (State s f sp (Mload chunk addr args dst :: c) rs m)
+ step (State s f sp (Mload trap chunk addr args dst :: c) rs m)
+ E0 (State s f sp c rs' m)
+ | exec_Mload_notrap1:
+ forall s f sp chunk addr args dst c rs m rs',
+ eval_addressing ge sp addr rs##args = None ->
+ rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- (default_notrap_load_value chunk)) ->
+ step (State s f sp (Mload NOTRAP chunk addr args dst :: c) rs m)
+ E0 (State s f sp c rs' m)
+ | exec_Mload_notrap2:
+ forall s f sp chunk addr args dst c rs m a rs',
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- (default_notrap_load_value chunk)) ->
+ step (State s f sp (Mload NOTRAP chunk addr args dst :: c) rs m)
E0 (State s f sp c rs' m)
| exec_Mstore:
forall s f sp chunk addr args src c rs m m' a rs',
diff --git a/backend/OpHelpers.v b/backend/OpHelpers.v
index 53414dab..b9b97903 100644
--- a/backend/OpHelpers.v
+++ b/backend/OpHelpers.v
@@ -6,16 +6,16 @@ Require Import Op CminorSel.
runtime library functions. The following type class collects
the names of these functions. *)
-Definition sig_l_l := mksignature (Tlong :: nil) (Some Tlong) cc_default.
-Definition sig_l_f := mksignature (Tlong :: nil) (Some Tfloat) cc_default.
-Definition sig_l_s := mksignature (Tlong :: nil) (Some Tsingle) cc_default.
-Definition sig_f_l := mksignature (Tfloat :: nil) (Some Tlong) cc_default.
-Definition sig_ll_l := mksignature (Tlong :: Tlong :: nil) (Some Tlong) cc_default.
-Definition sig_li_l := mksignature (Tlong :: Tint :: nil) (Some Tlong) cc_default.
-Definition sig_ii_l := mksignature (Tint :: Tint :: nil) (Some Tlong) cc_default.
-Definition sig_ii_i := mksignature (Tint :: Tint :: nil) (Some Tint) cc_default.
-Definition sig_ff_f := mksignature (Tfloat :: Tfloat :: nil) (Some Tfloat) cc_default.
-Definition sig_ss_s := mksignature (Tsingle :: Tsingle :: nil) (Some Tsingle) cc_default.
+Definition sig_l_l := mksignature (Tlong :: nil) Tlong cc_default.
+Definition sig_l_f := mksignature (Tlong :: nil) Tfloat cc_default.
+Definition sig_l_s := mksignature (Tlong :: nil) Tsingle cc_default.
+Definition sig_f_l := mksignature (Tfloat :: nil) Tlong cc_default.
+Definition sig_ll_l := mksignature (Tlong :: Tlong :: nil) Tlong cc_default.
+Definition sig_li_l := mksignature (Tlong :: Tint :: nil) Tlong cc_default.
+Definition sig_ii_l := mksignature (Tint :: Tint :: nil) Tlong cc_default.
+Definition sig_ii_i := mksignature (Tint :: Tint :: nil) Tint cc_default.
+Definition sig_ff_f := mksignature (Tfloat :: Tfloat :: nil) Tfloat cc_default.
+Definition sig_ss_s := mksignature (Tsingle :: Tsingle :: nil) Tsingle cc_default.
Class helper_functions := mk_helper_functions {
i64_dtos: ident; (**r float64 -> signed long *)
diff --git a/backend/PrintAsmaux.ml b/backend/PrintAsmaux.ml
index 8652b2c5..d82e6f84 100644
--- a/backend/PrintAsmaux.ml
+++ b/backend/PrintAsmaux.ml
@@ -99,7 +99,7 @@ let exists_constants () =
let current_function_stacksize = ref 0l
let current_function_sig =
- ref { sig_args = []; sig_res = None; sig_cc = cc_default }
+ ref { sig_args = []; sig_res = Tvoid; sig_cc = cc_default }
(* Functions for printing of symbol names *)
let elf_symbol oc symb =
@@ -268,8 +268,8 @@ let re_asm_param_2 = Str.regexp "%\\([QR]?\\)\\([0-9]+\\)"
let print_inline_asm print_preg oc txt sg args res =
let (operands, ty_operands) =
match sg.sig_res with
- | None -> (args, sg.sig_args)
- | Some tres -> (builtin_arg_of_res res :: args, tres :: sg.sig_args) in
+ | Tvoid -> (args, sg.sig_args)
+ | tres -> (builtin_arg_of_res res :: args, proj_rettype tres :: sg.sig_args) in
let print_fragment = function
| Str.Text s ->
output_string oc s
diff --git a/backend/PrintCminor.ml b/backend/PrintCminor.ml
index 8c255a65..c9a6d399 100644
--- a/backend/PrintCminor.ml
+++ b/backend/PrintCminor.ml
@@ -16,7 +16,7 @@
(** Pretty-printer for Cminor *)
open Format
-open !Camlcoq
+open! Camlcoq
open Integers
open AST
open PrintAST
@@ -193,9 +193,7 @@ let print_sig p sg =
List.iter
(fun t -> fprintf p "%s ->@ " (name_of_type t))
sg.sig_args;
- match sg.sig_res with
- | None -> fprintf p "void"
- | Some ty -> fprintf p "%s" (name_of_type ty)
+ fprintf p "%s" (name_of_rettype sg.sig_res)
let rec just_skips s =
match s with
diff --git a/backend/PrintLTL.ml b/backend/PrintLTL.ml
index 1c449e74..d8f2ac12 100644
--- a/backend/PrintLTL.ml
+++ b/backend/PrintLTL.ml
@@ -61,9 +61,10 @@ let print_succ pp s dfl =
let print_instruction pp succ = function
| Lop(op, args, res) ->
fprintf pp "%a = %a" mreg res (print_operation mreg) (op, args)
- | Lload(chunk, addr, args, dst) ->
- fprintf pp "%a = %s[%a]"
- mreg dst (name_of_chunk chunk) (print_addressing mreg) (addr, args)
+ | Lload(trap,chunk, addr, args, dst) ->
+ fprintf pp "%a = %s[%a]%a"
+ mreg dst (name_of_chunk chunk) (print_addressing mreg) (addr, args)
+ print_trapping_mode trap
| Lgetstack(sl, ofs, ty, dst) ->
fprintf pp "%a = %a" mreg dst slot (sl, ofs, ty)
| Lsetstack(src, sl, ofs, ty) ->
@@ -82,10 +83,11 @@ let print_instruction pp succ = function
(print_builtin_args loc) args
| Lbranch s ->
print_succ pp s succ
- | Lcond(cond, args, s1, s2) ->
- fprintf pp "if (%a) goto %d else goto %d"
+ | Lcond(cond, args, s1, s2, info) ->
+ fprintf pp "if (%a) goto %d else goto %d (prediction: %s)"
(print_condition mreg) (cond, args)
(P.to_int s1) (P.to_int s2)
+ (match info with None -> "none" | Some true -> "branch" | Some false -> "fallthrough")
| Ljumptable(arg, tbl) ->
let tbl = Array.of_list tbl in
fprintf pp "jumptable (%a)" mreg arg;
diff --git a/backend/PrintLTLin.ml b/backend/PrintLTLin.ml
deleted file mode 100644
index 4e8efd16..00000000
--- a/backend/PrintLTLin.ml
+++ /dev/null
@@ -1,115 +0,0 @@
-(* *********************************************************************)
-(* *)
-(* The Compcert verified compiler *)
-(* *)
-(* Xavier Leroy, INRIA Paris-Rocquencourt *)
-(* *)
-(* Copyright Institut National de Recherche en Informatique et en *)
-(* Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the INRIA Non-Commercial License Agreement. *)
-(* *)
-(* *********************************************************************)
-
-(** Pretty-printer for LTLin code *)
-
-open Format
-open Camlcoq
-open Datatypes
-open Maps
-open AST
-open Integers
-open Locations
-open Machregsaux
-open LTLin
-open PrintAST
-open PrintOp
-
-let reg pp loc =
- match loc with
- | R r ->
- begin match name_of_register r with
- | Some s -> fprintf pp "%s" s
- | None -> fprintf pp "<unknown reg>"
- end
- | S (Local(ofs, ty)) ->
- fprintf pp "local(%s,%ld)" (name_of_type ty) (camlint_of_coqint ofs)
- | S (Incoming(ofs, ty)) ->
- fprintf pp "incoming(%s,%ld)" (name_of_type ty) (camlint_of_coqint ofs)
- | S (Outgoing(ofs, ty)) ->
- fprintf pp "outgoing(%s,%ld)" (name_of_type ty) (camlint_of_coqint ofs)
-
-let rec regs pp = function
- | [] -> ()
- | [r] -> reg pp r
- | r1::rl -> fprintf pp "%a, %a" reg r1 regs rl
-
-let ros pp = function
- | Coq_inl r -> reg pp r
- | Coq_inr s -> fprintf pp "\"%s\"" (extern_atom s)
-
-let print_instruction pp i =
- match i with
- | Lop(op, args, res) ->
- fprintf pp "%a = %a@ "
- reg res (PrintOp.print_operation reg) (op, args)
- | Lload(chunk, addr, args, dst) ->
- fprintf pp "%a = %s[%a]@ "
- reg dst (name_of_chunk chunk)
- (PrintOp.print_addressing reg) (addr, args)
- | Lstore(chunk, addr, args, src) ->
- fprintf pp "%s[%a] = %a@ "
- (name_of_chunk chunk)
- (PrintOp.print_addressing reg) (addr, args)
- reg src
- | Lcall(sg, fn, args, res) ->
- fprintf pp "%a = %a(%a)@ "
- reg res ros fn regs args
- | Ltailcall(sg, fn, args) ->
- fprintf pp "tailcall %a(%a)@ "
- ros fn regs args
- | Lbuiltin(ef, args, res) ->
- fprintf pp "%a = builtin %s(%a)@ "
- reg res (name_of_external ef) regs args
- | Llabel lbl ->
- fprintf pp "%ld:@ " (P.to_int32 lbl)
- | Lgoto lbl ->
- fprintf pp "goto %ld@ " (P.to_int32 lbl)
- | Lcond(cond, args, lbl) ->
- fprintf pp "if (%a) goto %ld@ "
- (PrintOp.print_condition reg) (cond, args)
- (P.to_int32 lbl)
- | Ljumptable(arg, tbl) ->
- let tbl = Array.of_list tbl in
- fprintf pp "@[<v 2>jumptable (%a)" reg arg;
- for i = 0 to Array.length tbl - 1 do
- fprintf pp "@ case %d: goto %ld" i (P.to_int32 tbl.(i))
- done;
- fprintf pp "@]@ "
- | Lreturn None ->
- fprintf pp "return@ "
- | Lreturn (Some arg) ->
- fprintf pp "return %a@ " reg arg
-
-let print_function pp id f =
- fprintf pp "@[<v 2>%s(%a) {@ " (extern_atom id) regs f.fn_params;
- List.iter (print_instruction pp) f.fn_code;
- fprintf pp "@;<0 -2>}@]@."
-
-let print_globdef pp (id, gd) =
- match gd with
- | Gfun(Internal f) -> print_function pp id f
- | _ -> ()
-
-let print_program pp prog =
- List.iter (print_globdef pp) prog.prog_defs
-
-let destination : string option ref = ref None
-
-let print_if prog =
- match !destination with
- | None -> ()
- | Some f ->
- let oc = open_out f in
- let pp = formatter_of_out_channel oc in
- print_program pp prog;
- close_out oc
diff --git a/backend/PrintMach.ml b/backend/PrintMach.ml
index 517f3037..70e65832 100644
--- a/backend/PrintMach.ml
+++ b/backend/PrintMach.ml
@@ -48,10 +48,11 @@ let print_instruction pp i =
| Mop(op, args, res) ->
fprintf pp "\t%a = %a\n"
reg res (PrintOp.print_operation reg) (op, args)
- | Mload(chunk, addr, args, dst) ->
- fprintf pp "\t%a = %s[%a]\n"
+ | Mload(trap, chunk, addr, args, dst) ->
+ fprintf pp "\t%a = %s[%a]%a\n"
reg dst (name_of_chunk chunk)
(PrintOp.print_addressing reg) (addr, args)
+ print_trapping_mode trap
| Mstore(chunk, addr, args, src) ->
fprintf pp "\t%s[%a] = %a\n"
(name_of_chunk chunk)
diff --git a/backend/PrintRTL.ml b/backend/PrintRTL.ml
index 841540b6..b2ef05ca 100644
--- a/backend/PrintRTL.ml
+++ b/backend/PrintRTL.ml
@@ -50,10 +50,11 @@ let print_instruction pp (pc, i) =
fprintf pp "%a = %a\n"
reg res (PrintOp.print_operation reg) (op, args);
print_succ pp s (pc - 1)
- | Iload(chunk, addr, args, dst, s) ->
- fprintf pp "%a = %s[%a]\n"
+ | Iload(trap, chunk, addr, args, dst, s) ->
+ fprintf pp "%a = %s[%a]%a\n"
reg dst (name_of_chunk chunk)
- (PrintOp.print_addressing reg) (addr, args);
+ (PrintOp.print_addressing reg) (addr, args)
+ print_trapping_mode trap;
print_succ pp s (pc - 1)
| Istore(chunk, addr, args, src, s) ->
fprintf pp "%s[%a] = %a\n"
@@ -74,10 +75,11 @@ let print_instruction pp (pc, i) =
(name_of_external ef)
(print_builtin_args reg) args;
print_succ pp s (pc - 1)
- | Icond(cond, args, s1, s2) ->
- fprintf pp "if (%a) goto %d else goto %d\n"
+ | Icond(cond, args, s1, s2, info) ->
+ fprintf pp "if (%a) goto %d else goto %d (prediction: %s)\n"
(PrintOp.print_condition reg) (cond, args)
(P.to_int s1) (P.to_int s2)
+ (match info with None -> "none" | Some true -> "branch" | Some false -> "fallthrough")
| Ijumptable(arg, tbl) ->
let tbl = Array.of_list tbl in
fprintf pp "jumptable (%a)\n" reg arg;
diff --git a/backend/PrintXTL.ml b/backend/PrintXTL.ml
index 6432682a..d1b79623 100644
--- a/backend/PrintXTL.ml
+++ b/backend/PrintXTL.ml
@@ -86,9 +86,10 @@ let print_instruction pp succ = function
fprintf pp "(%a) = (%a) using %a, %a" vars dsts vars srcs var t1 var t2
| Xop(op, args, res) ->
fprintf pp "%a = %a" var res (print_operation var) (op, args)
- | Xload(chunk, addr, args, dst) ->
- fprintf pp "%a = %s[%a]"
- var dst (name_of_chunk chunk) (print_addressing var) (addr, args)
+ | Xload(trap, chunk, addr, args, dst) ->
+ fprintf pp "%a = %s[%a]%a"
+ var dst (name_of_chunk chunk) (print_addressing var) (addr, args)
+ print_trapping_mode trap
| Xstore(chunk, addr, args, src) ->
fprintf pp "%s[%a] = %a"
(name_of_chunk chunk) (print_addressing var) (addr, args) var src
@@ -103,7 +104,7 @@ let print_instruction pp succ = function
(print_builtin_args var) args
| Xbranch s ->
print_succ pp s succ
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, _) ->
fprintf pp "if (%a) goto %d else goto %d"
(print_condition var) (cond, args)
(P.to_int s1) (P.to_int s2)
diff --git a/backend/RTL.v b/backend/RTL.v
index 9599a24a..dec59ca2 100644
--- a/backend/RTL.v
+++ b/backend/RTL.v
@@ -43,11 +43,12 @@ Inductive instruction: Type :=
(** [Iop op args dest succ] performs the arithmetic operation [op]
over the values of registers [args], stores the result in [dest],
and branches to [succ]. *)
- | Iload: memory_chunk -> addressing -> list reg -> reg -> node -> instruction
- (** [Iload chunk addr args dest succ] loads a [chunk] quantity from
+ | Iload: trapping_mode -> memory_chunk -> addressing -> list reg -> reg -> node -> instruction
+ (** [Iload trap chunk addr args dest succ] loads a [chunk] quantity from
the address determined by the addressing mode [addr] and the
values of the [args] registers, stores the quantity just read
- into [dest], and branches to [succ]. *)
+ into [dest], and branches to [succ].
+ If trap=NOTRAP, then failures lead to a default value written to [dest]. *)
| Istore: memory_chunk -> addressing -> list reg -> reg -> node -> instruction
(** [Istore chunk addr args src succ] stores the value of register
[src] in the [chunk] quantity at the
@@ -66,11 +67,12 @@ Inductive instruction: Type :=
(** [Ibuiltin ef args dest succ] calls the built-in function
identified by [ef], giving it the values of [args] as arguments.
It stores the return value in [dest] and branches to [succ]. *)
- | Icond: condition -> list reg -> node -> node -> instruction
- (** [Icond cond args ifso ifnot] evaluates the boolean condition
+ | Icond: condition -> list reg -> node -> node -> option bool -> instruction
+ (** [Icond cond args ifso ifnot info] evaluates the boolean condition
[cond] over the values of registers [args]. If the condition
is true, it transitions to [ifso]. If the condition is false,
- it transitions to [ifnot]. *)
+ it transitions to [ifnot]. [info] is a ghost field there to provide
+ information relative to branch prediction. *)
| Ijumptable: reg -> list node -> instruction
(** [Ijumptable arg tbl] transitions to the node that is the [n]-th
element of the list [tbl], where [n] is the unsigned integer
@@ -212,12 +214,25 @@ Inductive step: state -> trace -> state -> Prop :=
step (State s f sp pc rs m)
E0 (State s f sp pc' (rs#res <- v) m)
| exec_Iload:
- forall s f sp pc rs m chunk addr args dst pc' a v,
- (fn_code f)!pc = Some(Iload chunk addr args dst pc') ->
+ forall s f sp pc rs m trap chunk addr args dst pc' a v,
+ (fn_code f)!pc = Some(Iload trap chunk addr args dst pc') ->
eval_addressing ge sp addr rs##args = Some a ->
Mem.loadv chunk m a = Some v ->
step (State s f sp pc rs m)
E0 (State s f sp pc' (rs#dst <- v) m)
+ | exec_Iload_notrap1:
+ forall s f sp pc rs m chunk addr args dst pc',
+ (fn_code f)!pc = Some(Iload NOTRAP chunk addr args dst pc') ->
+ eval_addressing ge sp addr rs##args = None ->
+ step (State s f sp pc rs m)
+ E0 (State s f sp pc' (rs#dst <- (default_notrap_load_value chunk)) m)
+ | exec_Iload_notrap2:
+ forall s f sp pc rs m chunk addr args dst pc' a,
+ (fn_code f)!pc = Some(Iload NOTRAP chunk addr args dst pc') ->
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = None->
+ step (State s f sp pc rs m)
+ E0 (State s f sp pc' (rs#dst <- (default_notrap_load_value chunk)) m)
| exec_Istore:
forall s f sp pc rs m chunk addr args src pc' a m',
(fn_code f)!pc = Some(Istore chunk addr args src pc') ->
@@ -248,8 +263,8 @@ Inductive step: state -> trace -> state -> Prop :=
step (State s f sp pc rs m)
t (State s f sp pc' (regmap_setres res vres rs) m')
| exec_Icond:
- forall s f sp pc rs m cond args ifso ifnot b pc',
- (fn_code f)!pc = Some(Icond cond args ifso ifnot) ->
+ forall s f sp pc rs m cond args ifso ifnot b pc' predb,
+ (fn_code f)!pc = Some(Icond cond args ifso ifnot predb) ->
eval_condition cond rs##args m = Some b ->
pc' = (if b then ifso else ifnot) ->
step (State s f sp pc rs m)
@@ -299,8 +314,8 @@ Proof.
Qed.
Lemma exec_Iload':
- forall s f sp pc rs m chunk addr args dst pc' rs' a v,
- (fn_code f)!pc = Some(Iload chunk addr args dst pc') ->
+ forall s f sp pc rs m trap chunk addr args dst pc' rs' a v,
+ (fn_code f)!pc = Some(Iload trap chunk addr args dst pc') ->
eval_addressing ge sp addr rs##args = Some a ->
Mem.loadv chunk m a = Some v ->
rs' = (rs#dst <- v) ->
@@ -384,12 +399,12 @@ Definition successors_instr (i: instruction) : list node :=
match i with
| Inop s => s :: nil
| Iop op args res s => s :: nil
- | Iload chunk addr args dst s => s :: nil
+ | Iload trap chunk addr args dst s => s :: nil
| Istore chunk addr args src s => s :: nil
| Icall sig ros args res s => s :: nil
| Itailcall sig ros args => nil
| Ibuiltin ef args res s => s :: nil
- | Icond cond args ifso ifnot => ifso :: ifnot :: nil
+ | Icond cond args ifso ifnot _ => ifso :: ifnot :: nil
| Ijumptable arg tbl => tbl
| Ireturn optarg => nil
end.
@@ -403,14 +418,14 @@ Definition instr_uses (i: instruction) : list reg :=
match i with
| Inop s => nil
| Iop op args res s => args
- | Iload chunk addr args dst s => args
+ | Iload trap chunk addr args dst s => args
| Istore chunk addr args src s => src :: args
| Icall sig (inl r) args res s => r :: args
| Icall sig (inr id) args res s => args
| Itailcall sig (inl r) args => r :: args
| Itailcall sig (inr id) args => args
| Ibuiltin ef args res s => params_of_builtin_args args
- | Icond cond args ifso ifnot => args
+ | Icond cond args ifso ifnot _ => args
| Ijumptable arg tbl => arg :: nil
| Ireturn None => nil
| Ireturn (Some arg) => arg :: nil
@@ -422,13 +437,13 @@ Definition instr_defs (i: instruction) : option reg :=
match i with
| Inop s => None
| Iop op args res s => Some res
- | Iload chunk addr args dst s => Some dst
+ | Iload trap chunk addr args dst s => Some dst
| Istore chunk addr args src s => None
| Icall sig ros args res s => Some res
| Itailcall sig ros args => None
| Ibuiltin ef args res s =>
match res with BR r => Some r | _ => None end
- | Icond cond args ifso ifnot => None
+ | Icond cond args ifso ifnot _ => None
| Ijumptable arg tbl => None
| Ireturn optarg => None
end.
@@ -462,7 +477,7 @@ Definition max_reg_instr (m: positive) (pc: node) (i: instruction) :=
match i with
| Inop s => m
| Iop op args res s => fold_left Pos.max args (Pos.max res m)
- | Iload chunk addr args dst s => fold_left Pos.max args (Pos.max dst m)
+ | Iload trap chunk addr args dst s => fold_left Pos.max args (Pos.max dst m)
| Istore chunk addr args src s => fold_left Pos.max args (Pos.max src m)
| Icall sig (inl r) args res s => fold_left Pos.max args (Pos.max r (Pos.max res m))
| Icall sig (inr id) args res s => fold_left Pos.max args (Pos.max res m)
@@ -471,7 +486,7 @@ Definition max_reg_instr (m: positive) (pc: node) (i: instruction) :=
| Ibuiltin ef args res s =>
fold_left Pos.max (params_of_builtin_args args)
(fold_left Pos.max (params_of_builtin_res res) m)
- | Icond cond args ifso ifnot => fold_left Pos.max args m
+ | Icond cond args ifso ifnot _ => fold_left Pos.max args m
| Ijumptable arg tbl => Pos.max arg m
| Ireturn None => m
| Ireturn (Some arg) => Pos.max arg m
diff --git a/backend/RTLgen.v b/backend/RTLgen.v
index 9d7a8506..ac98f3a1 100644
--- a/backend/RTLgen.v
+++ b/backend/RTLgen.v
@@ -410,12 +410,11 @@ Fixpoint convert_builtin_args {A: Type} (al: list (builtin_arg expr)) (rl: list
a1' :: convert_builtin_args al rl1
end.
-Definition convert_builtin_res (map: mapping) (oty: option typ) (r: builtin_res ident) : mon (builtin_res reg) :=
- match r, oty with
- | BR id, _ => do r <- find_var map id; ret (BR r)
- | BR_none, None => ret BR_none
- | BR_none, Some _ => do r <- new_reg; ret (BR r)
- | _, _ => error (Errors.msg "RTLgen: bad builtin_res")
+Definition convert_builtin_res (map: mapping) (ty: rettype) (r: builtin_res ident) : mon (builtin_res reg) :=
+ match r with
+ | BR id => do r <- find_var map id; ret (BR r)
+ | BR_none => if rettype_eq ty Tvoid then ret BR_none else (do r <- new_reg; ret (BR r))
+ | _ => error (Errors.msg "RTLgen: bad builtin_res")
end.
(** Translation of an expression. [transl_expr map a rd nd]
@@ -436,7 +435,7 @@ Fixpoint transl_expr (map: mapping) (a: expr) (rd: reg) (nd: node)
transl_exprlist map al rl no
| Eload chunk addr al =>
do rl <- alloc_regs map al;
- do no <- add_instr (Iload chunk addr rl rd nd);
+ do no <- add_instr (Iload TRAP chunk addr rl rd nd);
transl_exprlist map al rl no
| Econdition a b c =>
do nfalse <- transl_expr map c rd nd;
@@ -480,7 +479,7 @@ with transl_condexpr (map: mapping) (a: condexpr) (ntrue nfalse: node)
match a with
| CEcond c al =>
do rl <- alloc_regs map al;
- do nt <- add_instr (Icond c rl ntrue nfalse);
+ do nt <- add_instr (Icond c rl ntrue nfalse None);
transl_exprlist map al rl nt
| CEcondition a b c =>
do nc <- transl_condexpr map c ntrue nfalse;
@@ -667,10 +666,7 @@ Fixpoint reserve_labels (s: stmt) (ms: labelmap * state)
(** Translation of a CminorSel function. *)
Definition ret_reg (sig: signature) (rd: reg) : option reg :=
- match sig.(sig_res) with
- | None => None
- | Some ty => Some rd
- end.
+ if rettype_eq sig.(sig_res) Tvoid then None else Some rd.
Definition transl_fun (f: CminorSel.function) (ngoto: labelmap): mon (node * list reg) :=
do (rparams, map1) <- add_vars init_mapping f.(CminorSel.fn_params);
diff --git a/backend/RTLgenspec.v b/backend/RTLgenspec.v
index 17022a7d..30ad7d82 100644
--- a/backend/RTLgenspec.v
+++ b/backend/RTLgenspec.v
@@ -639,8 +639,8 @@ Lemma new_reg_return_ok:
map_valid map s1 ->
return_reg_ok s2 map (ret_reg sig r).
Proof.
- intros. unfold ret_reg. destruct (sig_res sig); constructor.
- eauto with rtlg. eauto with rtlg.
+ intros. unfold ret_reg.
+ destruct (rettype_eq (sig_res sig) Tvoid); constructor; eauto with rtlg.
Qed.
(** * Relational specification of the translation *)
@@ -707,7 +707,7 @@ Inductive tr_expr (c: code):
tr_expr c map pr (Eop op al) ns nd rd dst
| tr_Eload: forall map pr chunk addr al ns nd rd n1 rl dst,
tr_exprlist c map pr al ns n1 rl ->
- c!n1 = Some (Iload chunk addr rl rd nd) ->
+ c!n1 = Some (Iload TRAP chunk addr rl rd nd) ->
reg_map_ok map rd dst -> ~In rd pr ->
tr_expr c map pr (Eload chunk addr al) ns nd rd dst
| tr_Econdition: forall map pr a ifso ifnot ns nd rd ntrue nfalse dst,
@@ -744,9 +744,9 @@ Inductive tr_expr (c: code):
with tr_condition (c: code):
mapping -> list reg -> condexpr -> node -> node -> node -> Prop :=
- | tr_CEcond: forall map pr cond bl ns ntrue nfalse n1 rl,
+ | tr_CEcond: forall map pr cond bl ns ntrue nfalse n1 rl i,
tr_exprlist c map pr bl ns n1 rl ->
- c!n1 = Some (Icond cond rl ntrue nfalse) ->
+ c!n1 = Some (Icond cond rl ntrue nfalse i) ->
tr_condition c map pr (CEcond cond bl) ns ntrue nfalse
| tr_CEcondition: forall map pr a1 a2 a3 ns ntrue nfalse n2 n3,
tr_condition c map pr a1 ns n2 n3 ->
@@ -1224,9 +1224,9 @@ Lemma convert_builtin_res_charact:
Proof.
destruct res; simpl; intros.
- monadInv TR. constructor. unfold find_var in EQ. destruct (map_vars map)!x; inv EQ; auto.
-- destruct oty; monadInv TR.
-+ constructor. eauto with rtlg.
+- destruct (rettype_eq oty Tvoid); monadInv TR.
+ constructor.
++ constructor. eauto with rtlg.
- monadInv TR.
Qed.
@@ -1350,7 +1350,7 @@ Proof.
intros [C D].
eapply tr_function_intro; eauto with rtlg.
eapply transl_stmt_charact; eauto with rtlg.
- unfold ret_reg. destruct (sig_res (CminorSel.fn_sig f)).
- constructor. eauto with rtlg. eauto with rtlg.
+ unfold ret_reg. destruct (rettype_eq (sig_res (CminorSel.fn_sig f)) Tvoid).
constructor.
+ constructor; eauto with rtlg.
Qed.
diff --git a/backend/RTLtyping.v b/backend/RTLtyping.v
index 8336d1bf..15ed6d8a 100644
--- a/backend/RTLtyping.v
+++ b/backend/RTLtyping.v
@@ -104,11 +104,11 @@ Inductive wt_instr : instruction -> Prop :=
valid_successor s ->
wt_instr (Iop op args res s)
| wt_Iload:
- forall chunk addr args dst s,
+ forall trap chunk addr args dst s,
map env args = type_of_addressing addr ->
env dst = type_of_chunk chunk ->
valid_successor s ->
- wt_instr (Iload chunk addr args dst s)
+ wt_instr (Iload trap chunk addr args dst s)
| wt_Istore:
forall chunk addr args src s,
map env args = type_of_addressing addr ->
@@ -139,11 +139,11 @@ Inductive wt_instr : instruction -> Prop :=
valid_successor s ->
wt_instr (Ibuiltin ef args res s)
| wt_Icond:
- forall cond args s1 s2,
+ forall cond args s1 s2 i,
map env args = type_of_condition cond ->
valid_successor s1 ->
valid_successor s2 ->
- wt_instr (Icond cond args s1 s2)
+ wt_instr (Icond cond args s1 s2 i)
| wt_Ijumptable:
forall arg tbl,
env arg = Tint ->
@@ -151,11 +151,12 @@ Inductive wt_instr : instruction -> Prop :=
list_length_z tbl * 4 <= Int.max_unsigned ->
wt_instr (Ijumptable arg tbl)
| wt_Ireturn_none:
- funct.(fn_sig).(sig_res) = None ->
+ funct.(fn_sig).(sig_res) = Tvoid ->
wt_instr (Ireturn None)
| wt_Ireturn_some:
forall arg ty,
- funct.(fn_sig).(sig_res) = Some ty ->
+ funct.(fn_sig).(sig_res) <> Tvoid ->
+ env arg = proj_sig_res funct.(fn_sig) ->
env arg = ty ->
wt_instr (Ireturn (Some arg)).
@@ -282,7 +283,7 @@ Definition type_instr (e: S.typenv) (i: instruction) : res S.typenv :=
else
(let (targs, tres) := type_of_operation op in
do e1 <- S.set_list e args targs; S.set e1 res tres)
- | Iload chunk addr args dst s =>
+ | Iload trap chunk addr args dst s =>
do x <- check_successor s;
do e1 <- S.set_list e args (type_of_addressing addr);
S.set e1 dst (type_of_chunk chunk)
@@ -298,7 +299,7 @@ Definition type_instr (e: S.typenv) (i: instruction) : res S.typenv :=
| Itailcall sig ros args =>
do e1 <- type_ros e ros;
do e2 <- S.set_list e1 args sig.(sig_args);
- if opt_typ_eq sig.(sig_res) f.(fn_sig).(sig_res) then
+ if rettype_eq sig.(sig_res) f.(fn_sig).(sig_res) then
if tailcall_is_possible sig
then OK e2
else Error(msg "tailcall not possible")
@@ -312,7 +313,7 @@ Definition type_instr (e: S.typenv) (i: instruction) : res S.typenv :=
| _ => type_builtin_args e args sig.(sig_args)
end;
type_builtin_res e1 res (proj_sig_res sig)
- | Icond cond args s1 s2 =>
+ | Icond cond args s1 s2 _ =>
do x1 <- check_successor s1;
do x2 <- check_successor s2;
S.set_list e args (type_of_condition cond)
@@ -323,9 +324,9 @@ Definition type_instr (e: S.typenv) (i: instruction) : res S.typenv :=
then OK e1
else Error(msg "jumptable too big")
| Ireturn optres =>
- match optres, f.(fn_sig).(sig_res) with
- | None, None => OK e
- | Some r, Some t => S.set e r t
+ match optres, rettype_eq f.(fn_sig).(sig_res) Tvoid with
+ | None, left _ => OK e
+ | Some r, right _ => S.set e r (proj_sig_res f.(fn_sig))
| _, _ => Error(msg "bad return")
end
end.
@@ -468,7 +469,7 @@ Proof.
destruct l; try discriminate. destruct l; monadInv EQ0. eauto with ty.
destruct (type_of_operation o) as [targs tres] eqn:TYOP. monadInv EQ0. eauto with ty.
- (* tailcall *)
- destruct (opt_typ_eq (sig_res s) (sig_res (fn_sig f))); try discriminate.
+ destruct (rettype_eq (sig_res s) (sig_res (fn_sig f))); try discriminate.
destruct (tailcall_is_possible s) eqn:TCIP; inv EQ2.
eauto with ty.
- (* builtin *)
@@ -477,7 +478,8 @@ Proof.
destruct (zle (list_length_z l * 4) Int.max_unsigned); inv EQ2.
eauto with ty.
- (* return *)
- simpl in H. destruct o as [r|] eqn: RET; destruct (sig_res (fn_sig f)) as [t|] eqn: RES; try discriminate.
+ simpl in H.
+ destruct o as [r|] eqn: RET; destruct (rettype_eq (sig_res (fn_sig f)) Tvoid); try discriminate.
eauto with ty.
inv H; auto with ty.
Qed.
@@ -519,7 +521,7 @@ Proof.
eapply S.set_sound; eauto with ty.
eauto with ty.
- (* tailcall *)
- destruct (opt_typ_eq (sig_res s) (sig_res (fn_sig f))); try discriminate.
+ destruct (rettype_eq (sig_res s) (sig_res (fn_sig f))); try discriminate.
destruct (tailcall_is_possible s) eqn:TCIP; inv EQ2.
constructor.
eapply type_ros_sound; eauto with ty.
@@ -543,8 +545,9 @@ Proof.
eapply check_successors_sound; eauto.
auto.
- (* return *)
- simpl in H. destruct o as [r|] eqn: RET; destruct (sig_res (fn_sig f)) as [t|] eqn: RES; try discriminate.
- econstructor. eauto. eapply S.set_sound; eauto with ty.
+ simpl in H.
+ destruct o as [r|] eqn: RET; destruct (rettype_eq (sig_res (fn_sig f)) Tvoid); try discriminate.
+ econstructor. auto. eapply S.set_sound; eauto with ty. eauto.
inv H. constructor. auto.
Qed.
@@ -721,9 +724,9 @@ Proof.
rewrite check_successor_complete by auto; simpl.
apply IHtbl0; intros; auto.
- (* return none *)
- rewrite H0. exists e; auto.
+ rewrite H0, dec_eq_true. exists e; auto.
- (* return some *)
- rewrite H0. apply S.set_complete; auto.
+ rewrite dec_eq_false by auto. apply S.set_complete; auto.
Qed.
Lemma type_code_complete:
@@ -841,14 +844,24 @@ Proof.
Qed.
Lemma wt_exec_Iload:
- forall env f chunk addr args dst s m a v rs,
- wt_instr f env (Iload chunk addr args dst s) ->
+ forall env f trap chunk addr args dst s m a v rs,
+ wt_instr f env (Iload trap chunk addr args dst s) ->
Mem.loadv chunk m a = Some v ->
wt_regset env rs ->
wt_regset env (rs#dst <- v).
Proof.
intros. destruct a; simpl in H0; try discriminate. inv H.
- eapply wt_regset_assign; eauto. rewrite H8; eapply Mem.load_type; eauto.
+ eapply wt_regset_assign; eauto. rewrite H9; eapply Mem.load_type; eauto.
+Qed.
+
+Lemma wt_exec_Iload_notrap:
+ forall env f chunk addr args dst s rs,
+ wt_instr f env (Iload NOTRAP chunk addr args dst s) ->
+ wt_regset env rs ->
+ wt_regset env (rs#dst <- (default_notrap_load_value chunk)).
+Proof.
+ intros.
+ eapply wt_regset_assign; eauto. simpl. trivial.
Qed.
Lemma wt_exec_Ibuiltin:
@@ -872,7 +885,7 @@ Qed.
Inductive wt_stackframes: list stackframe -> signature -> Prop :=
| wt_stackframes_nil: forall sg,
- sg.(sig_res) = Some Tint ->
+ sg.(sig_res) = Tint ->
wt_stackframes nil sg
| wt_stackframes_cons:
forall s res f sp pc rs env sg,
@@ -930,6 +943,10 @@ Proof.
econstructor; eauto. eapply wt_exec_Iop; eauto.
(* Iload *)
econstructor; eauto. eapply wt_exec_Iload; eauto.
+ (* Iload notrap1*)
+ econstructor; eauto. eapply wt_exec_Iload_notrap; eauto.
+ (* Iload notrap2*)
+ econstructor; eauto. eapply wt_exec_Iload_notrap; eauto.
(* Istore *)
econstructor; eauto.
(* Icall *)
@@ -964,13 +981,13 @@ Proof.
econstructor; eauto.
(* Ireturn *)
econstructor; eauto.
- inv WTI; simpl. auto. unfold proj_sig_res; rewrite H2. auto.
+ inv WTI; simpl. auto. rewrite <- H3. auto.
(* internal function *)
simpl in *. inv H5.
econstructor; eauto.
inv H1. apply wt_init_regs; auto. rewrite wt_params0. auto.
(* external function *)
- econstructor; eauto. simpl.
+ econstructor; eauto.
eapply external_call_well_typed; eauto.
(* return *)
inv H1. econstructor; eauto.
diff --git a/backend/Regalloc.ml b/backend/Regalloc.ml
index 7db8a866..ffe26933 100644
--- a/backend/Regalloc.ml
+++ b/backend/Regalloc.ml
@@ -249,18 +249,18 @@ let block_of_RTL_instr funsig tyenv = function
else
let t = new_temp (tyenv res) in (t :: args2', t) in
movelist args1 args3 (Xop(op, args3, res3) :: move res3 res1 [Xbranch s])
- | RTL.Iload(chunk, addr, args, dst, s) ->
+ | RTL.Iload(trap, chunk, addr, args, dst, s) ->
if Archi.splitlong && chunk = Mint64 then begin
match offset_addressing addr (coqint_of_camlint 4l) with
| None -> assert false
| Some addr' ->
- [Xload(Mint32, addr, vregs tyenv args,
+ [Xload(trap, Mint32, addr, vregs tyenv args,
V((if Archi.big_endian then dst else twin_reg dst), Tint));
- Xload(Mint32, addr', vregs tyenv args,
+ Xload(trap, Mint32, addr', vregs tyenv args,
V((if Archi.big_endian then twin_reg dst else dst), Tint));
Xbranch s]
end else
- [Xload(chunk, addr, vregs tyenv args, vreg tyenv dst); Xbranch s]
+ [Xload(trap, chunk, addr, vregs tyenv args, vreg tyenv dst); Xbranch s]
| RTL.Istore(chunk, addr, args, src, s) ->
if Archi.splitlong && chunk = Mint64 then begin
match offset_addressing addr (coqint_of_camlint 4l) with
@@ -295,8 +295,8 @@ let block_of_RTL_instr funsig tyenv = function
(Xbuiltin(ef, args2, res2) ::
movelist (params_of_builtin_res res2) (params_of_builtin_res res1)
[Xbranch s])
- | RTL.Icond(cond, args, s1, s2) ->
- [Xcond(cond, vregs tyenv args, s1, s2)]
+ | RTL.Icond(cond, args, s1, s2, i) ->
+ [Xcond(cond, vregs tyenv args, s1, s2, i)]
| RTL.Ijumptable(arg, tbl) ->
[Xjumptable(vreg tyenv arg, tbl)]
| RTL.Ireturn None ->
@@ -364,7 +364,7 @@ let live_before instr after =
if VSet.mem res after
then vset_addlist args (VSet.remove res after)
else after
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
if VSet.mem dst after
then vset_addlist args (VSet.remove dst after)
else after
@@ -380,7 +380,7 @@ let live_before instr after =
vset_addargs args (vset_removeres res after)
| Xbranch s ->
after
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, _) ->
List.fold_right VSet.add args after
| Xjumptable(arg, tbl) ->
VSet.add arg after
@@ -459,7 +459,7 @@ let dce_instr instr after k =
if VSet.mem res after
then instr :: k
else k
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
if VSet.mem dst after
then instr :: k
else k
@@ -550,7 +550,7 @@ let spill_costs f =
(* temps must not be spilled *)
| Xop(op, args, res) ->
charge_list 10 1 args; charge 10 1 res
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
charge_list 10 1 args; charge 10 1 dst
| Xstore(chunk, addr, args, src) ->
charge_list 10 1 args; charge 10 1 src
@@ -575,7 +575,7 @@ let spill_costs f =
charge_list 10 1 (params_of_builtin_res res)
end
| Xbranch _ -> ()
- | Xcond(cond, args, _, _) ->
+ | Xcond(cond, args, _, _, _) ->
charge_list 10 1 args
| Xjumptable(arg, _) ->
charge 10 1 arg
@@ -677,7 +677,7 @@ let add_interfs_instr g instr live =
(vset_addlist (res :: argl) (VSet.remove res live))
end;
add_interfs_destroyed g (VSet.remove res live) (destroyed_by_op op)
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
add_interfs_def g dst live;
add_interfs_destroyed g (VSet.remove dst live)
(destroyed_by_load chunk addr)
@@ -718,7 +718,7 @@ let add_interfs_instr g instr live =
end
| Xbranch s ->
()
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, _) ->
add_interfs_destroyed g live (destroyed_by_cond cond)
| Xjumptable(arg, tbl) ->
add_interfs_destroyed g live destroyed_by_jumptable
@@ -782,7 +782,7 @@ let tospill_instr alloc instr ts =
ts
| Xop(op, args, res) ->
addlist_tospill alloc args (add_tospill alloc res ts)
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
addlist_tospill alloc args (add_tospill alloc dst ts)
| Xstore(chunk, addr, args, src) ->
addlist_tospill alloc args (add_tospill alloc src ts)
@@ -797,7 +797,7 @@ let tospill_instr alloc instr ts =
(addlist_tospill alloc (params_of_builtin_res res) ts)
| Xbranch s ->
ts
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, _) ->
addlist_tospill alloc args ts
| Xjumptable(arg, tbl) ->
add_tospill alloc arg ts
@@ -964,10 +964,10 @@ let spill_instr tospill eqs instr =
add res tmp (kill tmp (kill res eqs2)))
end
end
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
let (args', c1, eqs1) = reload_vars tospill eqs args in
let (dst', c2, eqs2) = save_var tospill eqs1 dst in
- (c1 @ Xload(chunk, addr, args', dst') :: c2, eqs2)
+ (c1 @ Xload(trap, chunk, addr, args', dst') :: c2, eqs2)
| Xstore(chunk, addr, args, src) ->
let (args', c1, eqs1) = reload_vars tospill eqs args in
let (src', c2, eqs2) = reload_var tospill eqs1 src in
@@ -990,9 +990,9 @@ let spill_instr tospill eqs instr =
(c1 @ Xbuiltin(ef, args', res') :: c2, eqs2)
| Xbranch s ->
([instr], eqs)
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, i) ->
let (args', c1, eqs1) = reload_vars tospill eqs args in
- (c1 @ [Xcond(cond, args', s1, s2)], eqs1)
+ (c1 @ [Xcond(cond, args', s1, s2, i)], eqs1)
| Xjumptable(arg, tbl) ->
let (arg', c1, eqs1) = reload_var tospill eqs arg in
(c1 @ [Xjumptable(arg', tbl)], eqs1)
@@ -1115,8 +1115,8 @@ let transl_instr alloc instr k =
LTL.Lop(Omove, [rarg1], rres) ::
LTL.Lop(op, rres :: rargl, rres) :: k
end
- | Xload(chunk, addr, args, dst) ->
- LTL.Lload(chunk, addr, mregs_of alloc args, mreg_of alloc dst) :: k
+ | Xload(trap, chunk, addr, args, dst) ->
+ LTL.Lload(trap, chunk, addr, mregs_of alloc args, mreg_of alloc dst) :: k
| Xstore(chunk, addr, args, src) ->
LTL.Lstore(chunk, addr, mregs_of alloc args, mreg_of alloc src) :: k
| Xcall(sg, vos, args, res) ->
@@ -1128,8 +1128,8 @@ let transl_instr alloc instr k =
AST.map_builtin_res (mreg_of alloc) res) :: k
| Xbranch s ->
LTL.Lbranch s :: []
- | Xcond(cond, args, s1, s2) ->
- LTL.Lcond(cond, mregs_of alloc args, s1, s2) :: []
+ | Xcond(cond, args, s1, s2, i) ->
+ LTL.Lcond(cond, mregs_of alloc args, s1, s2, i) :: []
| Xjumptable(arg, tbl) ->
LTL.Ljumptable(mreg_of alloc arg, tbl) :: []
| Xreturn optarg ->
diff --git a/backend/Renumber.v b/backend/Renumber.v
index 10f58251..2727b979 100644
--- a/backend/Renumber.v
+++ b/backend/Renumber.v
@@ -43,12 +43,12 @@ Definition renum_instr (i: instruction) : instruction :=
match i with
| Inop s => Inop (renum_pc s)
| Iop op args res s => Iop op args res (renum_pc s)
- | Iload chunk addr args res s => Iload chunk addr args res (renum_pc s)
+ | Iload trap chunk addr args res s => Iload trap chunk addr args res (renum_pc s)
| Istore chunk addr args src s => Istore chunk addr args src (renum_pc s)
| Icall sg ros args res s => Icall sg ros args res (renum_pc s)
| Itailcall sg ros args => i
| Ibuiltin ef args res s => Ibuiltin ef args res (renum_pc s)
- | Icond cond args s1 s2 => Icond cond args (renum_pc s1) (renum_pc s2)
+ | Icond cond args s1 s2 info => Icond cond args (renum_pc s1) (renum_pc s2) info
| Ijumptable arg tbl => Ijumptable arg (List.map renum_pc tbl)
| Ireturn or => i
end.
diff --git a/backend/Renumberproof.v b/backend/Renumberproof.v
index 7cda9425..2e161965 100644
--- a/backend/Renumberproof.v
+++ b/backend/Renumberproof.v
@@ -175,6 +175,18 @@ Proof.
rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
eapply exec_Iload; eauto.
constructor; auto. eapply reach_succ; eauto. simpl; auto.
+ (* load notrap1 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = None).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap1; eauto.
+ constructor; auto. eapply reach_succ; eauto. simpl; auto.
+ (* load notrap2 *)
+ econstructor; split.
+ assert (eval_addressing tge sp addr rs ## args = Some a).
+ rewrite <- H0. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_Iload_notrap2; eauto.
+ constructor; auto. eapply reach_succ; eauto. simpl; auto.
(* store *)
econstructor; split.
assert (eval_addressing tge sp addr rs ## args = Some a).
diff --git a/backend/Splitting.ml b/backend/Splitting.ml
index 40f09c3d..3ca45c3b 100644
--- a/backend/Splitting.ml
+++ b/backend/Splitting.ml
@@ -151,8 +151,8 @@ let ren_instr f maps pc i =
| Inop s -> Inop s
| Iop(op, args, res, s) ->
Iop(op, ren_regs before args, ren_reg after res, s)
- | Iload(chunk, addr, args, dst, s) ->
- Iload(chunk, addr, ren_regs before args, ren_reg after dst, s)
+ | Iload(trap, chunk, addr, args, dst, s) ->
+ Iload(trap, chunk, addr, ren_regs before args, ren_reg after dst, s)
| Istore(chunk, addr, args, src, s) ->
Istore(chunk, addr, ren_regs before args, ren_reg before src, s)
| Icall(sg, ros, args, res, s) ->
@@ -162,8 +162,8 @@ let ren_instr f maps pc i =
| Ibuiltin(ef, args, res, s) ->
Ibuiltin(ef, List.map (AST.map_builtin_arg (ren_reg before)) args,
AST.map_builtin_res (ren_reg after) res, s)
- | Icond(cond, args, s1, s2) ->
- Icond(cond, ren_regs before args, s1, s2)
+ | Icond(cond, args, s1, s2, i) ->
+ Icond(cond, ren_regs before args, s1, s2, i)
| Ijumptable(arg, tbl) ->
Ijumptable(ren_reg before arg, tbl)
| Ireturn optarg ->
diff --git a/backend/Stacking.v b/backend/Stacking.v
index 7b382d05..0e3f2832 100644
--- a/backend/Stacking.v
+++ b/backend/Stacking.v
@@ -133,8 +133,8 @@ Definition transl_instr
end
| Lop op args res =>
Mop (transl_op fe op) args res :: k
- | Lload chunk addr args dst =>
- Mload chunk (transl_addr fe addr) args dst :: k
+ | Lload trap chunk addr args dst =>
+ Mload trap chunk (transl_addr fe addr) args dst :: k
| Lstore chunk addr args src =>
Mstore chunk (transl_addr fe addr) args src :: k
| Lcall sig ros =>
diff --git a/backend/Stackingproof.v b/backend/Stackingproof.v
index 326fab61..d3fcdb91 100644
--- a/backend/Stackingproof.v
+++ b/backend/Stackingproof.v
@@ -1918,6 +1918,46 @@ Proof.
apply agree_regs_set_reg. rewrite transl_destroyed_by_load. apply agree_regs_undef_regs; auto. auto.
apply agree_locs_set_reg. apply agree_locs_undef_locs. auto. apply destroyed_by_load_caller_save. auto.
+- (* Lload notrap1*)
+ assert (eval_addressing ge (Vptr sp' Ptrofs.zero) (transl_addr (make_env (function_bounds f)) addr) rs0##args = None) as Haddress.
+ eapply eval_addressing_inject_none; eauto.
+ eapply globalenv_inject_preserves_globals. eapply sep_proj2. eapply sep_proj2. eapply sep_proj2. eexact SEP.
+ eapply agree_reglist; eauto.
+ econstructor; split.
+ apply plus_one. apply exec_Mload_notrap1.
+ rewrite <- Haddress. apply eval_addressing_preserved. exact symbols_preserved.
+ eauto. econstructor; eauto with coqlib.
+ apply agree_regs_set_reg. rewrite transl_destroyed_by_load. apply agree_regs_undef_regs; auto. auto.
+ apply agree_locs_set_reg. apply agree_locs_undef_locs. auto. apply destroyed_by_load_caller_save. auto.
+
+- (* Lload notrap2 *)
+ assert (exists a',
+ eval_addressing ge (Vptr sp' Ptrofs.zero) (transl_addr (make_env (function_bounds f)) addr) rs0##args = Some a'
+ /\ Val.inject j a a').
+ eapply eval_addressing_inject; eauto.
+ eapply globalenv_inject_preserves_globals. eapply sep_proj2. eapply sep_proj2. eapply sep_proj2. eexact SEP.
+ eapply agree_reglist; eauto.
+ destruct H1 as [a' [A B]].
+
+ destruct ( Mem.loadv chunk m' a') as [v'|] eqn:Hloadv.
+ {
+ econstructor; split.
+ apply plus_one. apply exec_Mload with (a:=a') (v:=v'); eauto.
+ try (rewrite <- A; apply eval_addressing_preserved; auto; exact symbols_preserved).
+ econstructor; eauto with coqlib.
+ apply agree_regs_set_reg. rewrite transl_destroyed_by_load. apply agree_regs_undef_regs; auto. auto.
+ apply agree_locs_set_reg. apply agree_locs_undef_locs. auto. apply destroyed_by_load_caller_save. auto.
+ }
+ {
+ econstructor; split.
+ apply plus_one. apply exec_Mload_notrap2 with (a:=a'); eauto.
+ try (rewrite <- A; apply eval_addressing_preserved; auto; exact symbols_preserved).
+
+ econstructor; eauto with coqlib.
+ apply agree_regs_set_reg. rewrite transl_destroyed_by_load. apply agree_regs_undef_regs; auto. auto.
+ apply agree_locs_set_reg. apply agree_locs_undef_locs. auto. apply destroyed_by_load_caller_save. auto.
+ }
+
- (* Lstore *)
assert (exists a',
eval_addressing ge (Vptr sp' Ptrofs.zero) (transl_addr (make_env (function_bounds f)) addr) rs0##args = Some a'
diff --git a/backend/Tailcall.v b/backend/Tailcall.v
index 939abeea..b7a62d74 100644
--- a/backend/Tailcall.v
+++ b/backend/Tailcall.v
@@ -82,7 +82,7 @@ Definition transf_instr (f: function) (pc: node) (instr: instruction) :=
| Icall sig ros args res s =>
if is_return niter f s res
&& tailcall_is_possible sig
- && opt_typ_eq sig.(sig_res) f.(fn_sig).(sig_res)
+ && rettype_eq sig.(sig_res) f.(fn_sig).(sig_res)
then Itailcall sig ros args
else instr
| _ => instr
diff --git a/backend/Tailcallproof.v b/backend/Tailcallproof.v
index 06e314f3..79a5c1cf 100644
--- a/backend/Tailcallproof.v
+++ b/backend/Tailcallproof.v
@@ -157,12 +157,10 @@ Lemma transf_instr_charact:
transf_instr_spec f instr (transf_instr f pc instr).
Proof.
intros. unfold transf_instr. destruct instr; try constructor.
- caseEq (is_return niter f n r && tailcall_is_possible s &&
- opt_typ_eq (sig_res s) (sig_res (fn_sig f))); intros.
- destruct (andb_prop _ _ H0). destruct (andb_prop _ _ H1).
- eapply transf_instr_tailcall; eauto.
- eapply is_return_charact; eauto.
- constructor.
+ destruct (is_return niter f n r && tailcall_is_possible s &&
+ rettype_eq (sig_res s) (sig_res (fn_sig f))) eqn:B.
+- InvBooleans. eapply transf_instr_tailcall; eauto. eapply is_return_charact; eauto.
+- constructor.
Qed.
Lemma transf_instr_lookup:
@@ -438,6 +436,43 @@ Proof.
apply eval_addressing_preserved. exact symbols_preserved. eauto.
econstructor; eauto. apply set_reg_lessdef; auto.
+- (* load notrap1 *)
+ TransfInstr.
+ assert (Val.lessdef_list (rs##args) (rs'##args)). apply regs_lessdef_regs; auto.
+ left.
+ exists (State s' (transf_function f) (Vptr sp0 Ptrofs.zero) pc' (rs'#dst <- (default_notrap_load_value chunk)) m'); split.
+ eapply exec_Iload_notrap1.
+ eassumption.
+ eapply eval_addressing_lessdef_none. eassumption.
+ erewrite eval_addressing_preserved.
+ eassumption. exact symbols_preserved.
+
+ econstructor; eauto. apply set_reg_lessdef; auto.
+
+- (* load notrap2 *)
+ TransfInstr.
+ assert (Val.lessdef_list (rs##args) (rs'##args)). apply regs_lessdef_regs; auto.
+ left.
+
+ exploit eval_addressing_lessdef; eauto.
+ intros [a' [ADDR' ALD]].
+
+ destruct (Mem.loadv chunk m' a') eqn:Echunk2.
+ + exists (State s' (transf_function f) (Vptr sp0 Ptrofs.zero) pc' (rs'#dst <- v) m'); split.
+ eapply exec_Iload with (a:=a'). eassumption.
+ erewrite eval_addressing_preserved.
+ eassumption.
+ exact symbols_preserved.
+ assumption.
+ econstructor; eauto. apply set_reg_lessdef; auto.
+ + exists (State s' (transf_function f) (Vptr sp0 Ptrofs.zero) pc' (rs'#dst <- (default_notrap_load_value chunk)) m'); split.
+ eapply exec_Iload_notrap2. eassumption.
+ erewrite eval_addressing_preserved.
+ eassumption.
+ exact symbols_preserved.
+ assumption.
+ econstructor; eauto. apply set_reg_lessdef; auto.
+
- (* store *)
TransfInstr.
assert (Val.lessdef_list (rs##args) (rs'##args)). apply regs_lessdef_regs; auto.
diff --git a/backend/Tunneling.v b/backend/Tunneling.v
index da1ce45a..a4c4a195 100644
--- a/backend/Tunneling.v
+++ b/backend/Tunneling.v
@@ -78,11 +78,11 @@ Definition record_gotos (f: LTL.function) : U.t :=
Definition tunnel_instr (uf: U.t) (i: instruction) : instruction :=
match i with
| Lbranch s => Lbranch (U.repr uf s)
- | Lcond cond args s1 s2 =>
+ | Lcond cond args s1 s2 info =>
let s1' := U.repr uf s1 in let s2' := U.repr uf s2 in
if peq s1' s2'
then Lbranch s1'
- else Lcond cond args s1' s2'
+ else Lcond cond args s1' s2' info
| Ljumptable arg tbl => Ljumptable arg (List.map (U.repr uf) tbl)
| _ => i
end.
diff --git a/backend/Tunnelingproof.v b/backend/Tunnelingproof.v
index 4f95ac9b..d3b8a9f0 100644
--- a/backend/Tunnelingproof.v
+++ b/backend/Tunnelingproof.v
@@ -441,6 +441,31 @@ Proof.
rewrite <- EV. apply eval_addressing_preserved. exact symbols_preserved.
eauto. eauto.
econstructor; eauto using locmap_set_lessdef, locmap_undef_regs_lessdef.
+- (* Lload notrap1 *)
+ exploit eval_addressing_lessdef_none. apply reglist_lessdef; eauto. eassumption.
+ left; simpl; econstructor; split.
+ eapply exec_Lload_notrap1.
+ rewrite <- H0.
+ apply eval_addressing_preserved. exact symbols_preserved. eauto.
+ econstructor; eauto using locmap_set_lessdef, locmap_undef_regs_lessdef.
+- (* Lload notrap2 *)
+ exploit eval_addressing_lessdef. apply reglist_lessdef; eauto. eauto.
+ intros (ta & EV & LD).
+ destruct (Mem.loadv chunk tm ta) eqn:Htload.
+ {
+ left; simpl; econstructor; split.
+ eapply exec_Lload.
+ rewrite <- EV. apply eval_addressing_preserved. exact symbols_preserved.
+ exact Htload. eauto.
+ econstructor; eauto using locmap_set_lessdef, locmap_undef_regs_lessdef.
+ }
+ {
+ left; simpl; econstructor; split.
+ eapply exec_Lload_notrap2.
+ rewrite <- EV. apply eval_addressing_preserved. exact symbols_preserved.
+ exact Htload. eauto.
+ econstructor; eauto using locmap_set_lessdef, locmap_undef_regs_lessdef.
+ }
- (* Lgetstack *)
left; simpl; econstructor; split.
econstructor; eauto.
diff --git a/backend/Unusedglob.v b/backend/Unusedglob.v
index 8ac7c4ce..93ca7af4 100644
--- a/backend/Unusedglob.v
+++ b/backend/Unusedglob.v
@@ -46,14 +46,14 @@ Definition ref_instruction (i: instruction) : list ident :=
match i with
| Inop _ => nil
| Iop op _ _ _ => globals_operation op
- | Iload _ addr _ _ _ => globals_addressing addr
+ | Iload _ _ addr _ _ _ => globals_addressing addr
| Istore _ addr _ _ _ => globals_addressing addr
| Icall _ (inl r) _ _ _ => nil
| Icall _ (inr id) _ _ _ => id :: nil
| Itailcall _ (inl r) _ => nil
| Itailcall _ (inr id) _ => id :: nil
| Ibuiltin _ args _ _ => globals_of_builtin_args args
- | Icond cond _ _ _ => nil
+ | Icond cond _ _ _ _ => nil
| Ijumptable _ _ => nil
| Ireturn _ => nil
end.
diff --git a/backend/Unusedglobproof.v b/backend/Unusedglobproof.v
index 680daba7..fa120b6d 100644
--- a/backend/Unusedglobproof.v
+++ b/backend/Unusedglobproof.v
@@ -915,7 +915,7 @@ Proof.
/\ Val.inject j a ta).
{ apply eval_addressing_inj with (ge1 := ge) (sp1 := Vptr sp0 Ptrofs.zero) (vl1 := rs##args).
intros. apply symbol_address_inject. eapply match_stacks_preserves_globals; eauto.
- apply KEPT. red. exists pc, (Iload chunk addr args dst pc'); auto.
+ apply KEPT. red. exists pc, (Iload trap chunk addr args dst pc'); auto.
econstructor; eauto.
apply regs_inject; auto.
assumption. }
@@ -924,6 +924,36 @@ Proof.
econstructor; split. eapply exec_Iload; eauto.
econstructor; eauto. apply set_reg_inject; auto.
+- (* load notrap1 *)
+ assert (eval_addressing tge (Vptr tsp Ptrofs.zero) addr trs##args = None).
+ { eapply eval_addressing_inj_none.
+ intros. apply symbol_address_inject. eapply match_stacks_preserves_globals; eauto.
+ apply KEPT. red. exists pc, (Iload NOTRAP chunk addr args dst pc'); auto.
+ econstructor; eauto.
+ rewrite Ptrofs.add_zero; reflexivity.
+ apply regs_inject; auto.
+ eassumption.
+ assumption. }
+
+ econstructor; split. eapply exec_Iload_notrap1; eauto.
+ econstructor; eauto. apply set_reg_inject; auto.
+
+- (* load notrap2 *)
+ assert (A: exists ta,
+ eval_addressing tge (Vptr tsp Ptrofs.zero) addr trs##args = Some ta
+ /\ Val.inject j a ta).
+ { apply eval_addressing_inj with (ge1 := ge) (sp1 := Vptr sp0 Ptrofs.zero) (vl1 := rs##args).
+ intros. apply symbol_address_inject. eapply match_stacks_preserves_globals; eauto.
+ apply KEPT. red. exists pc, (Iload NOTRAP chunk addr args dst pc'); auto.
+ econstructor; eauto.
+ apply regs_inject; auto.
+ assumption. }
+ destruct A as (ta & B & C).
+ destruct (Mem.loadv chunk tm ta) eqn:Echunk2.
+ + econstructor; split. eapply exec_Iload; eauto.
+ econstructor; eauto. apply set_reg_inject; auto.
+ + econstructor; split. eapply exec_Iload_notrap2; eauto.
+ econstructor; eauto. apply set_reg_inject; auto.
- (* store *)
assert (A: exists ta,
eval_addressing tge (Vptr tsp Ptrofs.zero) addr trs##args = Some ta
diff --git a/backend/ValueAnalysis.v b/backend/ValueAnalysis.v
index 2b233900..2e79d1a9 100644
--- a/backend/ValueAnalysis.v
+++ b/backend/ValueAnalysis.v
@@ -139,9 +139,14 @@ Definition transfer (f: function) (rm: romem) (pc: node) (ae: aenv) (am: amem) :
| Some(Iop op args res s) =>
let a := eval_static_operation op (aregs ae args) in
VA.State (AE.set res a ae) am
- | Some(Iload chunk addr args dst s) =>
+ | Some(Iload TRAP chunk addr args dst s) =>
let a := loadv chunk rm am (eval_static_addressing addr (aregs ae args)) in
VA.State (AE.set dst a ae) am
+
+ (* TODO: maybe a case analysis on the results of loadv? *)
+
+ | Some(Iload NOTRAP chunk addr args dst s) =>
+ VA.State (AE.set dst Vtop ae) am
| Some(Istore chunk addr args src s) =>
let am' := storev chunk am (eval_static_addressing addr (aregs ae args)) (areg ae src) in
VA.State ae am'
@@ -151,7 +156,7 @@ Definition transfer (f: function) (rm: romem) (pc: node) (ae: aenv) (am: amem) :
VA.Bot
| Some(Ibuiltin ef args res s) =>
transfer_builtin ae am rm ef args res
- | Some(Icond cond args s1 s2) =>
+ | Some(Icond cond args s1 s2 _) =>
VA.State ae am
| Some(Ijumptable arg tbl) =>
VA.State ae am
@@ -1039,9 +1044,8 @@ Proof.
red; simpl; intros. destruct (plt b (Mem.nextblock m)).
exploit RO; eauto. intros (R & P & Q).
split; auto.
- split. apply bmatch_incr with bc; auto. apply bmatch_inv with m; auto.
- intros. eapply Mem.loadbytes_unchanged_on_1. eapply external_call_readonly; eauto.
- auto. intros; red. apply Q.
+ split. apply bmatch_incr with bc; auto. apply bmatch_ext with m; auto.
+ intros. eapply external_call_readonly with (m2 := m'); eauto.
intros; red; intros; elim (Q ofs).
eapply external_call_max_perm with (m2 := m'); eauto.
destruct (j' b); congruence.
@@ -1268,11 +1272,29 @@ Proof.
apply ematch_update; auto. eapply eval_static_operation_sound; eauto with va.
- (* load *)
+ destruct trap.
+ + eapply sound_succ_state; eauto. simpl; auto.
+ unfold transfer; rewrite H. eauto.
+ apply ematch_update; auto. eapply loadv_sound; eauto with va.
+ eapply eval_static_addressing_sound; eauto with va.
+ + eapply sound_succ_state; eauto. simpl; auto.
+ unfold transfer; rewrite H. eauto.
+ apply ematch_update; auto.
+ eapply vmatch_top.
+ eapply loadv_sound; try eassumption.
+ eapply eval_static_addressing_sound; eauto with va.
+- (* load notrap1 *)
eapply sound_succ_state; eauto. simpl; auto.
unfold transfer; rewrite H. eauto.
- apply ematch_update; auto. eapply loadv_sound; eauto with va.
- eapply eval_static_addressing_sound; eauto with va.
-
+ apply ematch_update; auto.
+ unfold default_notrap_load_value.
+ constructor.
+- (* load notrap2 *)
+ eapply sound_succ_state; eauto. simpl; auto.
+ unfold transfer; rewrite H. eauto.
+ apply ematch_update; auto.
+ unfold default_notrap_load_value.
+ constructor.
- (* store *)
exploit eval_static_addressing_sound; eauto with va. intros VMADDR.
eapply sound_succ_state; eauto. simpl; auto.
diff --git a/backend/ValueDomain.v b/backend/ValueDomain.v
index c132ce7c..779e7bb9 100644
--- a/backend/ValueDomain.v
+++ b/backend/ValueDomain.v
@@ -3502,11 +3502,6 @@ Proof.
- omegaContradiction.
Qed.
-Lemma max_size_chunk: forall chunk, size_chunk chunk <= 8.
-Proof.
- destruct chunk; simpl; omega.
-Qed.
-
Remark inval_before_contents:
forall i c chunk' av' j,
(inval_before i (i - 7) c)##j = Some (ACval chunk' av') ->
diff --git a/backend/XTL.ml b/backend/XTL.ml
index f10efeed..1d8e89c0 100644
--- a/backend/XTL.ml
+++ b/backend/XTL.ml
@@ -30,13 +30,13 @@ type instruction =
| Xspill of var * var
| Xparmove of var list * var list * var * var
| Xop of operation * var list * var
- | Xload of memory_chunk * addressing * var list * var
+ | Xload of trapping_mode * memory_chunk * addressing * var list * var
| Xstore of memory_chunk * addressing * var list * var
| Xcall of signature * (var, ident) sum * var list * var list
| Xtailcall of signature * (var, ident) sum * var list
| Xbuiltin of external_function * var builtin_arg list * var builtin_res
| Xbranch of node
- | Xcond of condition * var list * node * node
+ | Xcond of condition * var list * node * node * bool option
| Xjumptable of var * node list
| Xreturn of var list
@@ -105,7 +105,7 @@ let twin_reg r =
let rec successors_block = function
| Xbranch s :: _ -> [s]
| Xtailcall(sg, vos, args) :: _ -> []
- | Xcond(cond, args, s1, s2) :: _ -> [s1; s2]
+ | Xcond(cond, args, s1, s2, _) :: _ -> [s1; s2]
| Xjumptable(arg, tbl) :: _ -> tbl
| Xreturn _:: _ -> []
| instr :: blk -> successors_block blk
@@ -159,7 +159,7 @@ let type_instr = function
let (targs, tres) = type_of_operation op in
set_vars_type args targs;
set_var_type res tres
- | Xload(chunk, addr, args, dst) ->
+ | Xload(trap, chunk, addr, args, dst) ->
set_vars_type args (type_of_addressing addr);
set_var_type dst (type_of_chunk chunk)
| Xstore(chunk, addr, args, src) ->
@@ -179,7 +179,7 @@ let type_instr = function
type_builtin_res res (proj_sig_res sg)
| Xbranch s ->
()
- | Xcond(cond, args, s1, s2) ->
+ | Xcond(cond, args, s1, s2, _) ->
set_vars_type args (type_of_condition cond)
| Xjumptable(arg, tbl) ->
set_var_type arg Tint
diff --git a/backend/XTL.mli b/backend/XTL.mli
index 54988d4b..7b7f7186 100644
--- a/backend/XTL.mli
+++ b/backend/XTL.mli
@@ -31,13 +31,13 @@ type instruction =
| Xspill of var * var
| Xparmove of var list * var list * var * var
| Xop of operation * var list * var
- | Xload of memory_chunk * addressing * var list * var
+ | Xload of trapping_mode * memory_chunk * addressing * var list * var
| Xstore of memory_chunk * addressing * var list * var
| Xcall of signature * (var, ident) sum * var list * var list
| Xtailcall of signature * (var, ident) sum * var list
| Xbuiltin of external_function * var builtin_arg list * var builtin_res
| Xbranch of node
- | Xcond of condition * var list * node * node
+ | Xcond of condition * var list * node * node * bool option
| Xjumptable of var * node list
| Xreturn of var list
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index dc25b516..bc5173ca 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -33,6 +33,7 @@ type inline_status =
type atom_info =
{ a_storage: C.storage; (* storage class *)
+ a_size: int64 option; (* size in bytes *)
a_alignment: int option; (* alignment *)
a_sections: Sections.section_name list; (* in which section to put it *)
(* 1 section for data, 3 sections (code/lit/jumptbl) for functions *)
@@ -61,15 +62,25 @@ let atom_alignof a =
with Not_found ->
None
+let atom_is_aligned a sz =
+ match atom_alignof a with
+ | None -> false
+ | Some align -> align mod (Z.to_int sz) = 0
+
let atom_sections a =
try
(Hashtbl.find decl_atom a).a_sections
with Not_found ->
[]
-let atom_is_small_data a ofs =
+let atom_is_small_data a ofs =
try
- (Hashtbl.find decl_atom a).a_access = Sections.Access_near
+ let info = Hashtbl.find decl_atom a in
+ info.a_access = Sections.Access_near
+ && (match info.a_size with
+ | None -> false
+ | Some sz ->
+ let ofs = camlint64_of_ptrofs ofs in 0L <= ofs && ofs < sz)
with Not_found ->
false
@@ -371,6 +382,7 @@ let name_for_string_literal s =
Hashtbl.add decl_atom id
{ a_storage = C.Storage_static;
a_alignment = Some 1;
+ a_size = Some (Int64.of_int (String.length s + 1));
a_sections = [Sections.for_stringlit()];
a_access = Sections.Access_default;
a_inline = No_specifier;
@@ -398,9 +410,12 @@ let name_for_wide_string_literal s =
incr stringNum;
let name = Printf.sprintf "__stringlit_%d" !stringNum in
let id = intern_string name in
+ let wchar_size = Machine.((!config).sizeof_wchar) in
Hashtbl.add decl_atom id
{ a_storage = C.Storage_static;
- a_alignment = Some Machine.((!config).sizeof_wchar);
+ a_alignment = Some wchar_size;
+ a_size = Some (Int64.(mul (of_int (List.length s + 1))
+ (of_int wchar_size)));
a_sections = [Sections.for_stringlit()];
a_access = Sections.Access_default;
a_inline = No_specifier;
@@ -1242,7 +1257,8 @@ let convertFundef loc env fd =
Hashtbl.add decl_atom id'
{ a_storage = fd.fd_storage;
a_alignment = None;
- a_sections = Sections.for_function env id' fd.fd_attrib;
+ a_size = None;
+ a_sections = Sections.for_function env loc id' fd.fd_attrib;
a_access = Sections.Access_default;
a_inline = inline;
a_loc = loc };
@@ -1327,7 +1343,7 @@ let convertGlobvar loc env (sto, id, ty, optinit) =
| Some i ->
convertInitializer env ty i in
let (section, access) =
- Sections.for_variable env id' ty (optinit <> None) in
+ Sections.for_variable env loc id' ty (optinit <> None) in
if Z.gt sz (Z.of_uint64 0xFFFF_FFFFL) then
error "'%s' is too big (%s bytes)"
id.name (Z.to_string sz);
@@ -1336,6 +1352,7 @@ let convertGlobvar loc env (sto, id, ty, optinit) =
Hashtbl.add decl_atom id'
{ a_storage = sto;
a_alignment = Some (Z.to_int al);
+ a_size = Some (Z.to_int64 sz);
a_sections = [section];
a_access = access;
a_inline = No_specifier;
diff --git a/cfrontend/Cexec.v b/cfrontend/Cexec.v
index 2942080b..b08c3ad7 100644
--- a/cfrontend/Cexec.v
+++ b/cfrontend/Cexec.v
@@ -460,6 +460,14 @@ Definition do_ef_free
check (zlt 0 (Ptrofs.unsigned sz));
do m' <- Mem.free m b (Ptrofs.unsigned lo - size_chunk Mptr) (Ptrofs.unsigned lo + Ptrofs.unsigned sz);
Some(w, E0, Vundef, m')
+ | Vint n :: nil =>
+ if Int.eq_dec n Int.zero && negb Archi.ptr64
+ then Some(w, E0, Vundef, m)
+ else None
+ | Vlong n :: nil =>
+ if Int64.eq_dec n Int64.zero && Archi.ptr64
+ then Some(w, E0, Vundef, m)
+ else None
| _ => None
end.
@@ -544,45 +552,51 @@ Proof with try congruence.
- eapply do_external_function_sound; eauto.
}
destruct ef; simpl.
-(* EF_external *)
+- (* EF_external *)
eapply do_external_function_sound; eauto.
-(* EF_builtin *)
+- (* EF_builtin *)
eapply BF_EX; eauto.
-(* EF_runtime *)
+- (* EF_runtime *)
eapply BF_EX; eauto.
-(* EF_vload *)
+- (* EF_vload *)
unfold do_ef_volatile_load. destruct vargs... destruct v... destruct vargs...
mydestr. destruct p as [[w'' t''] v]; mydestr.
exploit do_volatile_load_sound; eauto. intuition. econstructor; eauto.
- auto.
-(* EF_vstore *)
+- (* EF_vstore *)
unfold do_ef_volatile_store. destruct vargs... destruct v... destruct vargs... destruct vargs...
mydestr. destruct p as [[w'' t''] m'']. mydestr.
exploit do_volatile_store_sound; eauto. intuition. econstructor; eauto.
- auto.
-(* EF_malloc *)
+- (* EF_malloc *)
unfold do_ef_malloc. destruct vargs... destruct vargs... mydestr.
destruct (Mem.alloc m (- size_chunk Mptr) (Ptrofs.unsigned i)) as [m1 b] eqn:?. mydestr.
split. apply SIZE in Heqo. subst v. econstructor; eauto. constructor.
-(* EF_free *)
- unfold do_ef_free. destruct vargs... destruct v... destruct vargs...
- mydestr. split. apply SIZE in Heqo0. econstructor; eauto. congruence. omega. constructor.
-(* EF_memcpy *)
+- (* EF_free *)
+ unfold do_ef_free. destruct vargs... destruct v...
++ destruct vargs... mydestr; InvBooleans; subst i.
+ replace (Vint Int.zero) with Vnullptr. split; constructor.
+ apply negb_true_iff in H0. unfold Vnullptr; rewrite H0; auto.
++ destruct vargs... mydestr; InvBooleans; subst i.
+ replace (Vlong Int64.zero) with Vnullptr. split; constructor.
+ unfold Vnullptr; rewrite H0; auto.
++ destruct vargs... mydestr.
+ split. apply SIZE in Heqo0. econstructor; eauto. congruence. omega.
+ constructor.
+- (* EF_memcpy *)
unfold do_ef_memcpy. destruct vargs... destruct v... destruct vargs...
destruct v... destruct vargs... mydestr.
apply Decidable_sound in Heqb1. red in Heqb1.
split. econstructor; eauto; tauto. constructor.
-(* EF_annot *)
+- (* EF_annot *)
unfold do_ef_annot. mydestr.
split. constructor. apply list_eventval_of_val_sound; auto.
econstructor. constructor; eauto. constructor.
-(* EF_annot_val *)
+- (* EF_annot_val *)
unfold do_ef_annot_val. destruct vargs... destruct vargs... mydestr.
split. constructor. apply eventval_of_val_sound; auto.
econstructor. constructor; eauto. constructor.
-(* EF_inline_asm *)
+- (* EF_inline_asm *)
eapply do_inline_assembly_sound; eauto.
-(* EF_debug *)
+- (* EF_debug *)
unfold do_ef_debug. mydestr. split; constructor.
Qed.
@@ -605,37 +619,38 @@ Proof.
- eapply do_external_function_complete; eauto.
}
destruct ef; simpl in *.
-(* EF_external *)
+- (* EF_external *)
eapply do_external_function_complete; eauto.
-(* EF_builtin *)
+- (* EF_builtin *)
eapply BF_EX; eauto.
-(* EF_runtime *)
+- (* EF_runtime *)
eapply BF_EX; eauto.
-(* EF_vload *)
+- (* EF_vload *)
inv H; unfold do_ef_volatile_load.
exploit do_volatile_load_complete; eauto. intros EQ; rewrite EQ; auto.
-(* EF_vstore *)
+- (* EF_vstore *)
inv H; unfold do_ef_volatile_store.
exploit do_volatile_store_complete; eauto. intros EQ; rewrite EQ; auto.
-(* EF_malloc *)
+- (* EF_malloc *)
inv H; unfold do_ef_malloc.
inv H0. erewrite SIZE by eauto. rewrite H1, H2. auto.
-(* EF_free *)
+- (* EF_free *)
inv H; unfold do_ef_free.
- inv H0. rewrite H1. erewrite SIZE by eauto. rewrite zlt_true. rewrite H3. auto. omega.
-(* EF_memcpy *)
++ inv H0. rewrite H1. erewrite SIZE by eauto. rewrite zlt_true. rewrite H3. auto. omega.
++ inv H0. unfold Vnullptr; destruct Archi.ptr64; auto.
+- (* EF_memcpy *)
inv H; unfold do_ef_memcpy.
inv H0. rewrite Decidable_complete. rewrite H7; rewrite H8; auto.
red. tauto.
-(* EF_annot *)
+- (* EF_annot *)
inv H; unfold do_ef_annot. inv H0. inv H6. inv H4.
rewrite (list_eventval_of_val_complete _ _ _ H1). auto.
-(* EF_annot_val *)
+- (* EF_annot_val *)
inv H; unfold do_ef_annot_val. inv H0. inv H6. inv H4.
rewrite (eventval_of_val_complete _ _ _ H1). auto.
-(* EF_inline_asm *)
+- (* EF_inline_asm *)
eapply do_inline_assembly_complete; eauto.
-(* EF_debug *)
+- (* EF_debug *)
inv H. inv H0. reflexivity.
Qed.
diff --git a/cfrontend/Cop.v b/cfrontend/Cop.v
index aa73abb0..143e87a3 100644
--- a/cfrontend/Cop.v
+++ b/cfrontend/Cop.v
@@ -140,8 +140,8 @@ Definition classify_cast (tfrom tto: type) : classify_cast_cases :=
| Tfloat F64 _, Tfloat F32 _ => cast_case_s2f
| Tfloat F32 _, Tfloat F64 _ => cast_case_f2s
(* To pointer types *)
- | Tpointer _ _, Tint _ _ _ =>
- if Archi.ptr64 then cast_case_i2l Unsigned else cast_case_pointer
+ | Tpointer _ _, Tint _ si _ =>
+ if Archi.ptr64 then cast_case_i2l si else cast_case_pointer
| Tpointer _ _, Tlong _ _ =>
if Archi.ptr64 then cast_case_pointer else cast_case_l2i I32 Unsigned
| Tpointer _ _, (Tpointer _ _ | Tarray _ _ _ | Tfunction _ _ _) => cast_case_pointer
diff --git a/cfrontend/Csem.v b/cfrontend/Csem.v
index a76a14ba..6d2b470f 100644
--- a/cfrontend/Csem.v
+++ b/cfrontend/Csem.v
@@ -444,7 +444,7 @@ Lemma red_selection:
Proof.
intros. unfold Eselection.
set (t := typ_of_type ty).
- set (sg := mksignature (AST.Tint :: t :: t :: nil) (Some t) cc_default).
+ set (sg := mksignature (AST.Tint :: t :: t :: nil) t cc_default).
assert (LK: lookup_builtin_function "__builtin_sel"%string sg = Some (BI_standard (BI_select t))).
{ unfold sg, t; destruct ty as [ | ? ? ? | ? | [] ? | ? ? | ? ? ? | ? ? ? | ? ? | ? ? ];
simpl; unfold Tptr; destruct Archi.ptr64; reflexivity. }
diff --git a/cfrontend/Cshmgen.v b/cfrontend/Cshmgen.v
index 792a73f9..5bd12d00 100644
--- a/cfrontend/Cshmgen.v
+++ b/cfrontend/Cshmgen.v
@@ -23,6 +23,7 @@
Require Import Coqlib Maps Errors Integers Floats.
Require Import AST Linking.
Require Import Ctypes Cop Clight Cminor Csharpminor.
+Require Import Conventions1.
Local Open Scope string_scope.
Local Open Scope error_monad_scope.
@@ -558,6 +559,34 @@ Fixpoint typlist_of_arglist (al: list Clight.expr) (tyl: typelist)
typ_of_type (default_argument_conversion (typeof a1)) :: typlist_of_arglist a2 Tnil
end.
+(** Translate a function call.
+ Depending on the ABI, it may be necessary to normalize the value
+ returned by casting it to the return type of the function.
+ For example, in the x86 ABI, a return value of type "char" is
+ returned in register AL, leaving the top 24 bits of EAX
+ unspecified. Hence, a cast to type "char" is needed to sign- or
+ zero-extend the returned integer before using it. *)
+
+Definition make_normalization (t: type) (a: expr) :=
+ match t with
+ | Tint IBool _ _ => Eunop Ocast8unsigned a
+ | Tint I8 Signed _ => Eunop Ocast8signed a
+ | Tint I8 Unsigned _ => Eunop Ocast8unsigned a
+ | Tint I16 Signed _ => Eunop Ocast16signed a
+ | Tint I16 Unsigned _ => Eunop Ocast16unsigned a
+ | _ => a
+ end.
+
+Definition make_funcall (x: option ident) (tres: type) (sg: signature)
+ (fn: expr) (args: list expr): stmt :=
+ match x, return_value_needs_normalization sg.(sig_res) with
+ | Some id, true =>
+ Sseq (Scall x sg fn args)
+ (Sset id (make_normalization tres (Evar id)))
+ | _, _ =>
+ Scall x sg fn args
+ end.
+
(** * Translation of statements *)
(** [transl_statement nbrk ncnt s] returns a Csharpminor statement
@@ -601,10 +630,10 @@ Fixpoint transl_statement (ce: composite_env) (tyret: type) (nbrk ncnt: nat)
| fun_case_f args res cconv =>
do tb <- transl_expr ce b;
do tcl <- transl_arglist ce cl args;
- OK(Scall x {| sig_args := typlist_of_arglist cl args;
- sig_res := opttyp_of_type res;
- sig_cc := cconv |}
- tb tcl)
+ let sg := {| sig_args := typlist_of_arglist cl args;
+ sig_res := rettype_of_type res;
+ sig_cc := cconv |} in
+ OK (make_funcall x res sg tb tcl)
| _ => Error(msg "Cshmgen.transl_stmt(call)")
end
| Clight.Sbuiltin x ef tyargs bl =>
@@ -667,7 +696,7 @@ Definition transl_var (ce: composite_env) (v: ident * type) :=
Definition signature_of_function (f: Clight.function) :=
{| sig_args := map typ_of_type (map snd (Clight.fn_params f));
- sig_res := opttyp_of_type (Clight.fn_return f);
+ sig_res := rettype_of_type (Clight.fn_return f);
sig_cc := Clight.fn_callconv f |}.
Definition transl_function (ce: composite_env) (f: Clight.function) : res function :=
diff --git a/cfrontend/Cshmgenproof.v b/cfrontend/Cshmgenproof.v
index 09e31cb2..1ceb8e4d 100644
--- a/cfrontend/Cshmgenproof.v
+++ b/cfrontend/Cshmgenproof.v
@@ -15,7 +15,7 @@
Require Import Coqlib Errors Maps Integers Floats.
Require Import AST Linking.
Require Import Values Events Memory Globalenvs Smallstep.
-Require Import Ctypes Cop Clight Cminor Csharpminor.
+Require Import Ctypes Ctyping Cop Clight Cminor Csharpminor.
Require Import Cshmgen.
(** * Relational specification of the transformation *)
@@ -996,6 +996,26 @@ Proof.
eapply make_memcpy_correct with (b := b) (v := Vptr b' ofs'); eauto.
Qed.
+Lemma make_normalization_correct:
+ forall e le m a v t,
+ eval_expr ge e le m a v ->
+ wt_val v t ->
+ eval_expr ge e le m (make_normalization t a) v.
+Proof.
+ intros. destruct t; simpl; auto. inv H0.
+- destruct i; simpl in H3.
+ + destruct s; econstructor; eauto; simpl; congruence.
+ + destruct s; econstructor; eauto; simpl; congruence.
+ + auto.
+ + econstructor; eauto; simpl; congruence.
+- auto.
+- destruct i.
+ + destruct s; econstructor; eauto.
+ + destruct s; econstructor; eauto.
+ + auto.
+ + econstructor; eauto.
+Qed.
+
End CONSTRUCTORS.
(** * Basic preservation invariants *)
@@ -1360,7 +1380,16 @@ Inductive match_cont: composite_env -> type -> nat -> nat -> Clight.cont -> Csha
match_cont cu.(prog_comp_env) (Clight.fn_return f) nbrk' ncnt' k tk ->
match_cont ce tyret nbrk ncnt
(Clight.Kcall id f e le k)
- (Kcall id tf te le tk).
+ (Kcall id tf te le tk)
+ | match_Kcall_normalize: forall ce tyret nbrk ncnt nbrk' ncnt' f e k id a tf te le tk cu,
+ linkorder cu prog ->
+ transl_function cu.(prog_comp_env) f = OK tf ->
+ match_env e te ->
+ match_cont cu.(prog_comp_env) (Clight.fn_return f) nbrk' ncnt' k tk ->
+ (forall v e le m, wt_val v tyret -> le!id = Some v -> eval_expr tge e le m a v) ->
+ match_cont ce tyret nbrk ncnt
+ (Clight.Kcall (Some id) f e le k)
+ (Kcall (Some id) tf te le (Kseq (Sset id a) tk)).
Inductive match_states: Clight.state -> Csharpminor.state -> Prop :=
| match_state:
@@ -1377,14 +1406,15 @@ Inductive match_states: Clight.state -> Csharpminor.state -> Prop :=
forall fd args k m tfd tk targs tres cconv cu ce
(LINK: linkorder cu prog)
(TR: match_fundef cu fd tfd)
- (MK: match_cont ce Tvoid 0%nat 0%nat k tk)
+ (MK: match_cont ce tres 0%nat 0%nat k tk)
(ISCC: Clight.is_call_cont k)
(TY: type_of_fundef fd = Tfunction targs tres cconv),
match_states (Clight.Callstate fd args k m)
(Callstate tfd args tk m)
| match_returnstate:
- forall res k m tk ce
- (MK: match_cont ce Tvoid 0%nat 0%nat k tk),
+ forall res tres k m tk ce
+ (MK: match_cont ce tres 0%nat 0%nat k tk)
+ (WT: wt_val res tres),
match_states (Clight.Returnstate res k m)
(Returnstate res tk m).
@@ -1442,7 +1472,9 @@ Proof.
- (* set *)
auto.
- (* call *)
- simpl in TR. destruct (classify_fun (typeof e)); monadInv TR. auto.
+ simpl in TR. destruct (classify_fun (typeof e)); monadInv TR.
+ unfold make_funcall.
+ destruct o; auto; destruct Conventions1.return_value_needs_normalization; auto.
- (* builtin *)
auto.
- (* seq *)
@@ -1500,24 +1532,26 @@ End FIND_LABEL.
(** Properties of call continuations *)
Lemma match_cont_call_cont:
- forall ce' tyret' nbrk' ncnt' ce tyret nbrk ncnt k tk,
+ forall ce' nbrk' ncnt' ce tyret nbrk ncnt k tk,
match_cont ce tyret nbrk ncnt k tk ->
- match_cont ce' tyret' nbrk' ncnt' (Clight.call_cont k) (call_cont tk).
+ match_cont ce' tyret nbrk' ncnt' (Clight.call_cont k) (call_cont tk).
Proof.
induction 1; simpl; auto.
- constructor.
- econstructor; eauto.
+- apply match_Kstop.
+- eapply match_Kcall; eauto.
+- eapply match_Kcall_normalize; eauto.
Qed.
Lemma match_cont_is_call_cont:
- forall ce tyret nbrk ncnt k tk ce' tyret' nbrk' ncnt',
+ forall ce tyret nbrk ncnt k tk ce' nbrk' ncnt',
match_cont ce tyret nbrk ncnt k tk ->
Clight.is_call_cont k ->
- match_cont ce' tyret' nbrk' ncnt' k tk /\ is_call_cont tk.
+ match_cont ce' tyret nbrk' ncnt' k tk /\ is_call_cont tk.
Proof.
intros. inv H; simpl in H0; try contradiction; simpl.
- split; auto; constructor.
- split; auto; econstructor; eauto.
+ split; auto; apply match_Kstop.
+ split; auto; eapply match_Kcall; eauto.
+ split; auto; eapply match_Kcall_normalize; eauto.
Qed.
(** The simulation proof *)
@@ -1549,19 +1583,44 @@ Proof.
- (* call *)
revert TR. simpl. case_eq (classify_fun (typeof a)); try congruence.
- intros targs tres cc CF TR. monadInv TR. inv MTR.
+ intros targs tres cc CF TR. monadInv TR.
exploit functions_translated; eauto. intros (cu' & tfd & FIND & TFD & LINK').
rewrite H in CF. simpl in CF. inv CF.
- econstructor; split.
- apply plus_one. econstructor; eauto.
- eapply transl_expr_correct with (cunit := cu); eauto.
- eapply transl_arglist_correct with (cunit := cu); eauto.
- erewrite typlist_of_arglist_eq by eauto.
- eapply transl_fundef_sig1; eauto.
- rewrite H3. auto.
- econstructor; eauto.
- eapply match_Kcall with (ce := prog_comp_env cu') (cu := cu); eauto.
- simpl. auto.
+ set (sg := {| sig_args := typlist_of_arglist al targs;
+ sig_res := rettype_of_type tres;
+ sig_cc := cc |}) in *.
+ assert (SIG: funsig tfd = sg).
+ { unfold sg; erewrite typlist_of_arglist_eq by eauto.
+ eapply transl_fundef_sig1; eauto. rewrite H3; auto. }
+ assert (EITHER: tk' = tk /\ ts' = Scall optid sg x x0
+ \/ exists id, optid = Some id /\
+ tk' = tk /\ ts' = Sseq (Scall optid sg x x0)
+ (Sset id (make_normalization tres (Evar id)))).
+ { unfold make_funcall in MTR.
+ destruct optid. destruct Conventions1.return_value_needs_normalization.
+ inv MTR. right; exists i; auto.
+ inv MTR; auto.
+ inv MTR; auto. }
+ destruct EITHER as [(EK & ES) | (id & EI & EK & ES)]; rewrite EK, ES.
+ + (* without normalization of return value *)
+ econstructor; split.
+ apply plus_one. eapply step_call; eauto.
+ eapply transl_expr_correct with (cunit := cu); eauto.
+ eapply transl_arglist_correct with (cunit := cu); eauto.
+ econstructor; eauto.
+ eapply match_Kcall with (ce := prog_comp_env cu') (cu := cu); eauto.
+ exact I.
+ + (* with normalization of return value *)
+ subst optid.
+ econstructor; split.
+ eapply plus_two. apply step_seq. eapply step_call; eauto.
+ eapply transl_expr_correct with (cunit := cu); eauto.
+ eapply transl_arglist_correct with (cunit := cu); eauto.
+ traceEq.
+ econstructor; eauto.
+ eapply match_Kcall_normalize with (ce := prog_comp_env cu') (cu := cu); eauto.
+ intros. eapply make_normalization_correct; eauto. constructor; eauto.
+ exact I.
- (* builtin *)
monadInv TR. inv MTR.
@@ -1658,6 +1717,7 @@ Proof.
eapply match_env_free_blocks; eauto.
eapply match_returnstate with (ce := prog_comp_env cu); eauto.
eapply match_cont_call_cont. eauto.
+ constructor.
- (* return some *)
monadInv TR. inv MTR.
@@ -1667,6 +1727,7 @@ Proof.
eapply match_env_free_blocks; eauto.
eapply match_returnstate with (ce := prog_comp_env cu); eauto.
eapply match_cont_call_cont. eauto.
+ apply wt_val_casted. eapply cast_val_is_casted; eauto.
- (* skip call *)
monadInv TR. inv MTR.
@@ -1675,6 +1736,7 @@ Proof.
apply plus_one. apply step_skip_call. auto.
eapply match_env_free_blocks; eauto.
eapply match_returnstate with (ce := prog_comp_env cu); eauto.
+ constructor.
- (* switch *)
monadInv TR.
@@ -1738,20 +1800,33 @@ Proof.
simpl. econstructor; eauto.
unfold transl_function. rewrite EQ; simpl. rewrite EQ1; simpl. auto.
constructor.
+ replace (fn_return f) with tres. eassumption.
+ simpl in TY. unfold type_of_function in TY. congruence.
- (* external function *)
inv TR.
exploit match_cont_is_call_cont; eauto. intros [A B].
econstructor; split.
- apply plus_one. constructor. eauto.
+ apply plus_one. constructor.
eapply external_call_symbols_preserved; eauto. apply senv_preserved.
eapply match_returnstate with (ce := ce); eauto.
+ apply has_rettype_wt_val.
+ replace (rettype_of_type tres0) with (sig_res (ef_sig ef)).
+ eapply external_call_well_typed_gen; eauto.
+ rewrite H5. simpl. simpl in TY. congruence.
- (* returnstate *)
inv MK.
- econstructor; split.
- apply plus_one. constructor.
- econstructor; eauto. simpl; reflexivity. constructor.
+ + (* without normalization *)
+ econstructor; split.
+ apply plus_one. constructor.
+ econstructor; eauto. simpl; reflexivity. constructor.
+ + (* with normalization *)
+ econstructor; split.
+ eapply plus_three. econstructor. econstructor. constructor.
+ simpl. apply H13. eauto. apply PTree.gss.
+ traceEq.
+ simpl. rewrite PTree.set2. econstructor; eauto. simpl; reflexivity. constructor.
Qed.
Lemma transl_initial_states:
diff --git a/cfrontend/Csyntax.v b/cfrontend/Csyntax.v
index c34a5e13..e3e2c1e9 100644
--- a/cfrontend/Csyntax.v
+++ b/cfrontend/Csyntax.v
@@ -106,7 +106,7 @@ Definition Epreincr (id: incr_or_decr) (l: expr) (ty: type) :=
Definition Eselection (r1 r2 r3: expr) (ty: type) :=
let t := typ_of_type ty in
- let sg := mksignature (AST.Tint :: t :: t :: nil) (Some t) cc_default in
+ let sg := mksignature (AST.Tint :: t :: t :: nil) t cc_default in
Ebuiltin (EF_builtin "__builtin_sel"%string sg)
(Tcons type_bool (Tcons ty (Tcons ty Tnil)))
(Econs r1 (Econs r2 (Econs r3 Enil)))
diff --git a/cfrontend/Ctypes.v b/cfrontend/Ctypes.v
index bfc5daa9..664a60c5 100644
--- a/cfrontend/Ctypes.v
+++ b/cfrontend/Ctypes.v
@@ -732,8 +732,21 @@ Definition typ_of_type (t: type) : AST.typ :=
| Tpointer _ _ | Tarray _ _ _ | Tfunction _ _ _ | Tstruct _ _ | Tunion _ _ => AST.Tptr
end.
-Definition opttyp_of_type (t: type) : option AST.typ :=
- if type_eq t Tvoid then None else Some (typ_of_type t).
+Definition rettype_of_type (t: type) : AST.rettype :=
+ match t with
+ | Tvoid => AST.Tvoid
+ | Tint I32 _ _ => AST.Tint
+ | Tint I8 Signed _ => AST.Tint8signed
+ | Tint I8 Unsigned _ => AST.Tint8unsigned
+ | Tint I16 Signed _ => AST.Tint16signed
+ | Tint I16 Unsigned _ => AST.Tint16unsigned
+ | Tint IBool _ _ => AST.Tint8unsigned
+ | Tlong _ _ => AST.Tlong
+ | Tfloat F32 _ => AST.Tsingle
+ | Tfloat F64 _ => AST.Tfloat
+ | Tpointer _ _ => AST.Tptr
+ | Tarray _ _ _ | Tfunction _ _ _ | Tstruct _ _ | Tunion _ _ => AST.Tvoid
+ end.
Fixpoint typlist_of_typelist (tl: typelist) : list AST.typ :=
match tl with
@@ -742,7 +755,7 @@ Fixpoint typlist_of_typelist (tl: typelist) : list AST.typ :=
end.
Definition signature_of_type (args: typelist) (res: type) (cc: calling_convention): signature :=
- mksignature (typlist_of_typelist args) (opttyp_of_type res) cc.
+ mksignature (typlist_of_typelist args) (rettype_of_type res) cc.
(** * Construction of the composite environment *)
diff --git a/cfrontend/Ctyping.v b/cfrontend/Ctyping.v
index b92a9bac..00fcf8ab 100644
--- a/cfrontend/Ctyping.v
+++ b/cfrontend/Ctyping.v
@@ -397,10 +397,10 @@ Inductive wt_rvalue : expr -> Prop :=
wt_arguments rargs tyargs ->
(* This typing rule is specialized to the builtin invocations generated
by C2C, which are either __builtin_sel or builtins returning void. *)
- (ty = Tvoid /\ sig_res (ef_sig ef) = None)
+ (ty = Tvoid /\ sig_res (ef_sig ef) = AST.Tvoid)
\/ (tyargs = Tcons type_bool (Tcons ty (Tcons ty Tnil))
/\ let t := typ_of_type ty in
- let sg := mksignature (AST.Tint :: t :: t :: nil) (Some t) cc_default in
+ let sg := mksignature (AST.Tint :: t :: t :: nil) t cc_default in
ef = EF_builtin "__builtin_sel"%string sg) ->
wt_rvalue (Ebuiltin ef tyargs rargs ty)
| wt_Eparen: forall r tycast ty,
@@ -521,11 +521,20 @@ Fixpoint bind_globdef (e: typenv) (l: list (ident * globdef fundef type)) : type
| (id, Gvar v) :: l => bind_globdef (PTree.set id v.(gvar_info) e) l
end.
+Inductive wt_fundef (ce: composite_env) (e: typenv) : fundef -> Prop :=
+ | wt_fundef_internal: forall f,
+ wt_function ce e f ->
+ wt_fundef ce e (Internal f)
+ | wt_fundef_external: forall ef targs tres cc,
+ (ef_sig ef).(sig_res) = rettype_of_type tres ->
+ wt_fundef ce e (External ef targs tres cc).
+
Inductive wt_program : program -> Prop :=
| wt_program_intro: forall p,
let e := bind_globdef (PTree.empty _) p.(prog_defs) in
- (forall id f, In (id, Gfun (Internal f)) p.(prog_defs) ->
- wt_function p.(prog_comp_env) e f) ->
+ (forall id fd,
+ In (id, Gfun fd) p.(prog_defs) ->
+ wt_fundef p.(prog_comp_env) e fd) ->
wt_program p.
Hint Constructors wt_val wt_rvalue wt_lvalue wt_stmt wt_lblstmts: ty.
@@ -745,7 +754,7 @@ Definition ebuiltin (ef: external_function) (tyargs: typelist) (args: exprlist)
do x1 <- check_rvals args;
do x2 <- check_arguments args tyargs;
if type_eq tyres Tvoid
- && opt_typ_eq (sig_res (ef_sig ef)) None
+ && AST.rettype_eq (sig_res (ef_sig ef)) AST.Tvoid
then OK (Ebuiltin ef tyargs args tyres)
else Error (msg "builtin: wrong type decoration").
@@ -915,7 +924,8 @@ Definition retype_function (ce: composite_env) (e: typenv) (f: function) : res f
Definition retype_fundef (ce: composite_env) (e: typenv) (fd: fundef) : res fundef :=
match fd with
| Internal f => do f' <- retype_function ce e f; OK (Internal f')
- | External id args res cc => OK fd
+ | External ef args res cc =>
+ assertion (rettype_eq (ef_sig ef).(sig_res) (rettype_of_type res)); OK fd
end.
Definition typecheck_program (p: program) : res program :=
@@ -987,6 +997,7 @@ Proof.
classify_cast (Tint i s a) t2 <> cast_case_default).
{
unfold classify_cast. destruct t2; try congruence. destruct f; congruence.
+ destruct Archi.ptr64; congruence.
}
destruct i; auto.
Qed.
@@ -1240,7 +1251,7 @@ Lemma ebuiltin_sound:
Proof.
intros. monadInv H.
destruct (type_eq tyres Tvoid); simpl in EQ2; try discriminate.
- destruct (opt_typ_eq (sig_res (ef_sig ef)) None); inv EQ2.
+ destruct (rettype_eq (sig_res (ef_sig ef)) AST.Tvoid); inv EQ2.
econstructor; eauto. eapply check_arguments_sound; eauto.
Qed.
@@ -1372,6 +1383,14 @@ Proof.
intros. monadInv H. constructor; simpl. eapply retype_stmt_sound; eauto.
Qed.
+Lemma retype_fundef_sound:
+ forall ce e fd fd', retype_fundef ce e fd = OK fd' -> wt_fundef ce e fd'.
+Proof.
+ intros. destruct fd; monadInv H.
+- constructor; eapply retype_function_sound; eauto.
+- constructor; auto.
+Qed.
+
Theorem typecheck_program_sound:
forall p p', typecheck_program p = OK p' -> wt_program p'.
Proof.
@@ -1394,11 +1413,11 @@ Proof.
inv H1. simpl. auto.
}
rewrite ENVS.
- intros id f. revert MATCH; generalize (prog_defs p) (AST.prog_defs tp).
+ intros id fd. revert MATCH; generalize (prog_defs p) (AST.prog_defs tp).
induction 1; simpl; intros.
contradiction.
destruct H0; auto. subst b1; inv H. simpl in H1. inv H1.
- destruct f1; monadInv H4. eapply retype_function_sound; eauto.
+ eapply retype_fundef_sound; eauto.
Qed.
(** * Subject reduction *)
@@ -1710,6 +1729,26 @@ Proof.
inv H; auto.
Qed.
+Lemma has_rettype_wt_val:
+ forall v ty,
+ Val.has_rettype v (rettype_of_type ty) -> wt_val v ty.
+Proof.
+ unfold rettype_of_type, Val.has_rettype, Val.has_type; destruct ty; intros.
+- destruct v; contradiction || constructor.
+- destruct i.
+ + destruct s; destruct v; try contradiction; constructor; red; auto.
+ + destruct s; destruct v; try contradiction; constructor; red; auto.
+ + destruct v; try contradiction; constructor; auto.
+ + destruct v; try contradiction; constructor; red; auto.
+- destruct v; try contradiction; constructor; auto.
+- destruct f; destruct v; try contradiction; constructor.
+- unfold Tptr in *; destruct v; destruct Archi.ptr64 eqn:P64; try contradiction; constructor; auto.
+- destruct v; contradiction || constructor.
+- destruct v; contradiction || constructor.
+- destruct v; contradiction || constructor.
+- destruct v; contradiction || constructor.
+Qed.
+
Lemma wt_rred:
forall ge tenv a m t a' m',
rred ge a m t a' m' -> wt_rvalue ge tenv a -> wt_rvalue ge tenv a'.
@@ -1749,7 +1788,7 @@ Proof.
- (* builtin *) subst. destruct H7 as [(A & B) | (A & B)].
+ subst ty. auto with ty.
+ simpl in B. set (T := typ_of_type ty) in *.
- set (sg := mksignature (AST.Tint :: T :: T :: nil) (Some T) cc_default) in *.
+ set (sg := mksignature (AST.Tint :: T :: T :: nil) T cc_default) in *.
assert (LK: lookup_builtin_function "__builtin_sel"%string sg = Some (BI_standard (BI_select T))).
{ unfold sg, T; destruct ty as [ | ? ? ? | ? | [] ? | ? ? | ? ? ? | ? ? ? | ? ? | ? ? ];
simpl; unfold Tptr; destruct Archi.ptr64; reflexivity. }
@@ -1895,12 +1934,6 @@ Hypothesis WTPROG: wt_program prog.
Let ge := globalenv prog.
Let gtenv := bind_globdef (PTree.empty _) prog.(prog_defs).
-Hypothesis WT_EXTERNAL:
- forall id ef args res cc vargs m t vres m',
- In (id, Gfun (External ef args res cc)) prog.(prog_defs) ->
- external_call ef ge vargs m t vres m' ->
- wt_val vres res.
-
Inductive wt_expr_cont: typenv -> function -> cont -> Prop :=
| wt_Kdo: forall te f k,
wt_stmt_cont te f k ->
@@ -1999,12 +2032,6 @@ Proof.
induction 1; simpl; auto; econstructor; eauto.
Qed.
-Definition wt_fundef (fd: fundef) :=
- match fd with
- | Internal f => wt_function ge gtenv f
- | External ef targs tres cc => True
- end.
-
Definition fundef_return (fd: fundef) : type :=
match fd with
| Internal f => f.(fn_return)
@@ -2012,10 +2039,10 @@ Definition fundef_return (fd: fundef) : type :=
end.
Lemma wt_find_funct:
- forall v fd, Genv.find_funct ge v = Some fd -> wt_fundef fd.
+ forall v fd, Genv.find_funct ge v = Some fd -> wt_fundef ge gtenv fd.
Proof.
intros. apply Genv.find_funct_prop with (p := prog) (v := v); auto.
- intros. inv WTPROG. destruct f; simpl; auto. apply H1 with id; auto.
+ intros. inv WTPROG. apply H1 with id; auto.
Qed.
Inductive wt_state: state -> Prop :=
@@ -2031,7 +2058,7 @@ Inductive wt_state: state -> Prop :=
wt_state (ExprState f r k e m)
| wt_call_state: forall b fd vargs k m
(WTK: wt_call_cont k (fundef_return fd))
- (WTFD: wt_fundef fd)
+ (WTFD: wt_fundef ge gtenv fd)
(FIND: Genv.find_funct ge b = Some fd),
wt_state (Callstate fd vargs k m)
| wt_return_state: forall v k m ty
@@ -2088,7 +2115,6 @@ Qed.
End WT_FIND_LABEL.
-
Lemma preservation_estep:
forall S t S', estep ge S t S' -> wt_state S -> wt_state S'.
Proof.
@@ -2163,9 +2189,10 @@ Proof.
- inv WTS; eauto with ty.
- exploit wt_find_label. eexact WTB. eauto. eapply call_cont_wt'; eauto.
intros [A B]. eauto with ty.
-- simpl in WTFD; inv WTFD. econstructor; eauto. apply wt_call_cont_stmt_cont; auto.
-- exploit (Genv.find_funct_inversion prog); eauto. intros (id & A).
- econstructor; eauto.
+- inv WTFD. inv H3. econstructor; eauto. apply wt_call_cont_stmt_cont; auto.
+- inv WTFD. econstructor; eauto.
+ apply has_rettype_wt_val. simpl; rewrite <- H1.
+ eapply external_call_well_typed_gen; eauto.
- inv WTK. eauto with ty.
Qed.
@@ -2180,7 +2207,7 @@ Theorem wt_initial_state:
Proof.
intros. inv H. econstructor. constructor.
apply Genv.find_funct_ptr_prop with (p := prog) (b := b); auto.
- intros. inv WTPROG. destruct f0; simpl; auto. apply H4 with id; auto.
+ intros. inv WTPROG. apply H4 with id; auto.
instantiate (1 := (Vptr b Ptrofs.zero)). rewrite Genv.find_funct_find_funct_ptr. auto.
Qed.
diff --git a/cfrontend/PrintCsyntax.ml b/cfrontend/PrintCsyntax.ml
index 1c9729c5..03dc5837 100644
--- a/cfrontend/PrintCsyntax.ml
+++ b/cfrontend/PrintCsyntax.ml
@@ -19,7 +19,7 @@ open Format
open Camlcoq
open Values
open AST
-open Ctypes
+open! Ctypes
open Cop
open Csyntax
@@ -85,7 +85,7 @@ let name_optid id =
let rec name_cdecl id ty =
match ty with
- | Tvoid ->
+ | Ctypes.Tvoid ->
"void" ^ name_optid id
| Ctypes.Tint(sz, sg, a) ->
name_inttype sz sg ^ attributes a ^ name_optid id
diff --git a/common/AST.v b/common/AST.v
index 7ffe355d..eb34d675 100644
--- a/common/AST.v
+++ b/common/AST.v
@@ -45,9 +45,6 @@ Lemma typ_eq: forall (t1 t2: typ), {t1=t2} + {t1<>t2}.
Proof. decide equality. Defined.
Global Opaque typ_eq.
-Definition opt_typ_eq: forall (t1 t2: option typ), {t1=t2} + {t1<>t2}
- := option_eq typ_eq.
-
Definition list_typ_eq: forall (l1 l2: list typ), {l1=l2} + {l1<>l2}
:= list_eq_dec typ_eq.
@@ -91,10 +88,34 @@ Fixpoint subtype_list (tyl1 tyl2: list typ) : bool :=
| _, _ => false
end.
+(** To describe the values returned by functions, we use the more precise
+ types below. *)
+
+Inductive rettype : Type :=
+ | Tret (t: typ) (**r like type [t] *)
+ | Tint8signed (**r 8-bit signed integer *)
+ | Tint8unsigned (**r 8-bit unsigned integer *)
+ | Tint16signed (**r 16-bit signed integer *)
+ | Tint16unsigned (**r 16-bit unsigned integer *)
+ | Tvoid. (**r no value returned *)
+
+Coercion Tret: typ >-> rettype.
+
+Lemma rettype_eq: forall (t1 t2: rettype), {t1=t2} + {t1<>t2}.
+Proof. generalize typ_eq; decide equality. Defined.
+Global Opaque rettype_eq.
+
+Fixpoint proj_rettype (r: rettype) : typ :=
+ match r with
+ | Tret t => t
+ | Tint8signed | Tint8unsigned | Tint16signed | Tint16unsigned => Tint
+ | Tvoid => Tint
+ end.
+
(** Additionally, function definitions and function calls are annotated
by function signatures indicating:
- the number and types of arguments;
-- the type of the returned value, if any;
+- the type of the returned value;
- additional information on which calling convention to use.
These signatures are used in particular to determine appropriate
@@ -117,24 +138,20 @@ Global Opaque calling_convention_eq.
Record signature : Type := mksignature {
sig_args: list typ;
- sig_res: option typ;
+ sig_res: rettype;
sig_cc: calling_convention
}.
-Definition proj_sig_res (s: signature) : typ :=
- match s.(sig_res) with
- | None => Tint
- | Some t => t
- end.
+Definition proj_sig_res (s: signature) : typ := proj_rettype s.(sig_res).
Definition signature_eq: forall (s1 s2: signature), {s1=s2} + {s1<>s2}.
Proof.
- generalize opt_typ_eq, list_typ_eq, calling_convention_eq; decide equality.
+ generalize rettype_eq, list_typ_eq, calling_convention_eq; decide equality.
Defined.
Global Opaque signature_eq.
Definition signature_main :=
- {| sig_args := nil; sig_res := Some Tint; sig_cc := cc_default |}.
+ {| sig_args := nil; sig_res := Tint; sig_cc := cc_default |}.
(** Memory accesses (load and store instructions) are annotated by
a ``memory chunk'' indicating the type, size and signedness of the
@@ -177,6 +194,28 @@ Definition type_of_chunk (c: memory_chunk) : typ :=
Lemma type_of_Mptr: type_of_chunk Mptr = Tptr.
Proof. unfold Mptr, Tptr; destruct Archi.ptr64; auto. Qed.
+(** Same, as a return type. *)
+
+Definition rettype_of_chunk (c: memory_chunk) : rettype :=
+ match c with
+ | Mint8signed => Tint8signed
+ | Mint8unsigned => Tint8unsigned
+ | Mint16signed => Tint16signed
+ | Mint16unsigned => Tint16unsigned
+ | Mint32 => Tint
+ | Mint64 => Tlong
+ | Mfloat32 => Tsingle
+ | Mfloat64 => Tfloat
+ | Many32 => Tany32
+ | Many64 => Tany64
+ end.
+
+Lemma proj_rettype_of_chunk:
+ forall chunk, proj_rettype (rettype_of_chunk chunk) = type_of_chunk chunk.
+Proof.
+ destruct chunk; auto.
+Qed.
+
(** The chunk that is appropriate to store and reload a value of
the given type, without losing information. *)
@@ -193,6 +232,16 @@ Definition chunk_of_type (ty: typ) :=
Lemma chunk_of_Tptr: chunk_of_type Tptr = Mptr.
Proof. unfold Mptr, Tptr; destruct Archi.ptr64; auto. Qed.
+(** Trapping mode: does undefined behavior result in a trap or an undefined value (e.g. for loads) *)
+Inductive trapping_mode : Type := TRAP | NOTRAP.
+
+Definition trapping_mode_eq : forall x y : trapping_mode,
+ { x=y } + { x <> y}.
+Proof.
+ decide equality.
+Defined.
+
+
(** Initialization data for global variables. *)
Inductive init_data: Type :=
@@ -477,15 +526,15 @@ Definition ef_sig (ef: external_function): signature :=
| EF_external name sg => sg
| EF_builtin name sg => sg
| EF_runtime name sg => sg
- | EF_vload chunk => mksignature (Tptr :: nil) (Some (type_of_chunk chunk)) cc_default
- | EF_vstore chunk => mksignature (Tptr :: type_of_chunk chunk :: nil) None cc_default
- | EF_malloc => mksignature (Tptr :: nil) (Some Tptr) cc_default
- | EF_free => mksignature (Tptr :: nil) None cc_default
- | EF_memcpy sz al => mksignature (Tptr :: Tptr :: nil) None cc_default
- | EF_annot kind text targs => mksignature targs None cc_default
- | EF_annot_val kind text targ => mksignature (targ :: nil) (Some targ) cc_default
+ | EF_vload chunk => mksignature (Tptr :: nil) (rettype_of_chunk chunk) cc_default
+ | EF_vstore chunk => mksignature (Tptr :: type_of_chunk chunk :: nil) Tvoid cc_default
+ | EF_malloc => mksignature (Tptr :: nil) Tptr cc_default
+ | EF_free => mksignature (Tptr :: nil) Tvoid cc_default
+ | EF_memcpy sz al => mksignature (Tptr :: Tptr :: nil) Tvoid cc_default
+ | EF_annot kind text targs => mksignature targs Tvoid cc_default
+ | EF_annot_val kind text targ => mksignature (targ :: nil) targ cc_default
| EF_inline_asm text sg clob => sg
- | EF_debug kind text targs => mksignature targs None cc_default
+ | EF_debug kind text targs => mksignature targs Tvoid cc_default
end.
(** Whether an external function should be inlined by the compiler. *)
diff --git a/common/Builtins.v b/common/Builtins.v
index c9097e86..476b541e 100644
--- a/common/Builtins.v
+++ b/common/Builtins.v
@@ -29,7 +29,7 @@ Definition builtin_function_sig (b: builtin_function) : signature :=
| BI_platform b => platform_builtin_sig b
end.
-Definition builtin_function_sem (b: builtin_function) : builtin_sem (proj_sig_res (builtin_function_sig b)) :=
+Definition builtin_function_sem (b: builtin_function) : builtin_sem (sig_res (builtin_function_sig b)) :=
match b with
| BI_standard b => standard_builtin_sem b
| BI_platform b => platform_builtin_sem b
diff --git a/common/Builtins0.v b/common/Builtins0.v
index b78006dd..8da98314 100644
--- a/common/Builtins0.v
+++ b/common/Builtins0.v
@@ -26,8 +26,8 @@ Require Import AST Integers Floats Values Memdata.
appropriate for the target.
*)
-Definition val_opt_has_type (ov: option val) (t: typ) : Prop :=
- match ov with Some v => Val.has_type v t | None => True end.
+Definition val_opt_has_rettype (ov: option val) (t: rettype) : Prop :=
+ match ov with Some v => Val.has_rettype v t | None => True end.
Definition val_opt_inject (j: meminj) (ov ov': option val) : Prop :=
match ov, ov' with
@@ -42,10 +42,10 @@ Definition val_opt_inject (j: meminj) (ov ov': option val) : Prop :=
and be compatible with value injections.
*)
-Record builtin_sem (tret: typ) : Type := mkbuiltin {
+Record builtin_sem (tret: rettype) : Type := mkbuiltin {
bs_sem :> list val -> option val;
bs_well_typed: forall vl,
- val_opt_has_type (bs_sem vl) tret;
+ val_opt_has_rettype (bs_sem vl) tret;
bs_inject: forall j vl vl',
Val.inject_list j vl vl' -> val_opt_inject j (bs_sem vl) (bs_sem vl')
}.
@@ -60,8 +60,8 @@ Record builtin_sem (tret: typ) : Type := mkbuiltin {
Local Unset Program Cases.
Program Definition mkbuiltin_v1t
- (tret: typ) (f: val -> val)
- (WT: forall v1, Val.has_type (f v1) tret)
+ (tret: rettype) (f: val -> val)
+ (WT: forall v1, Val.has_rettype (f v1) tret)
(INJ: forall j v1 v1', Val.inject j v1 v1' -> Val.inject j (f v1) (f v1')) :=
mkbuiltin tret (fun vl => match vl with v1 :: nil => Some (f v1) | _ => None end) _ _.
Next Obligation.
@@ -72,8 +72,8 @@ Next Obligation.
Qed.
Program Definition mkbuiltin_v2t
- (tret: typ) (f: val -> val -> val)
- (WT: forall v1 v2, Val.has_type (f v1 v2) tret)
+ (tret: rettype) (f: val -> val -> val)
+ (WT: forall v1 v2, Val.has_rettype (f v1 v2) tret)
(INJ: forall j v1 v1' v2 v2',
Val.inject j v1 v1' -> Val.inject j v2 v2' ->
Val.inject j (f v1 v2) (f v1' v2')) :=
@@ -86,8 +86,8 @@ Next Obligation.
Qed.
Program Definition mkbuiltin_v3t
- (tret: typ) (f: val -> val -> val -> val)
- (WT: forall v1 v2 v3, Val.has_type (f v1 v2 v3) tret)
+ (tret: rettype) (f: val -> val -> val -> val)
+ (WT: forall v1 v2 v3, Val.has_rettype (f v1 v2 v3) tret)
(INJ: forall j v1 v1' v2 v2' v3 v3',
Val.inject j v1 v1' -> Val.inject j v2 v2' -> Val.inject j v3 v3' ->
Val.inject j (f v1 v2 v3) (f v1' v2' v3')) :=
@@ -100,8 +100,8 @@ Next Obligation.
Qed.
Program Definition mkbuiltin_v1p
- (tret: typ) (f: val -> option val)
- (WT: forall v1, val_opt_has_type (f v1) tret)
+ (tret: rettype) (f: val -> option val)
+ (WT: forall v1, val_opt_has_rettype (f v1) tret)
(INJ: forall j v1 v1',
Val.inject j v1 v1' -> val_opt_inject j (f v1) (f v1')) :=
mkbuiltin tret (fun vl => match vl with v1 :: nil => f v1 | _ => None end) _ _.
@@ -113,8 +113,8 @@ Next Obligation.
Qed.
Program Definition mkbuiltin_v2p
- (tret: typ) (f: val -> val -> option val)
- (WT: forall v1 v2, val_opt_has_type (f v1 v2) tret)
+ (tret: rettype) (f: val -> val -> option val)
+ (WT: forall v1 v2, val_opt_has_rettype (f v1 v2) tret)
(INJ: forall j v1 v1' v2 v2',
Val.inject j v1 v1' -> Val.inject j v2 v2' ->
val_opt_inject j (f v1 v2) (f v1' v2')) :=
@@ -171,7 +171,7 @@ Proof.
destruct t; intros; constructor.
Qed.
-Lemma inj_num_opt_wt: forall t x, val_opt_has_type (option_map (inj_num t) x) t.
+Lemma inj_num_opt_wt: forall t x, val_opt_has_rettype (option_map (inj_num t) x) t.
Proof.
intros. destruct x; simpl. apply inj_num_wt. auto.
Qed.
@@ -200,13 +200,13 @@ Proof.
Qed.
Lemma proj_num_opt_wt:
- forall tres t k0 k1 v,
+ forall (tres: typ) t k0 k1 v,
k0 = None \/ k0 = Some Vundef ->
- (forall x, val_opt_has_type (k1 x) tres) ->
- val_opt_has_type (proj_num t k0 v k1) tres.
+ (forall x, val_opt_has_rettype (k1 x) tres) ->
+ val_opt_has_rettype (proj_num t k0 v k1) tres.
Proof.
intros.
- assert (val_opt_has_type k0 tres). { destruct H; subst k0; exact I. }
+ assert (val_opt_has_rettype k0 tres). { destruct H; subst k0; exact I. }
destruct t; simpl; destruct v; auto.
Qed.
@@ -393,33 +393,33 @@ Definition standard_builtin_table : list (string * standard_builtin) :=
Definition standard_builtin_sig (b: standard_builtin) : signature :=
match b with
| BI_select t =>
- mksignature (Tint :: t :: t :: nil) (Some t) cc_default
+ mksignature (Tint :: t :: t :: nil) t cc_default
| BI_fabs | BI_fsqrt =>
- mksignature (Tfloat :: nil) (Some Tfloat) cc_default
+ mksignature (Tfloat :: nil) Tfloat cc_default
| BI_negl =>
- mksignature (Tlong :: nil) (Some Tlong) cc_default
+ mksignature (Tlong :: nil) Tlong cc_default
| BI_addl | BI_subl | BI_i64_umulh| BI_i64_smulh
| BI_i64_sdiv | BI_i64_udiv | BI_i64_smod | BI_i64_umod =>
- mksignature (Tlong :: Tlong :: nil) (Some Tlong) cc_default
+ mksignature (Tlong :: Tlong :: nil) Tlong cc_default
| BI_mull =>
- mksignature (Tint :: Tint :: nil) (Some Tlong) cc_default
+ mksignature (Tint :: Tint :: nil) Tlong cc_default
| BI_i32_bswap =>
- mksignature (Tint :: nil) (Some Tint) cc_default
+ mksignature (Tint :: nil) Tint cc_default
| BI_i64_bswap =>
- mksignature (Tlong :: nil) (Some Tlong) cc_default
+ mksignature (Tlong :: nil) Tlong cc_default
| BI_i16_bswap =>
- mksignature (Tint :: nil) (Some Tint) cc_default
+ mksignature (Tint :: nil) Tint cc_default
| BI_i64_shl | BI_i64_shr | BI_i64_sar =>
- mksignature (Tlong :: Tint :: nil) (Some Tlong) cc_default
+ mksignature (Tlong :: Tint :: nil) Tlong cc_default
| BI_i64_dtos | BI_i64_dtou =>
- mksignature (Tfloat :: nil) (Some Tlong) cc_default
+ mksignature (Tfloat :: nil) Tlong cc_default
| BI_i64_stod | BI_i64_utod =>
- mksignature (Tlong :: nil) (Some Tfloat) cc_default
+ mksignature (Tlong :: nil) Tfloat cc_default
| BI_i64_stof | BI_i64_utof =>
- mksignature (Tlong :: nil) (Some Tsingle) cc_default
+ mksignature (Tlong :: nil) Tsingle cc_default
end.
-Program Definition standard_builtin_sem (b: standard_builtin) : builtin_sem (proj_sig_res (standard_builtin_sig b)) :=
+Program Definition standard_builtin_sem (b: standard_builtin) : builtin_sem (sig_res (standard_builtin_sig b)) :=
match b with
| BI_select t =>
mkbuiltin t
diff --git a/common/Events.v b/common/Events.v
index 3fb84f49..28bb992a 100644
--- a/common/Events.v
+++ b/common/Events.v
@@ -623,7 +623,7 @@ Record extcall_properties (sem: extcall_sem) (sg: signature) : Prop :=
ec_well_typed:
forall ge vargs m1 t vres m2,
sem ge vargs m1 t vres m2 ->
- Val.has_type vres (proj_sig_res sg);
+ Val.has_rettype vres sg.(sig_res);
(** The semantics is invariant under change of global environment that preserves symbols. *)
ec_symbols_preserved:
@@ -649,9 +649,12 @@ Record extcall_properties (sem: extcall_sem) (sg: signature) : Prop :=
(** External call cannot modify memory unless they have [Max, Writable]
permissions. *)
ec_readonly:
- forall ge vargs m1 t vres m2,
+ forall ge vargs m1 t vres m2 b ofs n bytes,
sem ge vargs m1 t vres m2 ->
- Mem.unchanged_on (loc_not_writable m1) m1 m2;
+ Mem.valid_block m1 b ->
+ Mem.loadbytes m2 b ofs n = Some bytes ->
+ (forall i, ofs <= i < ofs + n -> ~Mem.perm m1 b i Max Writable) ->
+ Mem.loadbytes m1 b ofs n = Some bytes;
(** External calls must commute with memory extensions, in the
following sense. *)
@@ -771,12 +774,12 @@ Qed.
Lemma volatile_load_ok:
forall chunk,
extcall_properties (volatile_load_sem chunk)
- (mksignature (Tptr :: nil) (Some (type_of_chunk chunk)) cc_default).
+ (mksignature (Tptr :: nil) (rettype_of_chunk chunk) cc_default).
Proof.
intros; constructor; intros.
(* well typed *)
-- unfold proj_sig_res; simpl. inv H. inv H0. apply Val.load_result_type.
- eapply Mem.load_type; eauto.
+- inv H. inv H0. apply Val.load_result_rettype.
+ eapply Mem.load_rettype; eauto.
(* symbols *)
- inv H0. constructor. eapply volatile_load_preserved; eauto.
(* valid blocks *)
@@ -784,7 +787,7 @@ Proof.
(* max perms *)
- inv H; auto.
(* readonly *)
-- inv H. apply Mem.unchanged_on_refl.
+- inv H; auto.
(* mem extends *)
- inv H. inv H1. inv H6. inv H4.
exploit volatile_load_extends; eauto. intros [v' [A B]].
@@ -833,14 +836,27 @@ Proof.
rewrite C; auto.
Qed.
+Lemma unchanged_on_readonly:
+ forall m1 m2 b ofs n bytes,
+ Mem.unchanged_on (loc_not_writable m1) m1 m2 ->
+ Mem.valid_block m1 b ->
+ Mem.loadbytes m2 b ofs n = Some bytes ->
+ (forall i, ofs <= i < ofs + n -> ~Mem.perm m1 b i Max Writable) ->
+ Mem.loadbytes m1 b ofs n = Some bytes.
+Proof.
+ intros.
+ rewrite <- H1. symmetry.
+ apply Mem.loadbytes_unchanged_on_1 with (P := loc_not_writable m1); auto.
+Qed.
+
Lemma volatile_store_readonly:
forall ge chunk1 m1 b1 ofs1 v t m2,
volatile_store ge chunk1 m1 b1 ofs1 v t m2 ->
Mem.unchanged_on (loc_not_writable m1) m1 m2.
Proof.
intros. inv H.
- apply Mem.unchanged_on_refl.
- eapply Mem.store_unchanged_on; eauto.
+- apply Mem.unchanged_on_refl.
+- eapply Mem.store_unchanged_on; eauto.
exploit Mem.store_valid_access_3; eauto. intros [P Q].
intros. unfold loc_not_writable. red; intros. elim H2.
apply Mem.perm_cur_max. apply P. auto.
@@ -922,7 +938,7 @@ Qed.
Lemma volatile_store_ok:
forall chunk,
extcall_properties (volatile_store_sem chunk)
- (mksignature (Tptr :: type_of_chunk chunk :: nil) None cc_default).
+ (mksignature (Tptr :: type_of_chunk chunk :: nil) Tvoid cc_default).
Proof.
intros; constructor; intros.
(* well typed *)
@@ -934,7 +950,7 @@ Proof.
(* perms *)
- inv H. inv H2. auto. eauto with mem.
(* readonly *)
-- inv H. eapply volatile_store_readonly; eauto.
+- inv H. eapply unchanged_on_readonly; eauto. eapply volatile_store_readonly; eauto.
(* mem extends*)
- inv H. inv H1. inv H6. inv H7. inv H4.
exploit volatile_store_extends; eauto. intros [m2' [A [B C]]].
@@ -967,7 +983,7 @@ Inductive extcall_malloc_sem (ge: Senv.t):
Lemma extcall_malloc_ok:
extcall_properties extcall_malloc_sem
- (mksignature (Tptr :: nil) (Some Tptr) cc_default).
+ (mksignature (Tptr :: nil) Tptr cc_default).
Proof.
assert (UNCHANGED:
forall (P: block -> Z -> Prop) m lo hi v m' b m'',
@@ -984,7 +1000,7 @@ Proof.
}
constructor; intros.
(* well typed *)
-- inv H. unfold proj_sig_res, Tptr; simpl. destruct Archi.ptr64; auto.
+- inv H. simpl. unfold Tptr; destruct Archi.ptr64; auto.
(* symbols preserved *)
- inv H0; econstructor; eauto.
(* valid block *)
@@ -994,7 +1010,7 @@ Proof.
rewrite dec_eq_false. auto.
apply Mem.valid_not_valid_diff with m1; eauto with mem.
(* readonly *)
-- inv H. eapply UNCHANGED; eauto.
+- inv H. eapply unchanged_on_readonly; eauto.
(* mem extends *)
- inv H. inv H1. inv H7.
assert (SZ: v2 = Vptrofs sz).
@@ -1045,38 +1061,43 @@ Qed.
Inductive extcall_free_sem (ge: Senv.t):
list val -> mem -> trace -> val -> mem -> Prop :=
- | extcall_free_sem_intro: forall b lo sz m m',
+ | extcall_free_sem_ptr: forall b lo sz m m',
Mem.load Mptr m b (Ptrofs.unsigned lo - size_chunk Mptr) = Some (Vptrofs sz) ->
Ptrofs.unsigned sz > 0 ->
Mem.free m b (Ptrofs.unsigned lo - size_chunk Mptr) (Ptrofs.unsigned lo + Ptrofs.unsigned sz) = Some m' ->
- extcall_free_sem ge (Vptr b lo :: nil) m E0 Vundef m'.
+ extcall_free_sem ge (Vptr b lo :: nil) m E0 Vundef m'
+ | extcall_free_sem_null: forall m,
+ extcall_free_sem ge (Vnullptr :: nil) m E0 Vundef m.
Lemma extcall_free_ok:
extcall_properties extcall_free_sem
- (mksignature (Tptr :: nil) None cc_default).
+ (mksignature (Tptr :: nil) Tvoid cc_default).
Proof.
constructor; intros.
(* well typed *)
-- inv H. unfold proj_sig_res. simpl. auto.
+- inv H; simpl; auto.
(* symbols preserved *)
- inv H0; econstructor; eauto.
(* valid block *)
-- inv H. eauto with mem.
+- inv H; eauto with mem.
(* perms *)
-- inv H. eapply Mem.perm_free_3; eauto.
+- inv H; eauto using Mem.perm_free_3.
(* readonly *)
-- inv H. eapply Mem.free_unchanged_on; eauto.
- intros. red; intros. elim H3.
+- eapply unchanged_on_readonly; eauto. inv H.
++ eapply Mem.free_unchanged_on; eauto.
+ intros. red; intros. elim H6.
apply Mem.perm_cur_max. apply Mem.perm_implies with Freeable; auto with mem.
eapply Mem.free_range_perm; eauto.
++ apply Mem.unchanged_on_refl.
(* mem extends *)
-- inv H. inv H1. inv H8. inv H6.
+- inv H.
++ inv H1. inv H8. inv H6.
exploit Mem.load_extends; eauto. intros [v' [A B]].
assert (v' = Vptrofs sz).
{ unfold Vptrofs in *; destruct Archi.ptr64; inv B; auto. }
subst v'.
exploit Mem.free_parallel_extends; eauto. intros [m2' [C D]].
- exists Vundef; exists m2'; intuition.
+ exists Vundef; exists m2'; intuition auto.
econstructor; eauto.
eapply Mem.free_unchanged_on; eauto.
unfold loc_out_of_bounds; intros.
@@ -1084,8 +1105,14 @@ Proof.
{ apply Mem.perm_cur_max. apply Mem.perm_implies with Freeable; auto with mem.
eapply Mem.free_range_perm. eexact H4. eauto. }
tauto.
++ inv H1. inv H5. replace v2 with Vnullptr.
+ exists Vundef; exists m1'; intuition auto.
+ constructor.
+ apply Mem.unchanged_on_refl.
+ unfold Vnullptr in *; destruct Archi.ptr64; inv H3; auto.
(* mem inject *)
-- inv H0. inv H2. inv H7. inv H9.
+- inv H0.
++ inv H2. inv H7. inv H9.
exploit Mem.load_inject; eauto. intros [v' [A B]].
assert (v' = Vptrofs sz).
{ unfold Vptrofs in *; destruct Archi.ptr64; inv B; auto. }
@@ -1099,7 +1126,7 @@ Proof.
intro EQ.
exploit Mem.free_parallel_inject; eauto. intros (m2' & C & D).
exists f, Vundef, m2'; split.
- apply extcall_free_sem_intro with (sz := sz) (m' := m2').
+ apply extcall_free_sem_ptr with (sz := sz) (m' := m2').
rewrite EQ. rewrite <- A. f_equal. omega.
auto. auto.
rewrite ! EQ. rewrite <- C. f_equal; omega.
@@ -1112,14 +1139,19 @@ Proof.
apply P. omega.
split. auto.
red; intros. congruence.
++ inv H2. inv H6. replace v' with Vnullptr.
+ exists f, Vundef, m1'; intuition auto using Mem.unchanged_on_refl.
+ constructor.
+ red; intros; congruence.
+ unfold Vnullptr in *; destruct Archi.ptr64; inv H4; auto.
(* trace length *)
- inv H; simpl; omega.
(* receptive *)
-- assert (t1 = t2). inv H; inv H0; auto. subst t2.
+- assert (t1 = t2) by (inv H; inv H0; auto). subst t2.
exists vres1; exists m1; auto.
(* determ *)
-- inv H; inv H0.
- assert (EQ1: Vptrofs sz0 = Vptrofs sz) by congruence.
+- inv H; inv H0; try (unfold Vnullptr in *; destruct Archi.ptr64; discriminate).
++ assert (EQ1: Vptrofs sz0 = Vptrofs sz) by congruence.
assert (EQ2: sz0 = sz).
{ unfold Vptrofs in EQ1; destruct Archi.ptr64 eqn:SF.
rewrite <- (Ptrofs.of_int64_to_int64 SF sz0), <- (Ptrofs.of_int64_to_int64 SF sz). congruence.
@@ -1127,6 +1159,7 @@ Proof.
}
subst sz0.
split. constructor. intuition congruence.
++ split. constructor. intuition auto.
Qed.
(** ** Semantics of [memcpy] operations. *)
@@ -1147,11 +1180,11 @@ Inductive extcall_memcpy_sem (sz al: Z) (ge: Senv.t):
Lemma extcall_memcpy_ok:
forall sz al,
extcall_properties (extcall_memcpy_sem sz al)
- (mksignature (Tptr :: Tptr :: nil) None cc_default).
+ (mksignature (Tptr :: Tptr :: nil) Tvoid cc_default).
Proof.
intros. constructor.
- (* return type *)
- intros. inv H. constructor.
+ intros. inv H. exact I.
- (* change of globalenv *)
intros. inv H0. econstructor; eauto.
- (* valid blocks *)
@@ -1159,8 +1192,9 @@ Proof.
- (* perms *)
intros. inv H. eapply Mem.perm_storebytes_2; eauto.
- (* readonly *)
- intros. inv H. eapply Mem.storebytes_unchanged_on; eauto.
- intros; red; intros. elim H8.
+ intros. inv H. eapply unchanged_on_readonly; eauto.
+ eapply Mem.storebytes_unchanged_on; eauto.
+ intros; red; intros. elim H11.
apply Mem.perm_cur_max. eapply Mem.storebytes_range_perm; eauto.
- (* extensions *)
intros. inv H.
@@ -1258,7 +1292,7 @@ Inductive extcall_annot_sem (text: string) (targs: list typ) (ge: Senv.t):
Lemma extcall_annot_ok:
forall text targs,
extcall_properties (extcall_annot_sem text targs)
- (mksignature targs None cc_default).
+ (mksignature targs Tvoid cc_default).
Proof.
intros; constructor; intros.
(* well typed *)
@@ -1271,7 +1305,7 @@ Proof.
(* perms *)
- inv H; auto.
(* readonly *)
-- inv H. apply Mem.unchanged_on_refl.
+- inv H; auto.
(* mem extends *)
- inv H.
exists Vundef; exists m1'; intuition.
@@ -1303,11 +1337,11 @@ Inductive extcall_annot_val_sem (text: string) (targ: typ) (ge: Senv.t):
Lemma extcall_annot_val_ok:
forall text targ,
extcall_properties (extcall_annot_val_sem text targ)
- (mksignature (targ :: nil) (Some targ) cc_default).
+ (mksignature (targ :: nil) targ cc_default).
Proof.
intros; constructor; intros.
(* well typed *)
-- inv H. unfold proj_sig_res; simpl. eapply eventval_match_type; eauto.
+- inv H. eapply eventval_match_type; eauto.
(* symbols *)
- destruct H as (A & B & C). inv H0. econstructor; eauto.
eapply eventval_match_preserved; eauto.
@@ -1316,7 +1350,7 @@ Proof.
(* perms *)
- inv H; auto.
(* readonly *)
-- inv H. apply Mem.unchanged_on_refl.
+- inv H; auto.
(* mem extends *)
- inv H. inv H1. inv H6.
exists v2; exists m1'; intuition.
@@ -1347,7 +1381,7 @@ Inductive extcall_debug_sem (ge: Senv.t):
Lemma extcall_debug_ok:
forall targs,
extcall_properties extcall_debug_sem
- (mksignature targs None cc_default).
+ (mksignature targs Tvoid cc_default).
Proof.
intros; constructor; intros.
(* well typed *)
@@ -1359,7 +1393,7 @@ Proof.
(* perms *)
- inv H; auto.
(* readonly *)
-- inv H. apply Mem.unchanged_on_refl.
+- inv H; auto.
(* mem extends *)
- inv H.
exists Vundef; exists m1'; intuition.
@@ -1396,7 +1430,8 @@ Proof.
intros. set (bsem := builtin_function_sem bf). constructor; intros.
(* well typed *)
- inv H.
- specialize (bs_well_typed _ bsem vargs). unfold val_opt_has_type, bsem; rewrite H0.
+ specialize (bs_well_typed _ bsem vargs).
+ unfold val_opt_has_rettype, bsem; rewrite H0.
auto.
(* symbols *)
- inv H0. econstructor; eauto.
@@ -1405,7 +1440,7 @@ Proof.
(* perms *)
- inv H; auto.
(* readonly *)
-- inv H. apply Mem.unchanged_on_refl.
+- inv H; auto.
(* mem extends *)
- inv H. fold bsem in H2. apply val_inject_list_lessdef in H1.
specialize (bs_inject _ bsem _ _ _ H1).
@@ -1516,7 +1551,7 @@ Proof.
apply extcall_debug_ok.
Qed.
-Definition external_call_well_typed ef := ec_well_typed (external_call_spec ef).
+Definition external_call_well_typed_gen ef := ec_well_typed (external_call_spec ef).
Definition external_call_symbols_preserved ef := ec_symbols_preserved (external_call_spec ef).
Definition external_call_valid_block ef := ec_valid_block (external_call_spec ef).
Definition external_call_max_perm ef := ec_max_perm (external_call_spec ef).
@@ -1527,6 +1562,16 @@ Definition external_call_trace_length ef := ec_trace_length (external_call_spec
Definition external_call_receptive ef := ec_receptive (external_call_spec ef).
Definition external_call_determ ef := ec_determ (external_call_spec ef).
+(** Corollary of [external_call_well_typed_gen]. *)
+
+Lemma external_call_well_typed:
+ forall ef ge vargs m1 t vres m2,
+ external_call ef ge vargs m1 t vres m2 ->
+ Val.has_type vres (proj_sig_res (ef_sig ef)).
+Proof.
+ intros. apply Val.has_proj_rettype. eapply external_call_well_typed_gen; eauto.
+Qed.
+
(** Corollary of [external_call_valid_block]. *)
Lemma external_call_nextblock:
diff --git a/common/Memdata.v b/common/Memdata.v
index 7144d72c..a09b90f5 100644
--- a/common/Memdata.v
+++ b/common/Memdata.v
@@ -44,6 +44,13 @@ Definition size_chunk (chunk: memory_chunk) : Z :=
| Many64 => 8
end.
+Definition largest_size_chunk := 8.
+
+Lemma max_size_chunk: forall chunk, size_chunk chunk <= 8.
+Proof.
+ destruct chunk; simpl; omega.
+Qed.
+
Lemma size_chunk_pos:
forall chunk, size_chunk chunk > 0.
Proof.
@@ -547,18 +554,26 @@ Proof.
destruct v1; auto.
Qed.
-Lemma decode_val_type:
+Lemma decode_val_rettype:
forall chunk cl,
- Val.has_type (decode_val chunk cl) (type_of_chunk chunk).
+ Val.has_rettype (decode_val chunk cl) (rettype_of_chunk chunk).
Proof.
intros. unfold decode_val.
destruct (proj_bytes cl).
- destruct chunk; simpl; auto.
-Local Opaque Val.load_result.
+- destruct chunk; simpl; rewrite ? Int.sign_ext_idem, ? Int.zero_ext_idem by omega; auto.
+- Local Opaque Val.load_result.
destruct chunk; simpl;
(exact I || apply Val.load_result_type || destruct Archi.ptr64; (exact I || apply Val.load_result_type)).
Qed.
+Lemma decode_val_type:
+ forall chunk cl,
+ Val.has_type (decode_val chunk cl) (type_of_chunk chunk).
+Proof.
+ intros. rewrite <- proj_rettype_of_chunk.
+ apply Val.has_proj_rettype. apply decode_val_rettype.
+Qed.
+
Lemma encode_val_int8_signed_unsigned:
forall v, encode_val Mint8signed v = encode_val Mint8unsigned v.
Proof.
@@ -607,11 +622,9 @@ Lemma decode_val_cast:
| _ => True
end.
Proof.
- unfold decode_val; intros; destruct chunk; auto; destruct (proj_bytes l); auto.
- unfold Val.sign_ext. rewrite Int.sign_ext_idem; auto. omega.
- unfold Val.zero_ext. rewrite Int.zero_ext_idem; auto. omega.
- unfold Val.sign_ext. rewrite Int.sign_ext_idem; auto. omega.
- unfold Val.zero_ext. rewrite Int.zero_ext_idem; auto. omega.
+ intros.
+ assert (A: Val.has_rettype v (rettype_of_chunk chunk)) by apply decode_val_rettype.
+ destruct chunk; auto; simpl in A; destruct v; try contradiction; simpl; congruence.
Qed.
(** Pointers cannot be forged. *)
diff --git a/common/Memory.v b/common/Memory.v
index b68a5049..cd8a2001 100644
--- a/common/Memory.v
+++ b/common/Memory.v
@@ -38,6 +38,10 @@ Require Import Floats.
Require Import Values.
Require Export Memdata.
Require Export Memtype.
+Require Import Lia.
+
+Definition default_notrap_load_value (chunk : memory_chunk) := Vundef.
+
(* To avoid useless definitions of inductors in extracted code. *)
Local Unset Elimination Schemes.
@@ -538,6 +542,48 @@ Proof.
induction vl; simpl; intros. auto. rewrite IHvl. auto.
Qed.
+Remark set_setN_swap_disjoint:
+ forall vl: list memval,
+ forall v: memval,
+ forall m : ZMap.t memval,
+ forall p pl: Z,
+ ~ (Intv.In p (pl, pl + Z.of_nat (length vl))) ->
+ (setN vl pl (ZMap.set p v m)) = (ZMap.set p v (setN vl pl m)).
+Proof.
+ induction vl; simpl; trivial.
+ intros.
+ unfold Intv.In in *; simpl in *.
+ rewrite ZMap.set_disjoint by lia.
+ apply IHvl.
+ lia.
+Qed.
+
+Lemma setN_swap_disjoint:
+ forall vl1 vl2: list memval,
+ forall m : ZMap.t memval,
+ forall p1 p2: Z,
+ Intv.disjoint (p1, p1 + Z.of_nat (length vl1))
+ (p2, p2 + Z.of_nat (length vl2)) ->
+ (setN vl1 p1 (setN vl2 p2 m)) = (setN vl2 p2 (setN vl1 p1 m)).
+Proof.
+ induction vl1; simpl; trivial.
+ intros until p2. intro DISJOINT.
+ rewrite <- set_setN_swap_disjoint.
+ { rewrite IHvl1.
+ reflexivity.
+ unfold Intv.disjoint, Intv.In in *.
+ simpl in *.
+ intro.
+ intro BOUNDS.
+ apply DISJOINT.
+ lia.
+ }
+ unfold Intv.disjoint, Intv.In in *.
+ simpl in *.
+ apply DISJOINT.
+ lia.
+Qed.
+
(** [store chunk m b ofs v] perform a write in memory state [m].
Value [v] is stored at address [b] and offset [ofs].
Return the updated memory store, or [None] if the accessed bytes
@@ -682,6 +728,15 @@ Proof.
apply decode_val_type.
Qed.
+Theorem load_rettype:
+ forall m chunk b ofs v,
+ load chunk m b ofs = Some v ->
+ Val.has_rettype v (rettype_of_chunk chunk).
+Proof.
+ intros. exploit load_result; eauto; intros. rewrite H0.
+ apply decode_val_rettype.
+Qed.
+
Theorem load_cast:
forall m chunk b ofs v,
load chunk m b ofs = Some v ->
@@ -1169,6 +1224,106 @@ Local Hint Resolve store_valid_block_1 store_valid_block_2: mem.
Local Hint Resolve store_valid_access_1 store_valid_access_2
store_valid_access_3: mem.
+Remark mem_same_proof_irr :
+ forall m1 m2 : mem,
+ (mem_contents m1) = (mem_contents m2) ->
+ (mem_access m1) = (mem_access m2) ->
+ (nextblock m1) = (nextblock m2) ->
+ m1 = m2.
+Proof.
+ destruct m1 as [contents1 access1 nextblock1 access_max1 nextblock_noaccess1 default1].
+ destruct m2 as [contents2 access2 nextblock2 access_max2 nextblock_noaccess2 default2].
+ simpl.
+ intros.
+ subst contents2.
+ subst access2.
+ subst nextblock2.
+ f_equal; apply proof_irr.
+Qed.
+
+Theorem store_store_other:
+ forall chunk b ofs v chunk' b' ofs' v' m0 m1 m1',
+ b' <> b
+ \/ ofs' + size_chunk chunk' <= ofs
+ \/ ofs + size_chunk chunk <= ofs' ->
+ store chunk m0 b ofs v = Some m1 ->
+ store chunk' m0 b' ofs' v' = Some m1' ->
+ store chunk' m1 b' ofs' v' =
+ store chunk m1' b ofs v.
+Proof.
+ intros until m1'.
+ intro DISJOINT.
+ intros W0 W0'.
+ assert (valid_access m1' chunk b ofs Writable) as WRITEABLE1' by eauto with mem.
+ (* {
+ eapply store_valid_access_1.
+ apply W0'.
+ eapply store_valid_access_3.
+ apply W0.
+ } *)
+ assert (valid_access m1 chunk' b' ofs' Writable) as WRITABLE1 by eauto with mem.
+ (* {
+ eapply store_valid_access_1.
+ apply W0.
+ eapply store_valid_access_3.
+ apply W0'.
+ } *)
+ unfold store in *.
+ destruct (valid_access_dec m0 chunk b ofs Writable).
+ 2: congruence.
+ destruct (valid_access_dec m1 chunk' b' ofs' Writable).
+ 2: contradiction.
+ destruct (valid_access_dec m0 chunk' b' ofs' Writable).
+ 2: congruence.
+ destruct (valid_access_dec m1' chunk b ofs Writable).
+ 2: contradiction.
+ f_equal.
+ inv W0; simpl in *.
+ inv W0'; simpl in *.
+ apply mem_same_proof_irr; simpl; trivial.
+ destruct (eq_block b b').
+ { subst b'.
+ rewrite PMap.gss.
+ rewrite PMap.gss.
+ rewrite PMap.set2.
+ rewrite PMap.set2.
+ f_equal.
+ apply setN_swap_disjoint.
+ unfold Intv.disjoint.
+ rewrite encode_val_length.
+ rewrite <- size_chunk_conv.
+ rewrite encode_val_length.
+ rewrite <- size_chunk_conv.
+ unfold Intv.In; simpl.
+ intros.
+ destruct DISJOINT. contradiction.
+ lia.
+ }
+ {
+ rewrite PMap.set_disjoint by congruence.
+ rewrite PMap.gso by congruence.
+ rewrite PMap.gso by congruence.
+ reflexivity.
+ }
+Qed.
+
+Section STOREV.
+Variable chunk: memory_chunk.
+Variable m1: mem.
+Variables addr v: val.
+Variable m2: mem.
+Hypothesis STORE: storev chunk m1 addr v = Some m2.
+
+
+Theorem loadv_storev_same:
+ loadv chunk m2 addr = Some (Val.load_result chunk v).
+Proof.
+ destruct addr; simpl in *; try discriminate.
+ eapply load_store_same.
+ eassumption.
+Qed.
+End STOREV.
+
Lemma load_store_overlap:
forall chunk m1 b ofs v m2 chunk' ofs' v',
store chunk m1 b ofs v = Some m2 ->
diff --git a/common/Memtype.v b/common/Memtype.v
index 53775d8b..ca9c6f1f 100644
--- a/common/Memtype.v
+++ b/common/Memtype.v
@@ -300,6 +300,11 @@ Axiom load_type:
load chunk m b ofs = Some v ->
Val.has_type v (type_of_chunk chunk).
+Axiom load_rettype:
+ forall m chunk b ofs v,
+ load chunk m b ofs = Some v ->
+ Val.has_rettype v (rettype_of_chunk chunk).
+
(** For a small integer or float type, the value returned by [load]
is invariant under the corresponding cast. *)
Axiom load_cast:
diff --git a/common/PrintAST.ml b/common/PrintAST.ml
index e477957a..3f718428 100644
--- a/common/PrintAST.ml
+++ b/common/PrintAST.ml
@@ -27,6 +27,14 @@ let name_of_type = function
| Tany32 -> "any32"
| Tany64 -> "any64"
+let name_of_rettype = function
+ | Tret t -> name_of_type t
+ | Tvoid -> "void"
+ | Tint8signed -> "int8s"
+ | Tint8unsigned -> "int8u"
+ | Tint16signed -> "int16s"
+ | Tint16unsigned -> "int16u"
+
let name_of_chunk = function
| Mint8signed -> "int8s"
| Mint8unsigned -> "int8u"
@@ -90,3 +98,7 @@ let rec print_builtin_res px oc = function
fprintf oc "splitlong(%a, %a)"
(print_builtin_res px) hi (print_builtin_res px) lo
+let print_trapping_mode oc = function
+ | TRAP -> ()
+ | NOTRAP -> output_string oc " [notrap]"
+
diff --git a/common/Sections.ml b/common/Sections.ml
index 30be9e69..839128a5 100644
--- a/common/Sections.ml
+++ b/common/Sections.ml
@@ -160,9 +160,22 @@ let gcc_section name readonly exec =
sec_writable = not readonly; sec_executable = exec;
sec_access = Access_default }
+(* Check and extract whether a section was given as attribute *)
+
+let get_attr_section loc attr =
+ match Cutil.find_custom_attributes ["section"; "__section__"] attr with
+ | [] -> None
+ | [[C.AString name]] -> Some name
+ | [[_]] ->
+ Diagnostics.error loc "'section' attribute requires a string";
+ None
+ | _ ->
+ Diagnostics.error loc "ambiguous 'section' attribute";
+ None
+
(* Determine section for a variable definition *)
-let for_variable env id ty init =
+let for_variable env loc id ty init =
let attr = Cutil.attributes_of_type env ty in
let readonly = List.mem C.AConst attr && not(List.mem C.AVolatile attr) in
let si =
@@ -170,11 +183,11 @@ let for_variable env id ty init =
(* 1- Section explicitly associated with #use_section *)
Hashtbl.find use_section_table id
with Not_found ->
- match Cutil.find_custom_attributes ["section"; "__section__"] attr with
- | [[C.AString name]] ->
+ match get_attr_section loc attr with
+ | Some name ->
(* 2- Section given as an attribute, gcc-style *)
gcc_section name readonly false
- | _ ->
+ | None ->
(* 3- Default section appropriate for size and const-ness *)
let size =
match Cutil.sizeof env ty with Some sz -> sz | None -> max_int in
@@ -190,17 +203,17 @@ let for_variable env id ty init =
(* Determine sections for a function definition *)
-let for_function env id attr =
+let for_function env loc id attr =
let si_code =
try
(* 1- Section explicitly associated with #use_section *)
Hashtbl.find use_section_table id
with Not_found ->
- match Cutil.find_custom_attributes ["section"; "__section__"] attr with
- | [[C.AString name]] ->
+ match get_attr_section loc attr with
+ | Some name ->
(* 2- Section given as an attribute, gcc-style *)
gcc_section name true true
- | _ ->
+ | None ->
(* 3- Default section *)
try
Hashtbl.find current_section_table "CODE"
diff --git a/common/Sections.mli b/common/Sections.mli
index bc97814d..d9fd9239 100644
--- a/common/Sections.mli
+++ b/common/Sections.mli
@@ -46,7 +46,7 @@ val define_section:
-> ?writable:bool -> ?executable:bool -> ?access:access_mode -> unit -> unit
val use_section_for: AST.ident -> string -> bool
-val for_variable: Env.t -> AST.ident -> C.typ -> bool ->
+val for_variable: Env.t -> C.location -> AST.ident -> C.typ -> bool ->
section_name * access_mode
-val for_function: Env.t -> AST.ident -> C.attributes -> section_name list
+val for_function: Env.t -> C.location -> AST.ident -> C.attributes -> section_name list
val for_stringlit: unit -> section_name
diff --git a/common/Values.v b/common/Values.v
index de317734..6401ba52 100644
--- a/common/Values.v
+++ b/common/Values.v
@@ -149,6 +149,23 @@ Proof.
auto.
Defined.
+Definition has_rettype (v: val) (r: rettype) : Prop :=
+ match r, v with
+ | Tret t, _ => has_type v t
+ | Tint8signed, Vint n => n = Int.sign_ext 8 n
+ | Tint8unsigned, Vint n => n = Int.zero_ext 8 n
+ | Tint16signed, Vint n => n = Int.sign_ext 16 n
+ | Tint16unsigned, Vint n => n = Int.zero_ext 16 n
+ | _, Vundef => True
+ | _, _ => False
+ end.
+
+Lemma has_proj_rettype: forall v r,
+ has_rettype v r -> has_type v (proj_rettype r).
+Proof.
+ destruct r; simpl; intros; auto; destruct v; try contradiction; exact I.
+Qed.
+
(** Truth values. Non-zero integers are treated as [True].
The integer 0 (also used to represent the null pointer) is [False].
Other values are neither true nor false. *)
@@ -1003,10 +1020,24 @@ Definition load_result (chunk: memory_chunk) (v: val) :=
| _, _ => Vundef
end.
+Lemma load_result_rettype:
+ forall chunk v, has_rettype (load_result chunk v) (rettype_of_chunk chunk).
+Proof.
+ intros. unfold has_rettype; destruct chunk; destruct v; simpl; auto.
+- rewrite Int.sign_ext_idem by omega; auto.
+- rewrite Int.zero_ext_idem by omega; auto.
+- rewrite Int.sign_ext_idem by omega; auto.
+- rewrite Int.zero_ext_idem by omega; auto.
+- destruct Archi.ptr64 eqn:SF; simpl; auto.
+- destruct Archi.ptr64 eqn:SF; simpl; auto.
+- destruct Archi.ptr64 eqn:SF; simpl; auto.
+Qed.
+
Lemma load_result_type:
forall chunk v, has_type (load_result chunk v) (type_of_chunk chunk).
Proof.
- intros. unfold has_type; destruct chunk; destruct v; simpl; auto; destruct Archi.ptr64 eqn:SF; simpl; auto.
+ intros. rewrite <- proj_rettype_of_chunk. apply has_proj_rettype.
+ apply load_result_rettype.
Qed.
Lemma load_result_same:
@@ -1439,6 +1470,60 @@ Proof.
assert (32 < Int.max_unsigned) by reflexivity. omega.
Qed.
+Theorem shrx1_shr:
+ forall x z,
+ shrx x (Vint (Int.repr 1)) = Some z ->
+ z = shr (add x (shru x (Vint (Int.repr 31)))) (Vint (Int.repr 1)).
+Proof.
+ intros. destruct x; simpl in H; try discriminate.
+ change (Int.ltu (Int.repr 1) (Int.repr 31)) with true in H; simpl in H.
+ inversion_clear H.
+ simpl.
+ change (Int.ltu (Int.repr 31) Int.iwordsize) with true; simpl.
+ change (Int.ltu (Int.repr 1) Int.iwordsize) with true; simpl.
+ f_equal.
+ rewrite Int.shrx1_shr by reflexivity.
+ reflexivity.
+Qed.
+
+Theorem shrx_shr_3:
+ forall n x z,
+ shrx x (Vint n) = Some z ->
+ z = (if Int.eq n Int.zero then x else
+ if Int.eq n Int.one
+ then shr (add x (shru x (Vint (Int.repr 31)))) (Vint Int.one)
+ else shr (add x (shru (shr x (Vint (Int.repr 31)))
+ (Vint (Int.sub (Int.repr 32) n))))
+ (Vint n)).
+Proof.
+ intros. destruct x; simpl in H; try discriminate.
+ destruct (Int.ltu n (Int.repr 31)) eqn:LT; inv H.
+ exploit Int.ltu_inv; eauto. change (Int.unsigned (Int.repr 31)) with 31; intros LT'.
+ predSpec Int.eq Int.eq_spec n Int.zero.
+- subst n. unfold Int.shrx. rewrite Int.shl_zero. unfold Int.divs. change (Int.signed Int.one) with 1.
+ rewrite Z.quot_1_r. rewrite Int.repr_signed; auto.
+- predSpec Int.eq Int.eq_spec n Int.one.
+ * subst n. simpl.
+ change (Int.ltu (Int.repr 31) Int.iwordsize) with true. simpl.
+ change (Int.ltu Int.one Int.iwordsize) with true. simpl.
+ f_equal.
+ apply Int.shrx1_shr.
+ reflexivity.
+ * clear H0.
+ simpl. change (Int.ltu (Int.repr 31) Int.iwordsize) with true. simpl.
+ replace (Int.ltu (Int.sub (Int.repr 32) n) Int.iwordsize) with true. simpl.
+ replace (Int.ltu n Int.iwordsize) with true.
+ f_equal; apply Int.shrx_shr_2; assumption.
+ symmetry; apply zlt_true. change (Int.unsigned n < 32); omega.
+ symmetry; apply zlt_true. unfold Int.sub. change (Int.unsigned (Int.repr 32)) with 32.
+ assert (Int.unsigned n <> 0).
+ { red; intros; elim H.
+ rewrite <- (Int.repr_unsigned n), H0. auto. }
+ rewrite Int.unsigned_repr.
+ change (Int.unsigned Int.iwordsize) with 32; omega.
+ assert (32 < Int.max_unsigned) by reflexivity. omega.
+Qed.
+
Theorem or_rolm:
forall x n m1 m2,
or (rolm x n m1) (rolm x n m2) = rolm x n (Int.or m1 m2).
@@ -1698,6 +1783,58 @@ Proof.
assert (64 < Int.max_unsigned) by reflexivity. omega.
Qed.
+Theorem shrxl1_shrl:
+ forall x z,
+ shrxl x (Vint (Int.repr 1)) = Some z ->
+ z = shrl (addl x (shrlu x (Vint (Int.repr 63)))) (Vint (Int.repr 1)).
+Proof.
+ intros. destruct x; simpl in H; try discriminate.
+ change (Int.ltu (Int.repr 1) (Int.repr 63)) with true in H; simpl in H.
+ inversion_clear H.
+ simpl.
+ change (Int.ltu (Int.repr 63) Int64.iwordsize') with true; simpl.
+ change (Int.ltu (Int.repr 1) Int64.iwordsize') with true; simpl.
+ f_equal.
+ rewrite Int64.shrx'1_shr' by reflexivity.
+ reflexivity.
+Qed.
+
+Theorem shrxl_shrl_3:
+ forall n x z,
+ shrxl x (Vint n) = Some z ->
+ z = (if Int.eq n Int.zero then x else
+ if Int.eq n Int.one
+ then shrl (addl x (shrlu x (Vint (Int.repr 63)))) (Vint Int.one)
+ else shrl (addl x (shrlu (shrl x (Vint (Int.repr 63)))
+ (Vint (Int.sub (Int.repr 64) n))))
+ (Vint n)).
+Proof.
+ intros. destruct x; simpl in H; try discriminate.
+ destruct (Int.ltu n (Int.repr 63)) eqn:LT; inv H.
+ exploit Int.ltu_inv; eauto. change (Int.unsigned (Int.repr 63)) with 63; intros LT'.
+ predSpec Int.eq Int.eq_spec n Int.zero.
+- subst n. unfold Int64.shrx'. rewrite Int64.shl'_zero. unfold Int64.divs. change (Int64.signed Int64.one) with 1.
+ rewrite Z.quot_1_r. rewrite Int64.repr_signed; auto.
+- predSpec Int.eq Int.eq_spec n Int.one.
+ * subst n. simpl.
+ change (Int.ltu (Int.repr 63) Int64.iwordsize') with true. simpl.
+ change (Int.ltu Int.one Int64.iwordsize') with true. simpl.
+ f_equal.
+ apply Int64.shrx'1_shr'.
+ reflexivity.
+ * clear H0.
+simpl. change (Int.ltu (Int.repr 63) Int64.iwordsize') with true. simpl.
+ replace (Int.ltu (Int.sub (Int.repr 64) n) Int64.iwordsize') with true. simpl.
+ replace (Int.ltu n Int64.iwordsize') with true.
+ f_equal; apply Int64.shrx'_shr_2; assumption.
+ symmetry; apply zlt_true. change (Int.unsigned n < 64); omega.
+ symmetry; apply zlt_true. unfold Int.sub. change (Int.unsigned (Int.repr 64)) with 64.
+ assert (Int.unsigned n <> 0). { red; intros; elim H. rewrite <- (Int.repr_unsigned n), H0. auto. }
+ rewrite Int.unsigned_repr.
+ change (Int.unsigned Int64.iwordsize') with 64; omega.
+ assert (64 < Int.max_unsigned) by reflexivity. omega.
+Qed.
+
Theorem negate_cmp_bool:
forall c x y, cmp_bool (negate_comparison c) x y = option_map negb (cmp_bool c x y).
Proof.
diff --git a/config_aarch64.sh b/config_aarch64.sh
new file mode 100755
index 00000000..ded267bf
--- /dev/null
+++ b/config_aarch64.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh aarch64-linux --toolprefix aarch64-linux-gnu- "$@"
diff --git a/config_arm.sh b/config_arm.sh
new file mode 100755
index 00000000..1861e029
--- /dev/null
+++ b/config_arm.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh arm-linux --toolprefix arm-linux-gnueabi- "$@"
diff --git a/config_armhf.sh b/config_armhf.sh
new file mode 100755
index 00000000..8a1302bd
--- /dev/null
+++ b/config_armhf.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh arm-eabihf --toolprefix arm-linux-gnueabihf- "$@"
diff --git a/config_ia32.sh b/config_ia32.sh
new file mode 100755
index 00000000..b40f2b39
--- /dev/null
+++ b/config_ia32.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh ia32-linux "$@"
diff --git a/config_k1c.sh b/config_k1c.sh
new file mode 100755
index 00000000..20408397
--- /dev/null
+++ b/config_k1c.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh k1c-cos "$@"
diff --git a/config_ppc.sh b/config_ppc.sh
new file mode 100755
index 00000000..d597cda5
--- /dev/null
+++ b/config_ppc.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh ppc-linux --toolprefix powerpc-linux-gnu- "$@"
diff --git a/config_ppc64.sh b/config_ppc64.sh
new file mode 100755
index 00000000..df31c18f
--- /dev/null
+++ b/config_ppc64.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh ppc64-linux --toolprefix powerpc64-linux-gnu- "$@"
diff --git a/config_rv32.sh b/config_rv32.sh
new file mode 100755
index 00000000..a5a5cf1c
--- /dev/null
+++ b/config_rv32.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh rv32-linux --toolprefix riscv64-linux-gnu- "$@"
diff --git a/config_rv64.sh b/config_rv64.sh
new file mode 100755
index 00000000..0698c2ff
--- /dev/null
+++ b/config_rv64.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh rv64-linux --toolprefix riscv64-linux-gnu- "$@"
diff --git a/config_simple.sh b/config_simple.sh
new file mode 100755
index 00000000..e2d3844c
--- /dev/null
+++ b/config_simple.sh
@@ -0,0 +1,11 @@
+arch=$1
+shift
+version=`git rev-parse --short HEAD`
+branch=`git rev-parse --abbrev-ref HEAD`
+date=`date -I`
+
+if test "x$CCOMP_INSTALL_PREFIX" = "x" ;
+then CCOMP_INSTALL_PREFIX=/opt/CompCert ;
+fi
+
+./configure --prefix ${CCOMP_INSTALL_PREFIX}/${branch}/${date}_${version}/$arch "$@" $arch
diff --git a/config_x86_64.sh b/config_x86_64.sh
new file mode 100755
index 00000000..b18ec95b
--- /dev/null
+++ b/config_x86_64.sh
@@ -0,0 +1 @@
+exec ./config_simple.sh x86_64-linux "$@"
diff --git a/configure b/configure
index d7cc2567..93d3c242 100755
--- a/configure
+++ b/configure
@@ -457,8 +457,8 @@ if test "$arch" = "mppa_k1c"; then
fi
osupper=`echo $os|tr a-z A-Z`
k1base="k1-$os"
- casm="$k1base-gcc"
- casm_options="$model_options -c"
+ casm="k1-elf-as"
+ casm_options="$model_options"
cc="$k1base-gcc $model_options"
clinker="$k1base-gcc"
bindir="$HOME/.usr/bin"
@@ -568,14 +568,14 @@ missingtools=false
echo "Testing Coq... " | tr -d '\n'
coq_ver=$(${COQBIN}coqc -v 2>/dev/null | sed -n -e 's/The Coq Proof Assistant, version \([^ ]*\).*$/\1/p')
case "$coq_ver" in
- 8.8.0|8.8.1|8.8.2|8.9.0|8.9.1|8.10|8.11.0)
+ 8.9.0|8.9.1|8.10.0|8.10.1|8.10.2|8.11.0)
echo "version $coq_ver -- good!";;
?*)
echo "version $coq_ver -- UNSUPPORTED"
if $ignore_coq_version; then
echo "Warning: this version of Coq is unsupported, proceed at your own risks."
else
- echo "Error: CompCert requires one of the following Coq versions: 8.10, 8.9.1, 8.9.0, 8.8.2, 8.8.1, 8.8.0"
+ echo "Error: CompCert requires one of the following Coq versions: 8.11.0, 8.10.2, 8.10.1, 8.10.0, 8.9.1, 8.9.0, 8.8.2, 8.8.1, 8.8.0"
missingtools=true
fi;;
"")
@@ -587,24 +587,19 @@ esac
echo "Testing OCaml... " | tr -d '\n'
ocaml_ver=`ocamlopt -version 2>/dev/null`
case "$ocaml_ver" in
- 4.00.*|4.01.*)
+ 4.00.*|4.01.*| 4.02.*|4.03.*|4.04.*)
echo "version $ocaml_ver -- UNSUPPORTED"
- echo "Error: CompCert requires OCaml version 4.02 or later."
+ echo "Error: CompCert requires OCaml version 4.05 or later."
missingtools=true;;
- 4.02.*|4.03.*|4.04.*)
- echo "version $ocaml_ver -- good!"
- echo "WARNING: some Intel processors of the Skylake and Kaby Lake generations"
- echo "have a hardware bug that can be triggered by this version of OCaml."
- echo "To avoid this risk, it is recommended to use OCaml 4.05 or later.";;
- 4.0*)
+ 4.*)
echo "version $ocaml_ver -- good!";;
?.*)
echo "version $ocaml_ver -- UNSUPPORTED"
- echo "Error: CompCert requires OCaml version 4.02 or later."
+ echo "Error: CompCert requires OCaml version 4.05 or later."
missingtools=true;;
*)
echo "NOT FOUND"
- echo "Error: make sure OCaml version 4.02 or later is installed."
+ echo "Error: make sure OCaml version 4.05 or later is installed."
missingtools=true;;
esac
@@ -625,8 +620,8 @@ case "$menhir_ver" in
20[0-9][0-9][0-9][0-9][0-9][0-9])
if test "$menhir_ver" -ge $MENHIR_REQUIRED; then
echo "version $menhir_ver -- good!"
- menhir_include_dir=$(menhir --suggest-menhirLib | tr -d '\r' | tr '\\' '/')
- if test -z "$menhir_include_dir"; then
+ menhir_dir=$(menhir --suggest-menhirLib | tr -d '\r' | tr '\\' '/')
+ if test -z "$menhir_dir"; then
echo "Error: cannot determine the location of the Menhir API library."
echo "This can be due to an incorrect Menhir package."
echo "Consider using the OPAM package for Menhir."
@@ -720,7 +715,7 @@ MANDIR=$sharedir/man
SHAREDIR=$sharedir
COQDEVDIR=$coqdevdir
OCAML_OPT_COMP=$ocaml_opt_comp
-MENHIR_INCLUDES=-I "$menhir_include_dir"
+MENHIR_DIR=$menhir_dir
COMPFLAGS=-bin-annot
EOF
@@ -850,7 +845,7 @@ EXECUTE=k1-cluster --syscall=libstd_scalls.so --
CFLAGS= -D __K1C_COS__
SIMU=k1-cluster --
BACKENDLIB=Machblock.v Machblockgen.v Machblockgenproof.v RTLpath.v RTLpathLivegen.v RTLpathLiveproofs.v RTLpathSE_theory.v RTLpathScheduler.v\\
- Asmblock.v Asmblockgen.v Asmblockgenproof0.v Asmblockgenproof1.v Asmblockgenproof.v Asmvliw.v\\
+ Asmblock.v Asmblockgen.v Asmblockgenproof0.v Asmblockgenproof1.v Asmblockgenproof.v Asmvliw.v Asmblockprops.v\\
ForwardSimulationBlock.v PostpassScheduling.v PostpassSchedulingproof.v\\
Asmblockdeps.v DecBoolOps.v Chunks.v Peephole.v ExtValues.v ExtFloats.v\\
AbstractBasicBlocksDef.v SeqSimuTheory.v ImpSimuTest.v Parallelizability.v\\
diff --git a/coq b/coq
index 0b04a8c7..fcf744fd 100755
--- a/coq
+++ b/coq
@@ -12,4 +12,4 @@ make -q ${1}o || {
done)
}
-"${COQBIN}coqide" $INCLUDES $1 && make ${1}o
+"${COQBIN}coqide" -async-proofs off $INCLUDES $1 && make ${1}o
diff --git a/cparser/Ceval.ml b/cparser/Ceval.ml
index 58dea5f4..ecf83779 100644
--- a/cparser/Ceval.ml
+++ b/cparser/Ceval.ml
@@ -271,7 +271,7 @@ let constant_expr env ty e =
try
match unroll env ty, cast env ty (expr env e) with
| TInt(ik, _), I n -> Some(CInt(n, ik, ""))
- | TPtr(_, _), I n -> Some(CInt(n, IInt, ""))
+ | TPtr(_, _), I n -> Some(CInt(n, ptr_t_ikind (), ""))
| (TArray(_, _, _) | TPtr(_, _)), S s -> Some(CStr s)
| (TArray(_, _, _) | TPtr(_, _)), WS s -> Some(CWStr s)
| TEnum(_, _), I n -> Some(CInt(n, enum_ikind, ""))
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index 7a2f4828..3467c092 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -836,6 +836,12 @@ let is_anonymous_composite = function
| TUnion (id,_) -> id.C.name = ""
| _ -> false
+let is_anonymous_type = function
+ | TEnum (id,_)
+ | TStruct (id,_)
+ | TUnion (id,_) -> id.C.name = ""
+ | _ -> false
+
let is_function_pointer_type env t =
match unroll env t with
| TPtr (ty, _) -> is_function_type env ty
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index f6c4627d..2ddee78c 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -174,6 +174,8 @@ val is_function_pointer_type : Env.t -> typ -> bool
(* Is type a pointer to function type? *)
val is_anonymous_composite : typ -> bool
(* Is type an anonymous composite? *)
+val is_anonymous_type : typ -> bool
+ (* Is the type an anonymous composite or enum *)
val is_qualified_array : typ -> bool
(* Does the type contain a qualified array type (e.g. int[const 5])? *)
val pointer_arithmetic_ok : Env.t -> typ -> bool
diff --git a/cparser/Diagnostics.ml b/cparser/Diagnostics.ml
index 012e4b66..7957375c 100644
--- a/cparser/Diagnostics.ml
+++ b/cparser/Diagnostics.ml
@@ -104,30 +104,46 @@ type warning_type =
| Reduced_alignment
| Non_linear_cond_expr
+(* List of all warnings with default status.
+ "true" means the warning is active by default.
+ "false" means the warning is off by default. *)
+let all_warnings =
+ [ (Unnamed, true);
+ (Unknown_attribute, true);
+ (Zero_length_array, false);
+ (Celeven_extension, false);
+ (Gnu_empty_struct, true);
+ (Missing_declarations, true);
+ (Constant_conversion, true);
+ (Int_conversion, true);
+ (Varargs, true);
+ (Implicit_function_declaration, true);
+ (Pointer_type_mismatch, true);
+ (Compare_distinct_pointer_types, true);
+ (Implicit_int, true);
+ (Main_return_type, true);
+ (Invalid_noreturn, true);
+ (Return_type, true);
+ (Literal_range, true);
+ (Unknown_pragmas, false);
+ (CompCert_conformance, false);
+ (Inline_asm_sdump, true);
+ (Unused_variable, false);
+ (Unused_parameter, false);
+ (Wrong_ais_parameter, true);
+ (Unused_ais_parameter, true);
+ (Ignored_attributes, true);
+ (Extern_after_definition, true);
+ (Static_in_inline, true);
+ (Flexible_array_extensions, false);
+ (Tentative_incomplete_static, false);
+ (Reduced_alignment, false);
+ (Non_linear_cond_expr, false);
+ ]
+
(* List of active warnings *)
-let active_warnings: warning_type list ref = ref [
- Unnamed;
- Unknown_attribute;
- Gnu_empty_struct;
- Missing_declarations;
- Constant_conversion;
- Int_conversion;
- Varargs;
- Implicit_function_declaration;
- Pointer_type_mismatch;
- Compare_distinct_pointer_types;
- Implicit_int;
- Main_return_type;
- Invalid_noreturn;
- Return_type;
- Literal_range;
- Inline_asm_sdump;
- Wrong_ais_parameter;
- Unused_ais_parameter;
- Ignored_attributes;
- Extern_after_definition;
- Static_in_inline;
-]
+let active_warnings: warning_type list ref =
+ ref (List.map fst (List.filter snd all_warnings))
(* List of errors treated as warning *)
let error_warnings: warning_type list ref = ref []
@@ -188,76 +204,14 @@ let warning_not_as_error w () =
(* Activate all warnings *)
let wall () =
- active_warnings:=[
- Unnamed;
- Unknown_attribute;
- Zero_length_array;
- Celeven_extension;
- Gnu_empty_struct;
- Missing_declarations;
- Constant_conversion;
- Int_conversion;
- Varargs;
- Implicit_function_declaration;
- Pointer_type_mismatch;
- Compare_distinct_pointer_types;
- Implicit_int;
- Main_return_type;
- Invalid_noreturn;
- Return_type;
- Literal_range;
- Unknown_pragmas;
- CompCert_conformance;
- Inline_asm_sdump;
- Unused_variable;
- Unused_parameter;
- Wrong_ais_parameter;
- Ignored_attributes;
- Extern_after_definition;
- Static_in_inline;
- Flexible_array_extensions;
- Tentative_incomplete_static;
- Reduced_alignment;
- Non_linear_cond_expr;
- ]
+ active_warnings:= List.map fst all_warnings
let wnothing () =
active_warnings :=[]
(* Make all warnings an error *)
let werror () =
- error_warnings:=[
- Unnamed;
- Unknown_attribute;
- Zero_length_array;
- Celeven_extension;
- Gnu_empty_struct;
- Missing_declarations;
- Constant_conversion;
- Int_conversion;
- Varargs;
- Implicit_function_declaration;
- Pointer_type_mismatch;
- Compare_distinct_pointer_types;
- Implicit_int;
- Main_return_type;
- Invalid_noreturn;
- Return_type;
- Literal_range;
- Unknown_pragmas;
- CompCert_conformance;
- Inline_asm_sdump;
- Unused_variable;
- Wrong_ais_parameter;
- Unused_ais_parameter;
- Ignored_attributes;
- Extern_after_definition;
- Static_in_inline;
- Flexible_array_extensions;
- Tentative_incomplete_static;
- Reduced_alignment;
- Non_linear_cond_expr;
- ]
+ error_warnings:= List.map fst all_warnings
(* Generate the warning key for the message *)
let key_of_warning w =
@@ -411,37 +365,7 @@ let error_option w =
Exact ("-Wno-error="^key), Unit ( warning_not_as_error w)]
let warning_options =
- error_option Unnamed @
- error_option Unknown_attribute @
- error_option Zero_length_array @
- error_option Celeven_extension @
- error_option Gnu_empty_struct @
- error_option Missing_declarations @
- error_option Constant_conversion @
- error_option Int_conversion @
- error_option Varargs @
- error_option Implicit_function_declaration @
- error_option Pointer_type_mismatch @
- error_option Compare_distinct_pointer_types @
- error_option Implicit_int @
- error_option Main_return_type @
- error_option Invalid_noreturn @
- error_option Return_type @
- error_option Literal_range @
- error_option Unknown_pragmas @
- error_option CompCert_conformance @
- error_option Inline_asm_sdump @
- error_option Unused_variable @
- error_option Unused_parameter @
- error_option Wrong_ais_parameter @
- error_option Unused_ais_parameter @
- error_option Ignored_attributes @
- error_option Extern_after_definition @
- error_option Static_in_inline @
- error_option Flexible_array_extensions @
- error_option Tentative_incomplete_static @
- error_option Reduced_alignment @
- error_option Non_linear_cond_expr @
+ List.concat (List.map (fun (w, active) -> error_option w) all_warnings) @
[Exact ("-Wfatal-errors"), Set error_fatal;
Exact ("-fdiagnostics-color"), Ignore; (* Either output supports it or no color *)
Exact ("-fno-diagnostics-color"), Unset color_diagnostics;
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 3797164d..9e17cb7e 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -21,7 +21,7 @@ open Machine
open Cabs
open C
open Diagnostics
-open !Cutil
+open! Cutil
(** * Utility functions *)
@@ -39,7 +39,16 @@ let warning loc =
let print_typ env fmt ty =
match ty with
| TNamed _ ->
- Format.fprintf fmt "'%a' (aka '%a')" Cprint.typ_raw ty Cprint.typ_raw (unroll env ty)
+ Format.fprintf fmt "'%a'" Cprint.typ_raw ty;
+ let ty' = unroll env ty in
+ if not (is_anonymous_type ty')
+ then Format.fprintf fmt " (aka '%a')" Cprint.typ_raw ty'
+ | TStruct (id,_) when id.C.name = "" ->
+ Format.fprintf fmt "'struct <anonymous>'"
+ | TUnion (id,_) when id.C.name = "" ->
+ Format.fprintf fmt "'union <anonymous>'"
+ | TEnum (id,_) when id.C.name = "" ->
+ Format.fprintf fmt "'enum <anonymous>'"
| _ -> Format.fprintf fmt "'%a'" Cprint.typ_raw ty
let pp_field fmt id =
@@ -172,7 +181,7 @@ let combine_toplevel_definitions loc env s old_sto old_ty sto ty =
error loc "static declaration of '%s' follows non-static declaration" s;
sto
| Storage_static,_ -> Storage_static (* Static stays static *)
- | Storage_extern,_ -> sto
+ | Storage_extern,_ -> if is_function_type env new_ty then Storage_extern else sto
| Storage_default,Storage_extern ->
if is_global_defined s && is_function_type env ty then
warning loc Extern_after_definition "this extern declaration follows a non-extern definition and is ignored";
@@ -443,7 +452,8 @@ let elab_constant loc = function
let (v, fk) = elab_float_constant f in
CFloat(v, fk)
| CONST_CHAR(wide, s) ->
- CInt(elab_char_constant loc wide s, IInt, "")
+ let ikind = if wide then wchar_ikind () else IInt in
+ CInt(elab_char_constant loc wide s, ikind, "")
| CONST_STRING(wide, s) ->
elab_string_literal loc wide s
@@ -1056,7 +1066,7 @@ and elab_struct_or_union_info kind loc env members attrs =
| fld :: rem ->
if wrap incomplete_type loc env' fld.fld_typ then
(* Must be fatal otherwise we get problems constructing the init *)
- fatal_error loc "member '%a' has incomplete type" pp_field fld.fld_name;
+ fatal_error loc "member '%a' has incomplete type %a" pp_field fld.fld_name (print_typ env) fld.fld_typ;
if wrap contains_flex_array_mem loc env' fld.fld_typ && kind = Struct then
warning loc Flexible_array_extensions "%a may not be used as a struct member due to flexible array member" (print_typ env) fld.fld_typ;
check_reduced_alignment loc env' fld.fld_typ;
@@ -1611,7 +1621,7 @@ end;
try
elab_item (I.top env root ty_root) ie []
with No_default_init ->
- error loc "variable has incomplete type %a" Cprint.typ ty_root;
+ error loc "variable has incomplete type %a" (print_typ env) ty_root;
raise Exit
(* Elaboration of a top-level initializer *)
@@ -1844,7 +1854,12 @@ let elab_expr ctx loc env a =
having declared it *)
match a1 with
| VARIABLE n when not (Env.ident_is_bound env n) ->
- warning Implicit_function_declaration "implicit declaration of function '%s' is invalid in C99" n;
+ let is_builtin = String.length n > 10
+ && String.sub n 0 10 = "__builtin_" in
+ if is_builtin then
+ error "use of unknown builtin '%s'" n
+ else
+ warning Implicit_function_declaration "implicit declaration of function '%s' is invalid in C99" n;
let ty = TFun(TInt(IInt, []), None, false, []) in
(* Check against other definitions and enter in env *)
let (id, sto, env, ty, linkage) =
@@ -1909,6 +1924,8 @@ let elab_expr ctx loc env a =
| CAST ((spec, dcl), ie) ->
let (ty, env) = elab_type loc env spec dcl in
+ if not (is_array_type env ty) && incomplete_type env ty then
+ fatal_error "ill-formed compound literal with incomplete type %a" (print_typ env) ty;
begin match elab_initializer loc env "<compound literal>" ty ie with
| (ty', Some i) -> { edesc = ECompound(ty', i); etyp = ty' },env
| (ty', None) -> fatal_error "ill-formed compound literal"
@@ -2411,8 +2428,8 @@ let enter_typedef loc env sto (s, ty, init) =
env
end
else begin
- error loc "typedef redefinition with different types (%a vs %a)"
- (print_typ env) ty (print_typ env) ty';
+ error loc "redefinition of typedef '%s' with different type (%a vs %a)"
+ s (print_typ env) ty (print_typ env) ty';
env
end
| _ ->
@@ -2425,9 +2442,10 @@ let enter_typedef loc env sto (s, ty, init) =
let enter_decdef local nonstatic_inline loc sto (decls, env) (s, ty, init) =
let isfun = is_function_type env ty in
+ let has_init = init <> NO_INIT in
if sto = Storage_register && has_std_alignas env ty then
error loc "alignment specified for 'register' object '%s'" s;
- if sto = Storage_extern && init <> NO_INIT then
+ if sto = Storage_extern && has_init then
error loc "'extern' declaration variable has an initializer";
if local && isfun then begin
match sto with
@@ -2451,10 +2469,14 @@ let enter_decdef local nonstatic_inline loc sto (decls, env) (s, ty, init) =
initializer can refer to the ident *)
let (id, sto', env1, ty, linkage) =
enter_or_refine_ident local loc env s sto1 ty in
- if init <> NO_INIT && not local then
+ if has_init && not local then
add_global_define loc s;
- if not isfun && is_void_type env ty then
- fatal_error loc "'%s' has incomplete type" s;
+ (* check if the type is void or incomplete and the declaration is initialized *)
+ if not isfun then begin
+ let incomplete_init = not (is_array_type env1 ty) && wrap incomplete_type loc env1 ty && has_init in
+ if is_void_type env1 ty || incomplete_init then
+ fatal_error loc "variable '%s' has incomplete type %a" s (print_typ env) ty;
+ end;
(* process the initializer *)
let (ty', init') = elab_initializer loc env1 s ty init in
(* update environment with refined type *)
@@ -2465,7 +2487,7 @@ let enter_decdef local nonstatic_inline loc sto (decls, env) (s, ty, init) =
warning loc Tentative_incomplete_static "tentative static definition with incomplete type";
end
else if local && sto' <> Storage_extern then
- error loc "variable has incomplete type %a" (print_typ env) ty';
+ error loc "variable '%s' has incomplete type %a" s (print_typ env) ty';
(* check if alignment is reduced *)
check_reduced_alignment loc env ty';
(* check for static variables in nonstatic inline functions *)
@@ -2659,10 +2681,10 @@ let elab_fundef genv spec name defs body loc =
and additionally they should have an identifier. In both cases a fatal
error is raised in order to avoid problems at later places. *)
let add_param env (id, ty) =
- if wrap incomplete_type loc env ty then
- fatal_error loc "parameter has incomplete type";
if id.C.name = "" then
fatal_error loc "parameter name omitted";
+ if wrap incomplete_type loc env ty then
+ fatal_error loc "parameter '%s' has incomplete type %a" id.C.name (print_typ env) ty;
Env.add_ident env id Storage_default ty
in
(* Enter parameters and extra declarations in the local environment.
diff --git a/cparser/Lexer.mll b/cparser/Lexer.mll
index 346477b5..e44a330f 100644
--- a/cparser/Lexer.mll
+++ b/cparser/Lexer.mll
@@ -177,7 +177,7 @@ let identifier_nondigit =
let identifier = identifier_nondigit (identifier_nondigit|digit)*
(* Whitespaces *)
-let whitespace_char_no_newline = [' ' '\t' '\012' '\r']
+let whitespace_char_no_newline = [' ' '\t' '\011' '\012' '\r']
(* Integer constants *)
let nonzero_digit = ['1'-'9']
diff --git a/debug/DwarfPrinter.ml b/debug/DwarfPrinter.ml
index 9a24041b..2cb8c7d9 100644
--- a/debug/DwarfPrinter.ml
+++ b/debug/DwarfPrinter.ml
@@ -602,8 +602,13 @@ module DwarfPrinter(Target: DWARF_TARGET):
print_sleb128 oc "" 0;
print_label oc debug_end (* End of the debug section *)
- let print_location_entry oc c_low l =
+ let print_location_entry oc needs_base c_low l =
print_label oc (loc_to_label l.loc_id);
+ (* If we have multiple ranges per compilation unit we need to specify a base address for the location *)
+ if needs_base then begin
+ fprintf oc " %s -1\n" address;
+ fprintf oc " %s %a\n" address label c_low;
+ end;
List.iter (fun (b,e,loc) ->
fprintf oc " %s %a-%a\n" address label b label c_low;
fprintf oc " %s %a-%a\n" address label e label c_low;
@@ -621,11 +626,11 @@ module DwarfPrinter(Target: DWARF_TARGET):
fprintf oc " %s 0\n" address
- let print_location_list oc (c_low,l) =
- let f = match c_low with
- | Some s -> print_location_entry oc s
- | None -> print_location_entry_abs oc in
- List.iter f l
+ let print_location_list oc needs_base l =
+ let f l = match l.loc_sec_begin with
+ | Some s -> print_location_entry oc needs_base s l
+ | None -> print_location_entry_abs oc l in
+ List.iter f l
let list_opt l f =
match l with
@@ -635,15 +640,15 @@ module DwarfPrinter(Target: DWARF_TARGET):
let print_diab_entries oc entries =
let abbrev_start = new_label () in
abbrev_start_addr := abbrev_start;
- List.iter (fun e -> compute_abbrev e.entry) entries;
+ List.iter (fun e -> compute_abbrev e.diab_entry) entries;
print_abbrev oc;
List.iter (fun e ->
let name = if e.section_name <> ".text" then Some e.section_name else None in
section oc (Section_debug_info name);
- print_debug_info oc e.start_label e.line_label e.entry) entries;
- if List.exists (fun e -> match e.dlocs with _,[] -> false | _,_ -> true) entries then begin
+ print_debug_info oc e.start_label e.line_label e.diab_entry) entries;
+ if List.exists (fun e -> match e.diab_locs with [] -> false | _ -> true) entries then begin
section oc Section_debug_loc;
- List.iter (fun e -> print_location_list oc e.dlocs) entries
+ List.iter (fun e -> print_location_list oc false e.diab_locs) entries
end
let print_ranges oc r =
@@ -665,8 +670,8 @@ module DwarfPrinter(Target: DWARF_TARGET):
fprintf oc " %s 0\n" address;
fprintf oc " %s 0\n" address) r
- let print_gnu_entries oc cp (lpc,loc) s r =
- compute_abbrev cp;
+ let print_gnu_entries oc entries =
+ compute_abbrev entries.gnu_entry;
let line_start = new_label ()
and start = new_label ()
and abbrev_start = new_label ()
@@ -674,18 +679,18 @@ module DwarfPrinter(Target: DWARF_TARGET):
debug_ranges_addr := range_label;
abbrev_start_addr := abbrev_start;
section oc (Section_debug_info None);
- print_debug_info oc start line_start cp;
+ print_debug_info oc start line_start entries.gnu_entry;
print_abbrev oc;
- list_opt loc (fun () ->
+ list_opt entries.gnu_locs (fun () ->
section oc Section_debug_loc;
- print_location_list oc (lpc,loc));
- list_opt r (fun () ->
- print_ranges oc r);
+ print_location_list oc entries.several_secs entries.gnu_locs);
+ list_opt entries.range_table (fun () ->
+ print_ranges oc entries.range_table);
section oc (Section_debug_line None);
print_label oc line_start;
- list_opt s (fun () ->
+ list_opt entries.string_table (fun () ->
section oc Section_debug_str;
- let s = List.sort (fun (a,_) (b,_) -> compare a b) s in
+ let s = List.sort (fun (a,_) (b,_) -> compare a b) entries.string_table in
List.iter (fun (id,s) ->
print_label oc (loc_to_label id);
fprintf oc " .asciz %S\n" s) s)
@@ -698,6 +703,6 @@ module DwarfPrinter(Target: DWARF_TARGET):
Hashtbl.clear loc_labels;
match debug with
| Diab entries -> print_diab_entries oc entries
- | Gnu (cp,loc,s,r) -> print_gnu_entries oc cp loc s r
+ | Gnu entries -> print_gnu_entries oc entries
end
diff --git a/debug/DwarfPrinter.mli b/debug/DwarfPrinter.mli
index e1e10601..78dc05fb 100644
--- a/debug/DwarfPrinter.mli
+++ b/debug/DwarfPrinter.mli
@@ -12,7 +12,7 @@
open DwarfTypes
-module DwarfPrinter: functor (Target: DWARF_TARGET) ->
+module DwarfPrinter: DWARF_TARGET ->
sig
val print_debug: out_channel -> debug_entries -> unit
end
diff --git a/debug/DwarfTypes.mli b/debug/DwarfTypes.mli
index 5a2bce3b..567c65cd 100644
--- a/debug/DwarfTypes.mli
+++ b/debug/DwarfTypes.mli
@@ -266,11 +266,13 @@ type dw_entry =
(* The type for the location list. *)
type location_entry =
- {
- loc: (address * address * location_value) list;
- loc_id: reference;
- }
-type dw_locations = constant option * location_entry list
+ {
+ loc: (address * address * location_value) list;
+ loc_id: reference;
+ loc_sec_begin : address option;
+ }
+
+type dw_locations = location_entry list
type range_entry =
| AddressRange of (address * address) list
@@ -285,13 +287,20 @@ type diab_entry =
section_name: string;
start_label: int;
line_label: int;
- entry: dw_entry;
- dlocs: dw_locations;
+ diab_entry: dw_entry;
+ diab_locs: dw_locations;
}
type diab_entries = diab_entry list
-type gnu_entries = dw_entry * dw_locations * dw_string * dw_ranges
+type gnu_entries =
+ {
+ string_table: dw_string;
+ range_table: dw_ranges;
+ gnu_locs: dw_locations;
+ gnu_entry: dw_entry;
+ several_secs: bool;
+ }
type debug_entries =
| Diab of diab_entries
diff --git a/debug/Dwarfgen.ml b/debug/Dwarfgen.ml
index e1b71f13..6c1d0846 100644
--- a/debug/Dwarfgen.ml
+++ b/debug/Dwarfgen.ml
@@ -408,7 +408,7 @@ module Dwarfgenaux (Target: TARGET) =
and lo = translate_label f_id lo in
hi,lo,range_entry_loc i.var_loc) l in
let id = next_id () in
- Some (LocRef id),[{loc = l;loc_id = id;}]
+ Some (LocRef id),[{loc_sec_begin = !current_section_start; loc = l;loc_id = id;}]
end
with Not_found -> None,[]
else
@@ -574,8 +574,8 @@ let diab_gen_compilation_section sec_name s defs acc =
section_name = s;
start_label = debug_start;
line_label = line_start;
- entry = cp;
- dlocs = Some low_pc,accu.locs;
+ diab_entry = cp;
+ diab_locs = accu.locs;
}::acc
let gen_diab_debug_info sec_name var_section : debug_entries =
@@ -643,6 +643,12 @@ let gen_gnu_debug_info sec_name var_section : debug_entries =
} in
let cp = new_entry (next_id ()) (DW_TAG_compile_unit cp) in
let cp = add_children cp (types@defs) in
- let loc_pc = if StringSet.cardinal sec > 1 then None else low_pc in
let string_table = Hashtbl.fold (fun s i acc -> (i,s)::acc) string_table [] in
- Gnu (cp,(loc_pc,accu.locs),string_table,snd accu.ranges)
+ let cp = {
+ string_table = string_table;
+ range_table = snd accu.ranges;
+ gnu_locs = accu.locs;
+ gnu_entry = cp;
+ several_secs = StringSet.cardinal sec > 1}
+ in
+ Gnu cp
diff --git a/doc/index.html b/doc/index.html
index 3a4cf6ba..631c5d99 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -24,7 +24,7 @@ a:active {color : Red; text-decoration : underline; }
<H1 align="center">The CompCert verified compiler</H1>
<H2 align="center">Commented Coq development</H2>
-<H3 align="center">Version 3.6, 2019-09-17</H3>
+<H3 align="center">Version 3.7, 2020-03-31</H3>
<H2>Introduction</H2>
@@ -101,6 +101,8 @@ See also: <A HREF="html/compcert.common.Memdata.html">Memdata</A> (in-memory rep
<LI> <A HREF="html/compcert.common.Determinism.html">Determinism</A>: determinism properties of small-step semantics.
<LI> <A HREF="html/compcert.powerpc.Op.html"><I>Op</I></A>: operators, addressing modes and their
semantics.
+<LI> <A HREF="html/compcert.common.Builtins.html">Builtins</A>: semantics of built-in functions. <BR>
+See also: <A HREF="html/compcert.common.Builtins0.html">Builtins0</A> (target-independent part), <A HREF="html/compcert.powerpc.Builtins1.html"><I>Builtins1</I></A> (target-dependent part).
<LI> <A HREF="html/compcert.common.Unityping.html">Unityping</A>: a solver for atomic unification constraints.
</UL>
diff --git a/driver/Clflags.ml b/driver/Clflags.ml
index cf1220d1..6986fb96 100644
--- a/driver/Clflags.ml
+++ b/driver/Clflags.ml
@@ -26,7 +26,11 @@ let option_ffloatconstprop = ref 2
let option_ftailcalls = ref true
let option_fconstprop = ref true
let option_fcse = ref true
+let option_fcse2 = ref true
let option_fredundancy = ref true
+let option_fduplicate = ref (-1)
+let option_finvertcond = ref true
+let option_ftracelinearize = ref false
let option_fpostpass = ref true
let option_fpostpass_sched = ref "list"
let option_fifconversion = ref true
@@ -74,4 +78,7 @@ let option_fglobaladdrtmp = ref false
let option_fglobaladdroffset = ref false
let option_fxsaddr = ref true
let option_faddx = ref false
-let option_fcoalesce_mem = ref true
+let option_fcoalesce_mem = ref true
+let option_fforward_moves = ref true
+let option_all_loads_nontrap = ref false
+let option_inline_auto_threshold = ref 0
diff --git a/driver/Compiler.v b/driver/Compiler.v
index d7784f7a..499feff2 100644
--- a/driver/Compiler.v
+++ b/driver/Compiler.v
@@ -41,8 +41,11 @@ Require Renumber.
Require Duplicate.
Require Constprop.
Require CSE.
+Require ForwardMoves.
+Require CSE2.
Require Deadcode.
Require Unusedglob.
+Require Allnontrap.
Require Allocation.
Require Tunneling.
Require Linearize.
@@ -63,8 +66,11 @@ Require Renumberproof.
Require Duplicateproof.
Require Constpropproof.
Require CSEproof.
+Require ForwardMovesproof.
+Require CSE2proof.
Require Deadcodeproof.
Require Unusedglobproof.
+Require Allnontrapproof.
Require Allocproof.
Require Tunnelingproof.
Require Linearizeproof.
@@ -128,7 +134,7 @@ Definition transf_rtl_program (f: RTL.program) : res Asm.program :=
@@ print (print_RTL 2)
@@ time "Renumbering" Renumber.transf_program
@@ print (print_RTL 3)
- @@@ time "Duplicating" Duplicate.transf_program
+ @@@ partial_if Compopts.optim_duplicate (time "Tail-duplicating" Duplicate.transf_program)
@@ print (print_RTL 4)
@@ total_if Compopts.optim_constprop (time "Constant propagation" Constprop.transf_program)
@@ print (print_RTL 5)
@@ -136,10 +142,16 @@ Definition transf_rtl_program (f: RTL.program) : res Asm.program :=
@@ print (print_RTL 6)
@@@ partial_if Compopts.optim_CSE (time "CSE" CSE.transf_program)
@@ print (print_RTL 7)
- @@@ partial_if Compopts.optim_redundancy (time "Redundancy elimination" Deadcode.transf_program)
+ @@ total_if Compopts.optim_CSE2 (time "CSE2" CSE2.transf_program)
@@ print (print_RTL 8)
- @@@ time "Unused globals" Unusedglob.transform_program
+ @@ total_if Compopts.optim_forward_moves ForwardMoves.transf_program
@@ print (print_RTL 9)
+ @@@ partial_if Compopts.optim_redundancy (time "Redundancy elimination" Deadcode.transf_program)
+ @@ print (print_RTL 10)
+ @@ total_if Compopts.all_loads_nontrap Allnontrap.transf_program
+ @@ print (print_RTL 11)
+ @@@ time "Unused globals" Unusedglob.transform_program
+ @@ print (print_RTL 12)
@@@ time "Register allocation" Allocation.transf_program
@@ print print_LTL
@@ time "Branch tunneling" Tunneling.tunnel_program
@@ -242,11 +254,14 @@ Definition CompCert's_passes :=
::: mkpass (match_if Compopts.optim_tailcalls Tailcallproof.match_prog)
::: mkpass Inliningproof.match_prog
::: mkpass Renumberproof.match_prog
- ::: mkpass Duplicateproof.match_prog
+ ::: mkpass (match_if Compopts.optim_duplicate Duplicateproof.match_prog)
::: mkpass (match_if Compopts.optim_constprop Constpropproof.match_prog)
::: mkpass (match_if Compopts.optim_constprop Renumberproof.match_prog)
::: mkpass (match_if Compopts.optim_CSE CSEproof.match_prog)
+ ::: mkpass (match_if Compopts.optim_CSE2 CSE2proof.match_prog)
+ ::: mkpass (match_if Compopts.optim_forward_moves ForwardMovesproof.match_prog)
::: mkpass (match_if Compopts.optim_redundancy Deadcodeproof.match_prog)
+ ::: mkpass (match_if Compopts.all_loads_nontrap Allnontrapproof.match_prog)
::: mkpass Unusedglobproof.match_prog
::: mkpass Allocproof.match_prog
::: mkpass Tunnelingproof.match_prog
@@ -286,12 +301,15 @@ Proof.
set (p7 := total_if optim_tailcalls Tailcall.transf_program p6) in *.
destruct (Inlining.transf_program p7) as [p8|e] eqn:P8; simpl in T; try discriminate.
set (p9 := Renumber.transf_program p8) in *.
- destruct (Duplicate.transf_program p9) as [p10|e] eqn:P10; simpl in T; try discriminate.
+ destruct (partial_if optim_duplicate Duplicate.transf_program p9) as [p10|e] eqn:P10; simpl in T; try discriminate.
set (p11 := total_if optim_constprop Constprop.transf_program p10) in *.
set (p12 := total_if optim_constprop Renumber.transf_program p11) in *.
destruct (partial_if optim_CSE CSE.transf_program p12) as [p13|e] eqn:P13; simpl in T; try discriminate.
- destruct (partial_if optim_redundancy Deadcode.transf_program p13) as [p14|e] eqn:P14; simpl in T; try discriminate.
- destruct (Unusedglob.transform_program p14) as [p15|e] eqn:P15; simpl in T; try discriminate.
+ set (p13bis := total_if optim_CSE2 CSE2.transf_program p13) in *.
+ set (p13ter := total_if optim_forward_moves ForwardMoves.transf_program p13bis) in *.
+ destruct (partial_if optim_redundancy Deadcode.transf_program p13ter) as [p14|e] eqn:P14; simpl in T; try discriminate.
+ set (p14bis := total_if all_loads_nontrap Allnontrap.transf_program p14) in *.
+ destruct (Unusedglob.transform_program p14bis) as [p15|e] eqn:P15; simpl in T; try discriminate.
destruct (Allocation.transf_program p15) as [p16|e] eqn:P16; simpl in T; try discriminate.
set (p17 := Tunneling.tunnel_program p16) in *.
destruct (Linearize.transf_program p17) as [p18|e] eqn:P18; simpl in T; try discriminate.
@@ -308,11 +326,14 @@ Proof.
exists p7; split. apply total_if_match. apply Tailcallproof.transf_program_match.
exists p8; split. apply Inliningproof.transf_program_match; auto.
exists p9; split. apply Renumberproof.transf_program_match; auto.
- exists p10; split. apply Duplicateproof.transf_program_match; auto.
+ exists p10; split. eapply partial_if_match; eauto. apply Duplicateproof.transf_program_match; auto.
exists p11; split. apply total_if_match. apply Constpropproof.transf_program_match.
exists p12; split. apply total_if_match. apply Renumberproof.transf_program_match.
exists p13; split. eapply partial_if_match; eauto. apply CSEproof.transf_program_match.
+ exists p13bis; split. apply total_if_match. apply CSE2proof.transf_program_match.
+ exists p13ter; split. eapply total_if_match; eauto. apply ForwardMovesproof.transf_program_match.
exists p14; split. eapply partial_if_match; eauto. apply Deadcodeproof.transf_program_match.
+ exists p14bis; split. eapply total_if_match; eauto. apply Allnontrapproof.transf_program_match.
exists p15; split. apply Unusedglobproof.transf_program_match; auto.
exists p16; split. apply Allocproof.transf_program_match; auto.
exists p17; split. apply Tunnelingproof.transf_program_match.
@@ -371,7 +392,7 @@ Ltac DestructM :=
destruct H as (p & M & MM); clear H
end.
repeat DestructM. subst tp.
- assert (F: forward_simulation (Cstrategy.semantics p) (Asm.semantics p22)).
+ assert (F: forward_simulation (Cstrategy.semantics p) (Asm.semantics p25)).
{
eapply compose_forward_simulations.
eapply SimplExprproof.transl_program_correct; eassumption.
@@ -390,7 +411,8 @@ Ltac DestructM :=
eapply compose_forward_simulations.
eapply Inliningproof.transf_program_correct; eassumption.
eapply compose_forward_simulations. eapply Renumberproof.transf_program_correct; eassumption.
- eapply compose_forward_simulations. eapply Duplicateproof.transf_program_correct; eassumption.
+ eapply compose_forward_simulations.
+ eapply match_if_simulation. eassumption. exact Duplicateproof.transf_program_correct.
eapply compose_forward_simulations.
eapply match_if_simulation. eassumption. exact Constpropproof.transf_program_correct.
eapply compose_forward_simulations.
@@ -398,8 +420,14 @@ Ltac DestructM :=
eapply compose_forward_simulations.
eapply match_if_simulation. eassumption. exact CSEproof.transf_program_correct.
eapply compose_forward_simulations.
+ eapply match_if_simulation. eassumption. exact CSE2proof.transf_program_correct.
+ eapply compose_forward_simulations.
+ eapply match_if_simulation. eassumption. exact ForwardMovesproof.transf_program_correct; eassumption.
+ eapply compose_forward_simulations.
eapply match_if_simulation. eassumption. exact Deadcodeproof.transf_program_correct; eassumption.
eapply compose_forward_simulations.
+ eapply match_if_simulation. eassumption. exact Allnontrapproof.transf_program_correct.
+ eapply compose_forward_simulations.
eapply Unusedglobproof.transf_program_correct; eassumption.
eapply compose_forward_simulations.
eapply Allocproof.transf_program_correct; eassumption.
diff --git a/driver/Compopts.v b/driver/Compopts.v
index 4f86901b..848657e5 100644
--- a/driver/Compopts.v
+++ b/driver/Compopts.v
@@ -27,6 +27,9 @@ Parameter generate_float_constants: unit -> bool.
(** For value analysis. Currently always false. *)
Parameter va_strict: unit -> bool.
+(** Flag -fduplicate. Branch prediction annotation + tail duplication *)
+Parameter optim_duplicate: unit -> bool.
+
(** Flag -ftailcalls. For tail call optimization. *)
Parameter optim_tailcalls: unit -> bool.
@@ -36,6 +39,9 @@ Parameter optim_constprop: unit -> bool.
(** Flag -fcse. For common subexpression elimination. *)
Parameter optim_CSE: unit -> bool.
+(** Flag -fcse2. For DMonniaux's common subexpression elimination. *)
+Parameter optim_CSE2: unit -> bool.
+
(** Flag -fredundancy. For dead code elimination. *)
Parameter optim_redundancy: unit -> bool.
@@ -63,6 +69,12 @@ Parameter thumb: unit -> bool.
(** Flag -g. For insertion of debugging information. *)
Parameter debug: unit -> bool.
+(** Flag -fall-loads-nontrap. Turn user loads into non trapping. *)
+Parameter all_loads_nontrap: unit -> bool.
+
+(** Flag -fforward-moves. Forward moves after CSE. *)
+Parameter optim_forward_moves: unit -> bool.
+
(* TODO is there a more appropriate place? *)
Require Import Coqlib.
Definition time {A B: Type} (name: string) (f: A -> B) : A -> B := f.
diff --git a/driver/Driver.ml b/driver/Driver.ml
index 288bb436..388482a0 100644
--- a/driver/Driver.ml
+++ b/driver/Driver.ml
@@ -190,15 +190,27 @@ Processing options:
-Os Optimize for code size in preference to code speed
-Obranchless Optimize to generate fewer conditional branches; try to produce
branch-free instruction sequences as much as possible
+ -finline-auto-threshold n Inline functions under size n
-ftailcalls Optimize function calls in tail position [on]
-fconst-prop Perform global constant propagation [on]
-ffloat-const-prop <n> Control constant propagation of floats
(<n>=0: none, <n>=1: limited, <n>=2: full; default is full)
-fcse Perform common subexpression elimination [on]
+ -fcse2 Perform inter-loop common subexpression elimination [on]
-fredundancy Perform redundancy elimination [on]
-fpostpass Perform postpass scheduling (only for K1 architecture) [on]
-fpostpass= <optim> Perform postpass scheduling with the specified optimization [list]
(<optim>=list: list scheduling, <optim>=ilp: ILP, <optim>=greedy: just packing bundles)
+ -fduplicate <nb_nodes> Perform tail duplication to form superblocks on predicted traces
+ nb_nodes control the heuristic deciding to duplicate or not
+ A value of -1 desactivates the entire pass (including branch prediction)
+ A value of 0 desactivates the duplication (but activates the branch prediction)
+ FIXME : this is desactivated by default for now
+ -finvertcond Invert conditions based on predicted paths (to prefer fallthrough).
+ Requires -fduplicate to be also activated [on]
+ -ftracelinearize Linearizes based on the traces identified by duplicate phase
+ It is heavily recommended to activate -finvertcond with this pass [off]
+ -fforward-moves Forward moves after CSE
-finline Perform inlining of functions [on]
-finline-functions-called-once Integrate functions only required by their
single caller [on]
@@ -257,8 +269,10 @@ let dump_mnemonics destfile =
exit 0
let optimization_options = [
- option_ftailcalls; option_fifconversion; option_fconstprop; option_fcse;
- option_fpostpass; option_fredundancy; option_finline_functions_called_once;
+ option_ftailcalls; option_fifconversion; option_fconstprop;
+ option_fcse; option_fcse2;
+ option_fpostpass;
+ option_fredundancy; option_finline; option_finline_functions_called_once;
]
let set_all opts () = List.iter (fun r -> r := true) opts
@@ -313,6 +327,7 @@ let cmdline_actions =
_Regexp "-O[123]$", Unit (set_all optimization_options);
Exact "-Os", Set option_Osize;
Exact "-Obranchless", Set option_Obranchless;
+ Exact "-finline-auto-threshold", Integer (fun n -> option_inline_auto_threshold := n);
Exact "-fsmall-data", Integer(fun n -> option_small_data := n);
Exact "-fsmall-const", Integer(fun n -> option_small_const := n);
Exact "-ffloat-const-prop", Integer(fun n -> option_ffloatconstprop := n);
@@ -381,8 +396,12 @@ let cmdline_actions =
@ f_opt "if-conversion" option_fifconversion
@ f_opt "const-prop" option_fconstprop
@ f_opt "cse" option_fcse
+ @ f_opt "cse2" option_fcse2
@ f_opt "redundancy" option_fredundancy
@ f_opt "postpass" option_fpostpass
+ @ [ Exact "-fduplicate", Integer (fun n -> option_fduplicate := n) ]
+ @ f_opt "invertcond" option_finvertcond
+ @ f_opt "tracelinearize" option_ftracelinearize
@ f_opt_str "postpass" option_fpostpass option_fpostpass_sched
@ f_opt "inline" option_finline
@ f_opt "inline-functions-called-once" option_finline_functions_called_once
@@ -391,6 +410,8 @@ let cmdline_actions =
@ f_opt "xsaddr" option_fxsaddr
@ f_opt "addx" option_faddx
@ f_opt "coalesce-mem" option_fcoalesce_mem
+ @ f_opt "all-loads-nontrap" option_all_loads_nontrap
+ @ f_opt "forward-moves" option_fforward_moves
(* Code generation options *)
@ f_opt "fpu" option_ffpu
@ f_opt "sse" option_ffpu (* backward compatibility *)
diff --git a/driver/Interp.ml b/driver/Interp.ml
index a6841460..d4286779 100644
--- a/driver/Interp.ml
+++ b/driver/Interp.ml
@@ -15,12 +15,12 @@
open Format
open Camlcoq
open AST
-open !Integers
+open! Integers
open Values
open Memory
open Globalenvs
open Events
-open Ctypes
+open! Ctypes
open Csyntax
open Csem
diff --git a/exportclight/ExportClight.ml b/exportclight/ExportClight.ml
index b124586a..c9d6fced 100644
--- a/exportclight/ExportClight.ml
+++ b/exportclight/ExportClight.ml
@@ -18,7 +18,7 @@
open Format
open Camlcoq
open AST
-open Ctypes
+open! Ctypes
open Cop
open Clight
@@ -221,6 +221,14 @@ let asttype p t =
| AST.Tany32 -> "AST.Tany32"
| AST.Tany64 -> "AST.Tany64")
+let astrettype p = function
+ | AST.Tret t -> asttype p t
+ | AST.Tvoid -> fprintf p "AST.Tvoid"
+ | AST.Tint8signed -> fprintf p "AST.Tint8signed"
+ | AST.Tint8unsigned -> fprintf p "AST.Tint8unsigned"
+ | AST.Tint16signed -> fprintf p "AST.Tint16signed"
+ | AST.Tint16unsigned -> fprintf p "AST.Tint16unsigned"
+
let name_of_chunk = function
| Mint8signed -> "Mint8signed"
| Mint8unsigned -> "Mint8unsigned"
@@ -236,7 +244,7 @@ let name_of_chunk = function
let signatur p sg =
fprintf p "@[<hov 2>(mksignature@ %a@ %a@ %a)@]"
(print_list asttype) sg.sig_args
- (print_option asttype) sg.sig_res
+ astrettype sg.sig_res
callconv sg.sig_cc
let assertions = ref ([]: (string * typ list) list)
@@ -381,7 +389,7 @@ and lblstmts p = function
(print_option coqZ) lbl stmt s lblstmts ls
let print_function p (id, f) =
- fprintf p "Definition f_%s := {|@ " (extern_atom id);
+ fprintf p "Definition f_%s := {|@ " (sanitize (extern_atom id));
fprintf p " fn_return := %a;@ " typ f.fn_return;
fprintf p " fn_callconv := %a;@ " callconv f.fn_callconv;
fprintf p " fn_params := %a;@ " (print_list (print_pair ident typ)) f.fn_params;
@@ -402,7 +410,7 @@ let init_data p = function
| Init_addrof(id,ofs) -> fprintf p "Init_addrof %a %a" ident id coqptrofs ofs
let print_variable p (id, v) =
- fprintf p "Definition v_%s := {|@ " (extern_atom id);
+ fprintf p "Definition v_%s := {|@ " (sanitize (extern_atom id));
fprintf p " gvar_info := %a;@ " typ v.gvar_info;
fprintf p " gvar_init := %a;@ " (print_list init_data) v.gvar_init;
fprintf p " gvar_readonly := %B;@ " v.gvar_readonly;
@@ -417,12 +425,12 @@ let print_globdef p (id, gd) =
let print_ident_globdef p = function
| (id, Gfun(Ctypes.Internal f)) ->
- fprintf p "(%a, Gfun(Internal f_%s))" ident id (extern_atom id)
+ fprintf p "(%a, Gfun(Internal f_%s))" ident id (sanitize (extern_atom id))
| (id, Gfun(Ctypes.External(ef, targs, tres, cc))) ->
fprintf p "@[<hov 2>(%a,@ @[<hov 2>Gfun(External %a@ %a@ %a@ %a))@]@]"
ident id external_function ef typlist targs typ tres callconv cc
| (id, Gvar v) ->
- fprintf p "(%a, Gvar v_%s)" ident id (extern_atom id)
+ fprintf p "(%a, Gvar v_%s)" ident id (sanitize (extern_atom id))
(* Composite definitions *)
diff --git a/extraction/extraction.v b/extraction/extraction.v
index 23d4520f..9b568951 100644
--- a/extraction/extraction.v
+++ b/extraction/extraction.v
@@ -105,10 +105,14 @@ Extract Constant Compopts.generate_float_constants =>
"fun _ -> !Clflags.option_ffloatconstprop >= 2".
Extract Constant Compopts.optim_tailcalls =>
"fun _ -> !Clflags.option_ftailcalls".
+Extract Constant Compopts.optim_duplicate =>
+ "fun _ -> (if !Clflags.option_fduplicate = -1 then false else true)".
Extract Constant Compopts.optim_constprop =>
"fun _ -> !Clflags.option_fconstprop".
Extract Constant Compopts.optim_CSE =>
"fun _ -> !Clflags.option_fcse".
+Extract Constant Compopts.optim_CSE2 =>
+ "fun _ -> !Clflags.option_fcse2".
Extract Constant Compopts.optim_redundancy =>
"fun _ -> !Clflags.option_fredundancy".
Extract Constant Compopts.optim_postpass =>
@@ -127,6 +131,12 @@ Extract Constant Compopts.optim_addx =>
"fun _ -> !Clflags.option_faddx".
Extract Constant Compopts.optim_coalesce_mem =>
"fun _ -> !Clflags.option_fcoalesce_mem".
+Extract Constant Compopts.optim_forward_moves =>
+ "fun _ -> !Clflags.option_fforward_moves".
+Extract Constant Compopts.va_strict =>
+ "fun _ -> false".
+Extract Constant Compopts.all_loads_nontrap =>
+ "fun _ -> !Clflags.option_all_loads_nontrap".
(* Compiler *)
Extract Constant Compiler.print_Clight => "PrintClight.print_if".
diff --git a/lib/BoolEqual.v b/lib/BoolEqual.v
index c9e7bad5..e8c1d831 100644
--- a/lib/BoolEqual.v
+++ b/lib/BoolEqual.v
@@ -106,8 +106,8 @@ Ltac bool_eq_refl_case :=
end.
Ltac bool_eq_refl :=
- let H := fresh "Hrec" in let x := fresh "x" in
- fix H 1; intros x; destruct x; simpl; bool_eq_refl_case.
+ let Hrec := fresh "Hrec" in let x := fresh "x" in
+ fix Hrec 1; intros x; destruct x; simpl; bool_eq_refl_case.
Lemma false_not_true:
forall (P: Prop), false = true -> P.
@@ -124,7 +124,6 @@ Qed.
Ltac bool_eq_sound_case :=
match goal with
- | [ H: false = true |- _ ] => exact (false_not_true _ H)
| [ H: _ && _ = true |- _ ] => apply andb_prop in H; destruct H; bool_eq_sound_case
| [ H: proj_sumbool ?a = true |- _ ] => apply proj_sumbool_true in H; bool_eq_sound_case
| [ |- ?C ?x1 ?x2 ?x3 ?x4 = ?C ?y1 ?y2 ?y3 ?y4 ] => apply f_equal4; auto
@@ -137,7 +136,9 @@ Ltac bool_eq_sound_case :=
Ltac bool_eq_sound :=
let Hrec := fresh "Hrec" in let x := fresh "x" in let y := fresh "y" in
- fix Hrec 1; intros x y; destruct x, y; simpl; intro; bool_eq_sound_case.
+ let H := fresh "EQ" in
+ fix Hrec 1; intros x y; destruct x, y; intro H;
+ try (apply (false_not_true _ H)); simpl in H; bool_eq_sound_case.
Lemma dec_eq_from_bool_eq:
forall (A: Type) (f: A -> A -> bool)
diff --git a/lib/Integers.v b/lib/Integers.v
index 3e78ee60..246c708c 100644
--- a/lib/Integers.v
+++ b/lib/Integers.v
@@ -4,7 +4,7 @@
(* *)
(* Xavier Leroy, INRIA Paris-Rocquencourt *)
(* *)
-(* Copyright Institut National de Recherche en Informatique et en *)
+(* Copyright Institut National de Recherstestche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU General Public License as published by *)
(* the Free Software Foundation, either version 2 of the License, or *)
@@ -1194,6 +1194,34 @@ Proof.
rewrite <- half_modulus_modulus. apply unsigned_range.
Qed.
+Local Transparent repr.
+Lemma sign_bit_of_signed: forall x,
+ (testbit x (zwordsize - 1)) = lt x zero.
+Proof.
+ intro.
+ rewrite sign_bit_of_unsigned.
+ unfold lt.
+ unfold signed, unsigned.
+ simpl.
+ pose proof half_modulus_pos as HMOD.
+ destruct (zlt 0 half_modulus) as [HMOD' | HMOD'].
+ 2: omega.
+ clear HMOD'.
+ destruct (zlt (intval x) half_modulus) as [ LOW | HIGH].
+ {
+ destruct x as [ix RANGE].
+ simpl in *.
+ destruct (zlt ix 0). omega.
+ reflexivity.
+ }
+ destruct (zlt _ _) as [LOW' | HIGH']; trivial.
+ destruct x as [ix RANGE].
+ simpl in *.
+ rewrite half_modulus_modulus in *.
+ omega.
+Qed.
+Local Opaque repr.
+
Lemma bits_signed:
forall x i, 0 <= i ->
Z.testbit (signed x) i = testbit x (if zlt i zwordsize then i else zwordsize - 1).
@@ -2427,6 +2455,57 @@ Proof.
bit_solve. destruct (zlt (i + unsigned (sub iwordsize y)) zwordsize); auto.
Qed.
+Theorem shrx1_shr:
+ forall x,
+ ltu one (repr (zwordsize - 1)) = true ->
+ shrx x (repr 1) = shr (add x (shru x (repr (zwordsize - 1)))) (repr 1).
+Proof.
+ intros.
+ rewrite shrx_shr by assumption.
+ rewrite shl_mul_two_p.
+ rewrite mul_commut. rewrite mul_one.
+ change (repr 1) with one.
+ rewrite unsigned_one.
+ change (two_p 1) with 2.
+ unfold sub.
+ rewrite unsigned_one.
+ assert (0 <= 2 <= max_unsigned).
+ {
+ unfold max_unsigned, modulus.
+ unfold zwordsize in *.
+ unfold ltu in *.
+ rewrite unsigned_one in H.
+ rewrite unsigned_repr in H.
+ {
+ destruct (zlt 1 (Z.of_nat wordsize - 1)) as [ LT | NONE].
+ 2: discriminate.
+ clear H.
+ rewrite two_power_nat_two_p.
+ split.
+ omega.
+ set (w := (Z.of_nat wordsize)) in *.
+ assert ((two_p 2) <= (two_p w)) as MONO.
+ {
+ apply two_p_monotone.
+ omega.
+ }
+ change (two_p 2) with 4 in MONO.
+ omega.
+ }
+ generalize wordsize_max_unsigned.
+ fold zwordsize.
+ generalize wordsize_pos.
+ omega.
+ }
+ rewrite unsigned_repr by assumption.
+ simpl.
+ rewrite shru_lt_zero.
+ destruct (lt x zero).
+ reflexivity.
+ rewrite add_zero.
+ reflexivity.
+Qed.
+
Theorem shrx_carry:
forall x y,
ltu y (repr (zwordsize - 1)) = true ->
@@ -3327,10 +3406,11 @@ Proof.
assert (0 <= Z.min (size a) (size b)).
generalize (size_range a) (size_range b). zify; omega.
apply bits_size_3. auto. intros.
- rewrite bits_and. zify. subst z z0. destruct H1.
- rewrite (bits_size_2 a). auto. omega.
- rewrite (bits_size_2 b). apply andb_false_r. omega.
- omega.
+ rewrite bits_and by omega.
+ rewrite andb_false_iff.
+ generalize (bits_size_2 a i).
+ generalize (bits_size_2 b i).
+ zify; intuition.
Qed.
Corollary and_interval:
@@ -3592,6 +3672,104 @@ Proof.
unfold ltu. apply zlt_true. change (unsigned z < 63). rewrite A; omega.
Qed.
+Lemma shr'63:
+ forall x, (shr' x (Int.repr 63)) = if lt x zero then mone else zero.
+Proof.
+ intro.
+ unfold shr', mone, zero.
+ rewrite Int.unsigned_repr by (change Int.max_unsigned with 4294967295; omega).
+ apply same_bits_eq.
+ intros i BIT.
+ rewrite testbit_repr by assumption.
+ rewrite Z.shiftr_spec by omega.
+ rewrite bits_signed by omega.
+ simpl.
+ change zwordsize with 64 in *.
+ destruct (zlt _ _) as [LT | GE].
+ {
+ replace i with 0 in * by omega.
+ change (0 + 63) with (zwordsize - 1).
+ rewrite sign_bit_of_signed.
+ destruct (lt x _).
+ all: rewrite testbit_repr by (change zwordsize with 64 in *; omega).
+ all: simpl; reflexivity.
+ }
+ change (64 - 1) with (zwordsize - 1).
+ rewrite sign_bit_of_signed.
+ destruct (lt x _).
+ all: rewrite testbit_repr by (change zwordsize with 64 in *; omega).
+ { symmetry.
+ apply Ztestbit_m1.
+ tauto.
+ }
+ symmetry.
+ apply Ztestbit_0.
+Qed.
+
+Lemma shru'63:
+ forall x, (shru' x (Int.repr 63)) = if lt x zero then one else zero.
+Proof.
+ intro.
+ unfold shru'.
+ rewrite Int.unsigned_repr by (change Int.max_unsigned with 4294967295; omega).
+ apply same_bits_eq.
+ intros i BIT.
+ rewrite testbit_repr by assumption.
+ rewrite Z.shiftr_spec by omega.
+ unfold lt.
+ rewrite signed_zero.
+ unfold one, zero.
+ destruct (zlt _ 0) as [LT | GE].
+ {
+ rewrite testbit_repr by assumption.
+ destruct (zeq i 0) as [IZERO | INONZERO].
+ { subst i.
+ change (Z.testbit (unsigned x) (0 + 63)) with (testbit x (zwordsize - 1)).
+ rewrite sign_bit_of_signed.
+ unfold lt.
+ rewrite signed_zero.
+ destruct (zlt _ _); try omega.
+ reflexivity.
+ }
+ change (Z.testbit (unsigned x) (i + 63)) with (testbit x (i+63)).
+ rewrite bits_above by (change zwordsize with 64; omega).
+ rewrite Ztestbit_1.
+ destruct (zeq i 0); trivial.
+ subst i.
+ omega.
+ }
+ destruct (zeq i 0) as [IZERO | INONZERO].
+ { subst i.
+ change (Z.testbit (unsigned x) (0 + 63)) with (testbit x (zwordsize - 1)).
+ rewrite sign_bit_of_signed.
+ unfold lt.
+ rewrite signed_zero.
+ rewrite bits_zero.
+ destruct (zlt _ _); try omega.
+ reflexivity.
+ }
+ change (Z.testbit (unsigned x) (i + 63)) with (testbit x (i + 63)).
+ rewrite bits_zero.
+ apply bits_above.
+ change zwordsize with 64.
+ omega.
+Qed.
+
+Theorem shrx'1_shr':
+ forall x,
+ Int.ltu Int.one (Int.repr (zwordsize - 1)) = true ->
+ shrx' x (Int.repr 1) = shr' (add x (shru' x (Int.repr (Int64.zwordsize - 1)))) (Int.repr 1).
+Proof.
+ intros.
+ rewrite shrx'_shr_2 by reflexivity.
+ change (Int.sub (Int.repr 64) (Int.repr 1)) with (Int.repr 63).
+ f_equal. f_equal.
+ rewrite shr'63.
+ rewrite shru'63.
+ rewrite shru'63.
+ destruct (lt x zero); reflexivity.
+Qed.
+
Remark int_ltu_2_inv:
forall y z,
Int.ltu y iwordsize' = true ->
diff --git a/lib/IntvSets.v b/lib/IntvSets.v
index 78c20cc5..b97d9882 100644
--- a/lib/IntvSets.v
+++ b/lib/IntvSets.v
@@ -102,7 +102,7 @@ Proof.
simpl. rewrite IHok. tauto.
destruct (zlt h0 l).
simpl. tauto.
- rewrite IHok. intuition.
+ rewrite IHok. intuition idtac.
assert (l0 <= x < h0 \/ l <= x < h) by xomega. tauto.
left; xomega.
left; xomega.
diff --git a/lib/Maps.v b/lib/Maps.v
index 9e44a7fe..8de3c892 100644
--- a/lib/Maps.v
+++ b/lib/Maps.v
@@ -116,6 +116,19 @@ Module Type TREE.
forall (m1: t A) (m2: t B) (i: elt),
get i (combine f m1 m2) = f (get i m1) (get i m2).
+ Parameter combine_null :
+ forall (A B C: Type) (f: A -> B -> option C),
+ t A -> t B -> t C.
+
+ Axiom gcombine_null:
+ forall (A B C: Type) (f: A -> B -> option C),
+ forall (m1: t A) (m2: t B) (i: elt),
+ get i (combine_null f m1 m2) =
+ match (get i m1), (get i m2) with
+ | (Some x1), (Some x2) => f x1 x2
+ | _, _ => None
+ end.
+
(** Enumerating the bindings of a tree. *)
Parameter elements:
forall (A: Type), t A -> list (elt * A).
@@ -151,6 +164,12 @@ Module Type TREE.
forall (A B: Type) (f: B -> A -> B) (v: B) (m: t A),
fold1 f m v =
List.fold_left (fun a p => f a (snd p)) (elements m) v.
+
+ Parameter bempty_canon :
+ forall (A : Type), t A -> bool.
+ Axiom bempty_canon_correct:
+ forall (A : Type) (tr : t A) (i : elt),
+ bempty_canon tr = true -> get i tr = None.
End TREE.
(** * The abstract signatures of maps *)
@@ -261,6 +280,12 @@ Module PTree <: TREE.
induction i; simpl; auto.
Qed.
+ Definition bempty_canon (A : Type) (tr : t A) : bool :=
+ match tr with
+ | Leaf => true
+ | _ => false
+ end.
+
Theorem gss:
forall (A: Type) (i: positive) (x: A) (m: t A), get i (set i x m) = Some x.
Proof.
@@ -269,7 +294,16 @@ Module PTree <: TREE.
Lemma gleaf : forall (A : Type) (i : positive), get i (Leaf : t A) = None.
Proof. exact gempty. Qed.
-
+
+ Lemma bempty_canon_correct:
+ forall (A : Type) (tr : t A) (i : elt),
+ bempty_canon tr = true -> get i tr = None.
+ Proof.
+ destruct tr; intros.
+ - rewrite gleaf; trivial.
+ - discriminate.
+ Qed.
+
Theorem gso:
forall (A: Type) (i j: positive) (x: A) (m: t A),
i <> j -> get i (set j x m) = get i m.
@@ -625,7 +659,81 @@ Module PTree <: TREE.
auto.
Qed.
- Fixpoint xelements (A : Type) (m : t A) (i : positive)
+ Section COMBINE_NULL.
+
+ Variables A B C: Type.
+ Variable f: A -> B -> option C.
+
+
+ Fixpoint combine_null (m1: t A) (m2: t B) {struct m1} : t C :=
+ match m1, m2 with
+ | (Node l1 o1 r1), (Node l2 o2 r2) =>
+ Node' (combine_null l1 l2)
+ (match o1, o2 with
+ | (Some x1), (Some x2) => f x1 x2
+ | _, _ => None
+ end)
+ (combine_null r1 r2)
+ | _, _ => Leaf
+ end.
+
+ Theorem gcombine_null:
+ forall (m1: t A) (m2: t B) (i: positive),
+ get i (combine_null m1 m2) =
+ match (get i m1), (get i m2) with
+ | (Some x1), (Some x2) => f x1 x2
+ | _, _ => None
+ end.
+ Proof.
+ induction m1; intros; simpl.
+ - rewrite gleaf. rewrite gleaf.
+ reflexivity.
+ - destruct m2; simpl.
+ + rewrite gleaf. rewrite gleaf.
+ destruct get; reflexivity.
+ + rewrite gnode'.
+ destruct i; simpl; try rewrite IHm1_1; try rewrite IHm1; trivial.
+ Qed.
+
+ End COMBINE_NULL.
+
+ Section REMOVE_TREE.
+
+ Variables A B: Type.
+
+ Fixpoint remove_t (m1: t A) (m2: t B) {struct m1} : t A :=
+ match m1, m2 with
+ | Leaf, _ | _, Leaf => m1
+ | (Node l1 o1 r1), (Node l2 o2 r2) =>
+ Node' (remove_t l1 l2)
+ (match o2 with
+ | Some _ => None
+ | None => o1
+ end)
+ (remove_t r1 r2)
+ end.
+
+ Theorem gremove_t:
+ forall m1 : t A,
+ forall m2 : t B,
+ forall i : positive,
+ get i (remove_t m1 m2) = match get i m2 with
+ | None => get i m1
+ | Some _ => None
+ end.
+ Proof.
+ induction m1; intros; simpl.
+ - rewrite gleaf.
+ destruct get; reflexivity.
+ - destruct m2; simpl.
+ + rewrite gleaf.
+ reflexivity.
+ + rewrite gnode'.
+ destruct i; simpl; try rewrite IHm1_1; try rewrite IHm1; trivial.
+ Qed.
+ End REMOVE_TREE.
+
+ Fixpoint xelements (A : Type) (m : t A) (i : positive)
(k: list (positive * A)) {struct m}
: list (positive * A) :=
match m with
@@ -958,6 +1066,36 @@ Module PTree <: TREE.
intros. apply fold1_xelements with (l := @nil (positive * A)).
Qed.
+ Local Open Scope positive.
+ Lemma set_disjoint1:
+ forall (A: Type)(i d : elt) (m: t A) (x y: A),
+ set (i + d) y (set i x m) = set i x (set (i + d) y m).
+ Proof.
+ induction i; destruct d; destruct m; intro; simpl; trivial;
+ intro; congruence.
+ Qed.
+
+ Local Open Scope positive.
+ Lemma set_disjoint:
+ forall (A: Type)(i j : elt) (m: t A) (x y: A),
+ i <> j ->
+ set j y (set i x m) = set i x (set j y m).
+ Proof.
+ intros.
+ destruct (Pos.compare_spec i j) as [Heq | Hlt | Hlt].
+ { congruence. }
+ {
+ rewrite (Pos.lt_iff_add i j) in Hlt.
+ destruct Hlt as [d Hd].
+ subst j.
+ apply set_disjoint1.
+ }
+ rewrite (Pos.lt_iff_add j i) in Hlt.
+ destruct Hlt as [d Hd].
+ subst i.
+ symmetry.
+ apply set_disjoint1.
+ Qed.
End PTree.
(** * An implementation of maps over type [positive] *)
@@ -1035,6 +1173,15 @@ Module PMap <: MAP.
intros. unfold set. simpl. decEq. apply PTree.set2.
Qed.
+ Local Open Scope positive.
+ Lemma set_disjoint:
+ forall (A: Type) (i j : elt) (x y: A) (m: t A),
+ i <> j ->
+ set j y (set i x m) = set i x (set j y m).
+ Proof.
+ intros. unfold set. decEq. apply PTree.set_disjoint. assumption.
+ Qed.
+
End PMap.
(** * An implementation of maps over any type that injects into type [positive] *)
@@ -1102,6 +1249,16 @@ Module IMap(X: INDEXED_TYPE).
intros. unfold set. apply PMap.set2.
Qed.
+ Lemma set_disjoint:
+ forall (A: Type) (i j : elt) (x y: A) (m: t A),
+ i <> j ->
+ set j y (set i x m) = set i x (set j y m).
+ Proof.
+ intros. unfold set. apply PMap.set_disjoint.
+ intro INEQ.
+ assert (i = j) by (apply X.index_inj; auto).
+ auto.
+ Qed.
End IMap.
Module ZIndexed.
diff --git a/mppa_k1c/Asm.v b/mppa_k1c/Asm.v
index e27ff40c..189e0c76 100644
--- a/mppa_k1c/Asm.v
+++ b/mppa_k1c/Asm.v
@@ -107,16 +107,16 @@ Inductive instruction : Type :=
| Pstsud (rd rs1 rs2: ireg)
(** Loads **)
- | Plb (rd: ireg) (ra: ireg) (ofs: addressing) (**r load byte *)
- | Plbu (rd: ireg) (ra: ireg) (ofs: addressing) (**r load byte unsigned *)
- | Plh (rd: ireg) (ra: ireg) (ofs: addressing) (**r load half word *)
- | Plhu (rd: ireg) (ra: ireg) (ofs: addressing) (**r load half word unsigned *)
- | Plw (rd: ireg) (ra: ireg) (ofs: addressing) (**r load int32 *)
- | Plw_a (rd: ireg) (ra: ireg) (ofs: addressing) (**r load any32 *)
- | Pld (rd: ireg) (ra: ireg) (ofs: addressing) (**r load int64 *)
- | Pld_a (rd: ireg) (ra: ireg) (ofs: addressing) (**r load any64 *)
- | Pfls (rd: freg) (ra: ireg) (ofs: addressing) (**r load float *)
- | Pfld (rd: freg) (ra: ireg) (ofs: addressing) (**r load 64-bit float *)
+ | Plb (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load byte *)
+ | Plbu (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load byte unsigned *)
+ | Plh (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load half word *)
+ | Plhu (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load half word unsigned *)
+ | Plw (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load int32 *)
+ | Plw_a (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load any32 *)
+ | Pld (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load int64 *)
+ | Pld_a (trap: trapping_mode) (rd: ireg) (ra: ireg) (ofs: addressing) (**r load any64 *)
+ | Pfls (trap: trapping_mode) (rd: freg) (ra: ireg) (ofs: addressing) (**r load float *)
+ | Pfld (trap: trapping_mode) (rd: freg) (ra: ireg) (ofs: addressing) (**r load 64-bit float *)
| Plq (rs: gpreg_q) (ra: ireg) (ofs: addressing) (**r load 2*64-bit *)
| Plo (rs: gpreg_o) (ra: ireg) (ofs: addressing) (**r load 4*64-bit *)
@@ -481,41 +481,41 @@ Definition basic_to_instruction (b: basic) :=
| PArithARRI64 (Asmvliw.Pcmoveil cond) rd rs1 imm => Pcmoveil cond rd rs1 imm
| PArithARRI64 (Asmvliw.Pcmoveuil cond) rd rs1 imm => Pcmoveuil cond rd rs1 imm
(** Load *)
- | PLoadRRO Asmvliw.Plb rd ra ofs => Plb rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Plbu rd ra ofs => Plbu rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Plh rd ra ofs => Plh rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Plhu rd ra ofs => Plhu rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Plw rd ra ofs => Plw rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Plw_a rd ra ofs => Plw_a rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Pld rd ra ofs => Pld rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Pld_a rd ra ofs => Pld_a rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Pfls rd ra ofs => Pfls rd ra (AOff ofs)
- | PLoadRRO Asmvliw.Pfld rd ra ofs => Pfld rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plb rd ra ofs => Plb trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plbu rd ra ofs => Plbu trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plh rd ra ofs => Plh trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plhu rd ra ofs => Plhu trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plw rd ra ofs => Plw trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Plw_a rd ra ofs => Plw_a trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Pld rd ra ofs => Pld trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Pld_a rd ra ofs => Pld_a trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Pfls rd ra ofs => Pfls trap rd ra (AOff ofs)
+ | PLoadRRO trap Asmvliw.Pfld rd ra ofs => Pfld trap rd ra (AOff ofs)
| PLoadQRRO qrs ra ofs => Plq qrs ra (AOff ofs)
| PLoadORRO qrs ra ofs => Plo qrs ra (AOff ofs)
- | PLoadRRR Asmvliw.Plb rd ra ro => Plb rd ra (AReg ro)
- | PLoadRRR Asmvliw.Plbu rd ra ro => Plbu rd ra (AReg ro)
- | PLoadRRR Asmvliw.Plh rd ra ro => Plh rd ra (AReg ro)
- | PLoadRRR Asmvliw.Plhu rd ra ro => Plhu rd ra (AReg ro)
- | PLoadRRR Asmvliw.Plw rd ra ro => Plw rd ra (AReg ro)
- | PLoadRRR Asmvliw.Plw_a rd ra ro => Plw_a rd ra (AReg ro)
- | PLoadRRR Asmvliw.Pld rd ra ro => Pld rd ra (AReg ro)
- | PLoadRRR Asmvliw.Pld_a rd ra ro => Pld_a rd ra (AReg ro)
- | PLoadRRR Asmvliw.Pfls rd ra ro => Pfls rd ra (AReg ro)
- | PLoadRRR Asmvliw.Pfld rd ra ro => Pfld rd ra (AReg ro)
-
- | PLoadRRRXS Asmvliw.Plb rd ra ro => Plb rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Plbu rd ra ro => Plbu rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Plh rd ra ro => Plh rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Plhu rd ra ro => Plhu rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Plw rd ra ro => Plw rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Plw_a rd ra ro => Plw_a rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Pld rd ra ro => Pld rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Pld_a rd ra ro => Pld_a rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Pfls rd ra ro => Pfls rd ra (ARegXS ro)
- | PLoadRRRXS Asmvliw.Pfld rd ra ro => Pfld rd ra (ARegXS ro)
+ | PLoadRRR trap Asmvliw.Plb rd ra ro => Plb trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Plbu rd ra ro => Plbu trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Plh rd ra ro => Plh trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Plhu rd ra ro => Plhu trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Plw rd ra ro => Plw trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Plw_a rd ra ro => Plw_a trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Pld rd ra ro => Pld trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Pld_a rd ra ro => Pld_a trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Pfls rd ra ro => Pfls trap rd ra (AReg ro)
+ | PLoadRRR trap Asmvliw.Pfld rd ra ro => Pfld trap rd ra (AReg ro)
+
+ | PLoadRRRXS trap Asmvliw.Plb rd ra ro => Plb trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Plbu rd ra ro => Plbu trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Plh rd ra ro => Plh trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Plhu rd ra ro => Plhu trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Plw rd ra ro => Plw trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Plw_a rd ra ro => Plw_a trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Pld rd ra ro => Pld trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Pld_a rd ra ro => Pld_a trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Pfls rd ra ro => Pfls trap rd ra (ARegXS ro)
+ | PLoadRRRXS trap Asmvliw.Pfld rd ra ro => Pfld trap rd ra (ARegXS ro)
(** Store *)
| PStoreRRO Asmvliw.Psb rd ra ofs => Psb rd ra (AOff ofs)
diff --git a/mppa_k1c/Asmblock.v b/mppa_k1c/Asmblock.v
index 9b4489c5..a05d4726 100644
--- a/mppa_k1c/Asmblock.v
+++ b/mppa_k1c/Asmblock.v
@@ -33,6 +33,19 @@ Require Import Conventions.
Require Import Errors.
Require Export Asmvliw.
+(* Notations necessary to hook Asmvliw definitions *)
+Notation undef_caller_save_regs := Asmvliw.undef_caller_save_regs.
+Notation regset := Asmvliw.regset.
+Notation extcall_arg := Asmvliw.extcall_arg.
+Notation extcall_arg_pair := Asmvliw.extcall_arg_pair.
+Notation extcall_arguments := Asmvliw.extcall_arguments.
+Notation set_res := Asmvliw.set_res.
+Notation function := Asmvliw.function.
+Notation bblocks := Asmvliw.bblocks.
+Notation header := Asmvliw.header.
+Notation body := Asmvliw.body.
+Notation exit := Asmvliw.exit.
+Notation correct := Asmvliw.correct.
(** * Auxiliary utilies on basic blocks *)
@@ -260,11 +273,11 @@ Definition exec_arith_instr (ai: ar_instruction) (rs: regset): regset := parexec
(** Auxiliaries for memory accesses *)
-Definition exec_load_offset (chunk: memory_chunk) (rs: regset) (m: mem) (d a: ireg) (ofs: offset) := parexec_load_offset chunk rs rs m m d a ofs.
+Definition exec_load_offset (trap: trapping_mode) (chunk: memory_chunk) (rs: regset) (m: mem) (d a: ireg) (ofs: offset) := parexec_load_offset trap chunk rs rs m m d a ofs.
-Definition exec_load_reg (chunk: memory_chunk) (rs: regset) (m: mem) (d a ro: ireg) := parexec_load_reg chunk rs rs m m d a ro.
+Definition exec_load_reg (trap: trapping_mode) (chunk: memory_chunk) (rs: regset) (m: mem) (d a ro: ireg) := parexec_load_reg trap chunk rs rs m m d a ro.
-Definition exec_load_regxs (chunk: memory_chunk) (rs: regset) (m: mem) (d a ro: ireg) := parexec_load_regxs chunk rs rs m m d a ro.
+Definition exec_load_regxs (trap: trapping_mode) (chunk: memory_chunk) (rs: regset) (m: mem) (d a ro: ireg) := parexec_load_regxs trap chunk rs rs m m d a ro.
Definition exec_load_q_offset (rs: regset) (m: mem) (d : gpreg_q) (a: ireg) (ofs: offset) := parexec_load_q_offset rs rs m m d a ofs.
@@ -294,6 +307,31 @@ Fixpoint exec_body (body: list basic) (rs: regset) (m: mem): outcome :=
end
end.
+
+Theorem builtin_body_nil:
+ forall bb ef args res, exit bb = Some (PExpand (Pbuiltin ef args res)) -> body bb = nil.
+Proof.
+ intros. destruct bb as [hd bdy ex WF]. simpl in *.
+ apply wf_bblock_refl in WF. inv WF. unfold builtin_alone in H1.
+ eapply H1; eauto.
+Qed.
+
+Theorem exec_body_app:
+ forall l l' rs m rs'' m'',
+ exec_body (l ++ l') rs m = Next rs'' m'' ->
+ exists rs' m',
+ exec_body l rs m = Next rs' m'
+ /\ exec_body l' rs' m' = Next rs'' m''.
+Proof.
+ induction l.
+ - intros. simpl in H. repeat eexists. auto.
+ - intros. rewrite <- app_comm_cons in H. simpl in H.
+ destruct (exec_basic_instr a rs m) eqn:EXEBI.
+ + apply IHl in H. destruct H as (rs1 & m1 & EXEB1 & EXEB2).
+ repeat eexists. simpl. rewrite EXEBI. eauto. auto.
+ + discriminate.
+Qed.
+
(** Position corresponding to a label *)
Definition goto_label (f: function) (lbl: label) (rs: regset) (m: mem) : outcome := par_goto_label f lbl rs rs m.
diff --git a/mppa_k1c/Asmblockdeps.v b/mppa_k1c/Asmblockdeps.v
index 8bc1112f..01eda623 100644
--- a/mppa_k1c/Asmblockdeps.v
+++ b/mppa_k1c/Asmblockdeps.v
@@ -7,7 +7,7 @@
Require Import AST.
Require Import Asmblock.
-Require Import Asmblockgenproof0.
+Require Import Asmblockgenproof0 Asmblockprops.
Require Import Values.
Require Import Globalenvs.
Require Import Memory.
@@ -22,6 +22,8 @@ Require Import Parallelizability.
Require Import Asmvliw Permutation.
Require Import Chunks.
+Require Import Lia.
+
Open Scope impure.
(** Definition of L *)
@@ -83,9 +85,9 @@ Coercion OArithRRI32: arith_name_rri32 >-> Funclass.
Coercion OArithRRI64: arith_name_rri64 >-> Funclass.
Inductive load_op :=
- | OLoadRRO (n: load_name) (ofs: offset)
- | OLoadRRR (n: load_name)
- | OLoadRRRXS (n: load_name)
+ | OLoadRRO (n: load_name) (trap: trapping_mode) (ofs: offset)
+ | OLoadRRR (n: load_name) (trap: trapping_mode)
+ | OLoadRRRXS (n: load_name) (trap: trapping_mode)
.
Coercion OLoadRRO: load_name >-> Funclass.
@@ -142,33 +144,39 @@ Definition arith_eval (ao: arith_op) (l: list value) :=
| _, _ => None
end.
-Definition exec_load_deps_offset (chunk: memory_chunk) (m: mem) (v: val) (ofs: offset) :=
+Definition exec_incorrect_load trap chunk :=
+ match trap with
+ | TRAP => None
+ | NOTRAP => Some (Val (concrete_default_notrap_load_value chunk))
+ end.
+
+Definition exec_load_deps_offset (trap: trapping_mode) (chunk: memory_chunk) (m: mem) (v: val) (ofs: offset) :=
let (ge, fn) := Ge in
match (eval_offset ofs) with
| OK ptr => match Mem.loadv chunk m (Val.offset_ptr v ptr) with
- | None => None
+ | None => exec_incorrect_load trap chunk
| Some vl => Some (Val vl)
end
| _ => None
end.
-Definition exec_load_deps_reg (chunk: memory_chunk) (m: mem) (v vo: val) :=
+Definition exec_load_deps_reg (trap: trapping_mode) (chunk: memory_chunk) (m: mem) (v vo: val) :=
match Mem.loadv chunk m (Val.addl v vo) with
- | None => None
+ | None => exec_incorrect_load trap chunk
| Some vl => Some (Val vl)
end.
-Definition exec_load_deps_regxs (chunk: memory_chunk) (m: mem) (v vo: val) :=
+Definition exec_load_deps_regxs (trap: trapping_mode) (chunk: memory_chunk) (m: mem) (v vo: val) :=
match Mem.loadv chunk m (Val.addl v (Val.shll vo (scale_of_chunk chunk))) with
- | None => None
+ | None => exec_incorrect_load trap chunk
| Some vl => Some (Val vl)
end.
Definition load_eval (lo: load_op) (l: list value) :=
match lo, l with
- | OLoadRRO n ofs, [Val v; Memstate m] => exec_load_deps_offset (load_chunk n) m v ofs
- | OLoadRRR n, [Val v; Val vo; Memstate m] => exec_load_deps_reg (load_chunk n) m v vo
- | OLoadRRRXS n, [Val v; Val vo; Memstate m] => exec_load_deps_regxs (load_chunk n) m v vo
+ | OLoadRRO n trap ofs, [Val v; Memstate m] => exec_load_deps_offset trap (load_chunk n) m v ofs
+ | OLoadRRR n trap, [Val v; Val vo; Memstate m] => exec_load_deps_reg trap (load_chunk n) m v vo
+ | OLoadRRRXS n trap, [Val v; Val vo; Memstate m] => exec_load_deps_regxs trap (load_chunk n) m v vo
| _, _ => None
end.
@@ -202,6 +210,136 @@ Definition store_eval (so: store_op) (l: list value) :=
| _, _ => None
end.
+Local Open Scope Z.
+
+Remark size_chunk_positive: forall chunk,
+ (size_chunk chunk) > 0.
+Proof.
+ destruct chunk; simpl; lia.
+Qed.
+
+Remark size_chunk_small: forall chunk,
+ (size_chunk chunk) <= 8.
+Proof.
+ destruct chunk; simpl; lia.
+Qed.
+
+Definition disjoint_chunks
+ (ofs1 : offset) (chunk1 : memory_chunk)
+ (ofs2 : offset) (chunk2 : memory_chunk) :=
+ Intv.disjoint ((Ptrofs.unsigned ofs1),
+ ((Ptrofs.unsigned ofs1) + (size_chunk chunk1)))
+ ((Ptrofs.unsigned ofs2),
+ ((Ptrofs.unsigned ofs2) + (size_chunk chunk2))).
+
+Definition small_offset_threshold := 18446744073709551608.
+
+Lemma store_store_disjoint_offsets :
+ forall n1 n2 ofs1 ofs2 vs1 vs2 va m0 m1 m2 m1' m2',
+ (disjoint_chunks ofs1 (store_chunk n1) ofs2 (store_chunk n2)) ->
+ (Ptrofs.unsigned ofs1) < small_offset_threshold ->
+ (Ptrofs.unsigned ofs2) < small_offset_threshold ->
+ store_eval (OStoreRRO n1 ofs1) [vs1; va; Memstate m0] = Some (Memstate m1) ->
+ store_eval (OStoreRRO n2 ofs2) [vs2; va; Memstate m1] = Some (Memstate m2) ->
+ store_eval (OStoreRRO n2 ofs2) [vs2; va; Memstate m0] = Some (Memstate m1') ->
+ store_eval (OStoreRRO n1 ofs1) [vs1; va; Memstate m1'] = Some (Memstate m2') ->
+ m2 = m2'.
+Proof.
+ intros until m2'.
+ intros DISJOINT SMALL1 SMALL2 STORE0 STORE1 STORE0' STORE1'.
+ unfold disjoint_chunks in DISJOINT.
+ destruct vs1 as [v1 | ]; simpl in STORE0, STORE1'; try congruence.
+ destruct vs2 as [v2 | ]; simpl in STORE1, STORE0'; try congruence.
+ destruct va as [base | ]; try congruence.
+ unfold exec_store_deps_offset in *.
+ destruct Ge.
+ unfold eval_offset in *; simpl in *.
+ unfold Mem.storev in *.
+ unfold Val.offset_ptr in *.
+ destruct base as [ | | | | | wblock wpofs] in * ; try congruence.
+ destruct (Mem.store _ _ _ _ _) eqn:E0; try congruence.
+ inv STORE0.
+ destruct (Mem.store (store_chunk n2) _ _ _ _) eqn:E1; try congruence.
+ inv STORE1.
+ destruct (Mem.store (store_chunk n2) m0 _ _ _) eqn:E0'; try congruence.
+ inv STORE0'.
+ destruct (Mem.store _ m1' _ _ _) eqn:E1'; try congruence.
+ inv STORE1'.
+ assert (Some m2 = Some m2').
+ 2: congruence.
+ rewrite <- E1.
+ rewrite <- E1'.
+ eapply Mem.store_store_other.
+ 2, 3: eassumption.
+
+ right.
+ pose proof (size_chunk_positive (store_chunk n1)).
+ pose proof (size_chunk_positive (store_chunk n2)).
+ pose proof (size_chunk_small (store_chunk n1)).
+ pose proof (size_chunk_small (store_chunk n2)).
+ destruct (Intv.range_disjoint _ _ DISJOINT) as [DIS | [DIS | DIS]];
+ unfold Intv.empty in DIS; simpl in DIS.
+ 1, 2: lia.
+ pose proof (Ptrofs.unsigned_range ofs1).
+ pose proof (Ptrofs.unsigned_range ofs2).
+ unfold small_offset_threshold in *.
+ destruct (Ptrofs.unsigned_add_either wpofs ofs1) as [R1 | R1]; rewrite R1;
+ destruct (Ptrofs.unsigned_add_either wpofs ofs2) as [R2 | R2]; rewrite R2;
+ change Ptrofs.modulus with 18446744073709551616 in *;
+ lia.
+Qed.
+
+Lemma load_store_disjoint_offsets :
+ forall n1 n2 tm ofs1 ofs2 vs va m0 m1,
+ (disjoint_chunks ofs1 (store_chunk n1) ofs2 (load_chunk n2)) ->
+ (Ptrofs.unsigned ofs1) < small_offset_threshold ->
+ (Ptrofs.unsigned ofs2) < small_offset_threshold ->
+ store_eval (OStoreRRO n1 ofs1) [vs; va; Memstate m0] = Some (Memstate m1) ->
+ load_eval (OLoadRRO n2 tm ofs2) [va; Memstate m1] =
+ load_eval (OLoadRRO n2 tm ofs2) [va; Memstate m0].
+Proof.
+ intros until m1.
+ intros DISJOINT SMALL1 SMALL2 STORE0.
+ destruct vs as [v | ]; simpl in STORE0; try congruence.
+ destruct va as [base | ]; try congruence.
+ unfold exec_store_deps_offset in *.
+ unfold eval_offset in *; simpl in *.
+ unfold exec_load_deps_offset.
+ unfold Mem.storev, Mem.loadv in *.
+ destruct Ge in *.
+ unfold eval_offset in *.
+ unfold Val.offset_ptr in *.
+ destruct base as [ | | | | | wblock wpofs] in * ; try congruence.
+ destruct (Mem.store _ _ _ _) eqn:E0; try congruence.
+ inv STORE0.
+ assert (
+ (Mem.load (load_chunk n2) m1 wblock
+ (Ptrofs.unsigned (Ptrofs.add wpofs ofs2))) =
+ (Mem.load (load_chunk n2) m0 wblock
+ (Ptrofs.unsigned (Ptrofs.add wpofs ofs2))) ) as LOADS.
+ {
+ eapply Mem.load_store_other.
+ eassumption.
+ right.
+ pose proof (size_chunk_positive (store_chunk n1)).
+ pose proof (size_chunk_positive (load_chunk n2)).
+ pose proof (size_chunk_small (store_chunk n1)).
+ pose proof (size_chunk_small (load_chunk n2)).
+ destruct (Intv.range_disjoint _ _ DISJOINT) as [DIS | [DIS | DIS]];
+ unfold Intv.empty in DIS; simpl in DIS.
+ 1,2: lia.
+
+ pose proof (Ptrofs.unsigned_range ofs1).
+ pose proof (Ptrofs.unsigned_range ofs2).
+ unfold small_offset_threshold in *.
+ destruct (Ptrofs.unsigned_add_either wpofs ofs1) as [R1 | R1]; rewrite R1;
+ destruct (Ptrofs.unsigned_add_either wpofs ofs2) as [R2 | R2]; rewrite R2;
+ change Ptrofs.modulus with 18446744073709551616 in *;
+ lia.
+ }
+ destruct (Mem.load _ m1 _ _) in *; destruct (Mem.load _ m0 _ _) in *; congruence.
+Qed.
+
Definition goto_label_deps (f: function) (lbl: label) (vpc: val) :=
match label_pos lbl 0 (fn_blocks f) with
| None => None
@@ -364,24 +502,47 @@ Proof.
Qed.
Hint Resolve offset_eq_correct: wlp.
+Definition trapping_mode_eq trap1 trap2 :=
+ RET (match trap1, trap2 with
+ | TRAP, TRAP | NOTRAP, NOTRAP => true
+ | TRAP, NOTRAP | NOTRAP, TRAP => false
+ end).
+Lemma trapping_mode_eq_correct t1 t2:
+ WHEN trapping_mode_eq t1 t2 ~> b THEN b = true -> t1 = t2.
+Proof.
+ wlp_simplify.
+ destruct t1; destruct t2; trivial; discriminate.
+Qed.
+Hint Resolve trapping_mode_eq_correct: wlp.
+
Definition load_op_eq (o1 o2: load_op): ?? bool :=
match o1 with
- | OLoadRRO n1 ofs1 =>
- match o2 with OLoadRRO n2 ofs2 => iandb (phys_eq n1 n2) (offset_eq ofs1 ofs2) | _ => RET false end
- | OLoadRRR n1 =>
- match o2 with OLoadRRR n2 => phys_eq n1 n2 | _ => RET false end
- | OLoadRRRXS n1 =>
- match o2 with OLoadRRRXS n2 => phys_eq n1 n2 | _ => RET false end
+ | OLoadRRO n1 trap ofs1 =>
+ match o2 with
+ | OLoadRRO n2 trap2 ofs2 => iandb (phys_eq n1 n2) (iandb (offset_eq ofs1 ofs2) (trapping_mode_eq trap trap2))
+ | _ => RET false
+ end
+ | OLoadRRR n1 trap =>
+ match o2 with
+ | OLoadRRR n2 trap2 => iandb (phys_eq n1 n2) (trapping_mode_eq trap trap2)
+ | _ => RET false
+ end
+ | OLoadRRRXS n1 trap =>
+ match o2 with
+ | OLoadRRRXS n2 trap2 => iandb (phys_eq n1 n2) (trapping_mode_eq trap trap2)
+ | _ => RET false
+ end
end.
Lemma load_op_eq_correct o1 o2:
WHEN load_op_eq o1 o2 ~> b THEN b = true -> o1 = o2.
Proof.
destruct o1, o2; wlp_simplify; try discriminate.
- - f_equal. pose (Ptrofs.eq_spec ofs ofs0).
- rewrite H in *. trivial.
- - congruence.
- - congruence.
+ { f_equal.
+ destruct trap, trap0; simpl in *; trivial; discriminate.
+ pose (Ptrofs.eq_spec ofs ofs0).
+ rewrite H in *. trivial. }
+ all: destruct trap, trap0; simpl in *; trivial; discriminate.
Qed.
Hint Resolve load_op_eq_correct: wlp.
Opaque load_op_eq_correct.
@@ -617,21 +778,21 @@ Definition trans_arith (ai: ar_instruction) : inst :=
Definition trans_basic (b: basic) : inst :=
match b with
| PArith ai => trans_arith ai
- | PLoadRRO n d a ofs => [(#d, Op (Load (OLoadRRO n ofs)) (PReg (#a) @ PReg pmem @ Enil))]
- | PLoadRRR n d a ro => [(#d, Op (Load (OLoadRRR n)) (PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
- | PLoadRRRXS n d a ro => [(#d, Op (Load (OLoadRRRXS n)) (PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
+ | PLoadRRO trap n d a ofs => [(#d, Op (Load (OLoadRRO n trap ofs)) (PReg (#a) @ PReg pmem @ Enil))]
+ | PLoadRRR trap n d a ro => [(#d, Op (Load (OLoadRRR n trap)) (PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
+ | PLoadRRRXS trap n d a ro => [(#d, Op (Load (OLoadRRRXS n trap)) (PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
| PStoreRRO n s a ofs => [(pmem, Op (Store (OStoreRRO n ofs)) (PReg (#s) @ PReg (#a) @ PReg pmem @ Enil))]
| PLoadQRRO qd a ofs =>
let (d0, d1) := gpreg_q_expand qd in
- [(#d0, Op (Load (OLoadRRO Pld_a ofs)) (PReg (#a) @ PReg pmem @ Enil));
- (#d1, Op (Load (OLoadRRO Pld_a (Ptrofs.add ofs (Ptrofs.repr 8)))) (Old(PReg (#a)) @ PReg pmem @ Enil))]
+ [(#d0, Op (Load (OLoadRRO Pld_a TRAP ofs)) (PReg (#a) @ PReg pmem @ Enil));
+ (#d1, Op (Load (OLoadRRO Pld_a TRAP (Ptrofs.add ofs (Ptrofs.repr 8)))) (Old(PReg (#a)) @ PReg pmem @ Enil))]
| PLoadORRO od a ofs =>
match gpreg_o_expand od with
| (d0, d1, d2, d3) =>
- [(#d0, Op (Load (OLoadRRO Pld_a ofs)) (PReg (#a) @ PReg pmem @ Enil));
- (#d1, Op (Load (OLoadRRO Pld_a (Ptrofs.add ofs (Ptrofs.repr 8)))) (Old(PReg (#a)) @ PReg pmem @ Enil));
- (#d2, Op (Load (OLoadRRO Pld_a (Ptrofs.add ofs (Ptrofs.repr 16)))) (Old(PReg (#a)) @ PReg pmem @ Enil));
- (#d3, Op (Load (OLoadRRO Pld_a (Ptrofs.add ofs (Ptrofs.repr 24)))) (Old(PReg (#a)) @ PReg pmem @ Enil))]
+ [(#d0, Op (Load (OLoadRRO Pld_a TRAP ofs)) (PReg (#a) @ PReg pmem @ Enil));
+ (#d1, Op (Load (OLoadRRO Pld_a TRAP (Ptrofs.add ofs (Ptrofs.repr 8)))) (Old(PReg (#a)) @ PReg pmem @ Enil));
+ (#d2, Op (Load (OLoadRRO Pld_a TRAP (Ptrofs.add ofs (Ptrofs.repr 16)))) (Old(PReg (#a)) @ PReg pmem @ Enil));
+ (#d3, Op (Load (OLoadRRO Pld_a TRAP (Ptrofs.add ofs (Ptrofs.repr 24)))) (Old(PReg (#a)) @ PReg pmem @ Enil))]
end
| PStoreRRR n s a ro => [(pmem, Op (Store (OStoreRRR n)) (PReg (#s) @ PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
| PStoreRRRXS n s a ro => [(pmem, Op (Store (OStoreRRRXS n)) (PReg (#s) @ PReg (#a) @ PReg (#ro) @ PReg pmem @ Enil))]
@@ -844,7 +1005,7 @@ Theorem bisimu_par_wio_basic ge fn rsr rsw mr mw sr sw bi:
Proof.
(* a little tactic to automate reasoning on preg_eq *)
-Local Hint Resolve not_eq_sym ppos_pmem_discr ppos_discr.
+Local Hint Resolve not_eq_sym ppos_pmem_discr ppos_discr: core.
Local Ltac preg_eq_discr r rd :=
destruct (preg_eq r rd); try (subst r; rewrite assign_eq, Pregmap.gss; auto);
rewrite (assign_diff _ (#rd) (#r) _); auto;
@@ -861,21 +1022,21 @@ Local Ltac preg_eq_discr r rd :=
unfold parexec_load_offset; simpl; unfold exec_load_deps_offset; erewrite GENV, H, H0;
unfold eval_offset;
simpl; auto;
- destruct (Mem.loadv _ _ _) eqn:MEML; simpl; auto;
+ destruct (Mem.loadv _ _ _) eqn:MEML; destruct trap; simpl; auto;
eexists; split; try split; Simpl;
intros rr; destruct rr; Simpl; destruct (ireg_eq g rd); subst; Simpl.
(* Load Reg *)
+ destruct i; simpl load_chunk. all:
unfold parexec_load_reg; simpl; unfold exec_load_deps_reg; rewrite H, H0; rewrite (H0 rofs);
- destruct (Mem.loadv _ _ _) eqn:MEML; simpl; auto;
+ destruct (Mem.loadv _ _ _) eqn:MEML; destruct trap; simpl; auto;
eexists; split; try split; Simpl;
intros rr; destruct rr; Simpl; destruct (ireg_eq g rd); subst; Simpl.
(* Load Reg XS *)
+ destruct i; simpl load_chunk. all:
unfold parexec_load_regxs; simpl; unfold exec_load_deps_regxs; rewrite H, H0; rewrite (H0 rofs);
- destruct (Mem.loadv _ _ _) eqn:MEML; simpl; auto;
+ destruct (Mem.loadv _ _ _) eqn:MEML; destruct trap; simpl; auto;
eexists; split; try split; Simpl;
intros rr; destruct rr; Simpl; destruct (ireg_eq g rd); subst; Simpl.
@@ -892,7 +1053,7 @@ Local Ltac preg_eq_discr r rd :=
preg_eq_discr r rd0. }
(* Load Octuple word *)
- + Local Hint Resolve not_eq_sym ppos_pmem_discr ppos_discr.
+ + Local Hint Resolve not_eq_sym ppos_pmem_discr ppos_discr: core.
unfold parexec_load_o_offset.
destruct (gpreg_o_expand rd) as [[[rd0 rd1] rd2] rd3]; destruct Ge; simpl.
rewrite H0, H.
@@ -1262,13 +1423,13 @@ Section SECT_BBLOCK_EQUIV.
Variable Ge: genv.
-Local Hint Resolve trans_state_match.
+Local Hint Resolve trans_state_match: core.
Lemma bblock_simu_reduce:
forall p1 p2 ge fn,
Ge = Genv ge fn ->
L.bblock_simu Ge (trans_block p1) (trans_block p2) ->
- Asmblockgenproof0.bblock_simu ge fn p1 p2.
+ Asmblockprops.bblock_simu ge fn p1 p2.
Proof.
unfold bblock_simu, res_eq; intros p1 p2 ge fn H1 H2 rs m DONTSTUCK.
generalize (H2 (trans_state (State rs m))); clear H2.
@@ -1537,9 +1698,9 @@ Definition string_of_load_name (n: load_name) : pstring :=
Definition string_of_load (op: load_op): pstring :=
match op with
- | OLoadRRO n _ => string_of_load_name n
- | OLoadRRR n => string_of_load_name n
- | OLoadRRRXS n => string_of_load_name n
+ | OLoadRRO n _ _ => string_of_load_name n
+ | OLoadRRR n _ => string_of_load_name n
+ | OLoadRRRXS n _ => string_of_load_name n
end.
Definition string_of_store_name (n: store_name) : pstring :=
@@ -1626,7 +1787,7 @@ Definition bblock_simu_test (verb: bool) (p1 p2: Asmvliw.bblock) : ?? bool :=
Local Hint Resolve IST.bblock_simu_test_correct bblock_simu_reduce IST.verb_bblock_simu_test_correct: wlp.
Theorem bblock_simu_test_correct verb p1 p2 :
- WHEN bblock_simu_test verb p1 p2 ~> b THEN b=true -> forall ge fn, Asmblockgenproof0.bblock_simu ge fn p1 p2.
+ WHEN bblock_simu_test verb p1 p2 ~> b THEN b=true -> forall ge fn, Asmblockprops.bblock_simu ge fn p1 p2.
Proof.
wlp_simplify.
Qed.
@@ -1642,7 +1803,7 @@ Definition pure_bblock_simu_test (verb: bool) (p1 p2: Asmvliw.bblock): bool :=
| None => false
end.
-Theorem pure_bblock_simu_test_correct verb p1 p2 ge fn: pure_bblock_simu_test verb p1 p2 = true -> Asmblockgenproof0.bblock_simu ge fn p1 p2.
+Theorem pure_bblock_simu_test_correct verb p1 p2 ge fn: pure_bblock_simu_test verb p1 p2 = true -> Asmblockprops.bblock_simu ge fn p1 p2.
Proof.
unfold pure_bblock_simu_test.
destruct (unsafe_coerce (bblock_simu_test verb p1 p2)) eqn: UNSAFE; try discriminate.
@@ -1652,7 +1813,7 @@ Qed.
Definition bblock_simub: Asmvliw.bblock -> Asmvliw.bblock -> bool := pure_bblock_simu_test true.
-Lemma bblock_simub_correct p1 p2 ge fn: bblock_simub p1 p2 = true -> Asmblockgenproof0.bblock_simu ge fn p1 p2.
+Lemma bblock_simub_correct p1 p2 ge fn: bblock_simub p1 p2 = true -> Asmblockprops.bblock_simu ge fn p1 p2.
Proof.
eapply (pure_bblock_simu_test_correct true).
Qed.
diff --git a/mppa_k1c/Asmblockgen.v b/mppa_k1c/Asmblockgen.v
index abb24327..36269954 100644
--- a/mppa_k1c/Asmblockgen.v
+++ b/mppa_k1c/Asmblockgen.v
@@ -28,6 +28,8 @@ Require Import Chunks.
Local Open Scope string_scope.
Local Open Scope error_monad_scope.
+Import PArithCoercions.
+
(** The code generation functions take advantage of several
characteristics of the [Mach] code generated by earlier passes of the
compiler, mostly that argument and result registers are of the correct
@@ -912,12 +914,12 @@ end.
Definition loadind (base: ireg) (ofs: ptrofs) (ty: typ) (dst: mreg) (k: bcode) :=
match ty, preg_of dst with
- | Tint, IR rd => OK (indexed_memory_access (PLoadRRO Plw rd) base ofs ::i k)
- | Tlong, IR rd => OK (indexed_memory_access (PLoadRRO Pld rd) base ofs ::i k)
- | Tsingle, IR rd => OK (indexed_memory_access (PLoadRRO Pfls rd) base ofs ::i k)
- | Tfloat, IR rd => OK (indexed_memory_access (PLoadRRO Pfld rd) base ofs ::i k)
- | Tany32, IR rd => OK (indexed_memory_access (PLoadRRO Plw_a rd) base ofs ::i k)
- | Tany64, IR rd => OK (indexed_memory_access (PLoadRRO Pld_a rd) base ofs ::i k)
+ | Tint, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Plw rd) base ofs ::i k)
+ | Tlong, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Pld rd) base ofs ::i k)
+ | Tsingle, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Pfls rd) base ofs ::i k)
+ | Tfloat, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Pfld rd) base ofs ::i k)
+ | Tany32, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Plw_a rd) base ofs ::i k)
+ | Tany64, IR rd => OK (indexed_memory_access (PLoadRRO TRAP Pld_a rd) base ofs ::i k)
| _, _ => Error (msg "Asmblockgen.loadind")
end.
@@ -933,7 +935,7 @@ Definition storeind (src: mreg) (base: ireg) (ofs: ptrofs) (ty: typ) (k: bcode)
end.
Definition loadind_ptr (base: ireg) (ofs: ptrofs) (dst: ireg) :=
- indexed_memory_access (PLoadRRO Pld dst) base ofs.
+ indexed_memory_access (PLoadRRO TRAP Pld dst) base ofs.
Definition storeind_ptr (src: ireg) (base: ireg) (ofs: ptrofs) :=
indexed_memory_access (PStoreRRO Psd src) base ofs.
@@ -993,27 +995,28 @@ Definition chunk2load (chunk: memory_chunk) :=
| Many64 => Pld_a
end.
-Definition transl_load_rro (chunk: memory_chunk) (addr: addressing)
+Definition transl_load_rro (trap: trapping_mode) (chunk: memory_chunk) (addr: addressing)
(args: list mreg) (dst: mreg) (k: bcode) : res bcode :=
do r <- ireg_of dst;
- transl_memory_access (PLoadRRO (chunk2load chunk) r) addr args k.
+ transl_memory_access (PLoadRRO trap (chunk2load chunk) r) addr args k.
-Definition transl_load_rrr (chunk: memory_chunk) (addr: addressing)
+Definition transl_load_rrr (trap: trapping_mode) (chunk: memory_chunk) (addr: addressing)
(args: list mreg) (dst: mreg) (k: bcode) : res bcode :=
do r <- ireg_of dst;
- transl_memory_access2 (PLoadRRR (chunk2load chunk) r) addr args k.
+ transl_memory_access2 (PLoadRRR trap (chunk2load chunk) r) addr args k.
-Definition transl_load_rrrXS (chunk: memory_chunk) (scale : Z)
+Definition transl_load_rrrXS (trap: trapping_mode) (chunk: memory_chunk) (scale : Z)
(args: list mreg) (dst: mreg) (k: bcode) : res bcode :=
do r <- ireg_of dst;
- transl_memory_access2XS chunk (PLoadRRRXS (chunk2load chunk) r) scale args k.
+ transl_memory_access2XS chunk (PLoadRRRXS trap (chunk2load chunk) r) scale args k.
-Definition transl_load (chunk: memory_chunk) (addr: addressing)
+Definition transl_load (trap : trapping_mode)
+ (chunk: memory_chunk) (addr: addressing)
(args: list mreg) (dst: mreg) (k: bcode) : res bcode :=
match addr with
- | Aindexed2XS scale => transl_load_rrrXS chunk scale args dst k
- | Aindexed2 => transl_load_rrr chunk addr args dst k
- | _ => transl_load_rro chunk addr args dst k
+ | Aindexed2XS scale => transl_load_rrrXS trap chunk scale args dst k
+ | Aindexed2 => transl_load_rrr trap chunk addr args dst k
+ | _ => transl_load_rro trap chunk addr args dst k
end.
Definition chunk2store (chunk: memory_chunk) :=
@@ -1073,8 +1076,8 @@ Definition transl_instr_basic (f: Machblock.function) (i: Machblock.basic_inst)
else (loadind_ptr SP f.(fn_link_ofs) FP) ::i c)
| MBop op args res =>
transl_op op args res k
- | MBload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | MBload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| MBstore chunk addr args src =>
transl_store chunk addr args src k
end.
@@ -1115,7 +1118,7 @@ Definition fp_is_parent (before: bool) (i: Machblock.basic_inst) : bool :=
| MBsetstack src ofs ty => before
| MBgetparam ofs ty dst => negb (mreg_eq dst MFP)
| MBop op args res => before && negb (mreg_eq res MFP)
- | MBload chunk addr args dst => before && negb (mreg_eq dst MFP)
+ | MBload trapping_mode chunk addr args dst => before && negb (mreg_eq dst MFP)
| MBstore chunk addr args res => before
end.
@@ -1185,7 +1188,7 @@ Definition transl_block (f: Machblock.function) (fb: Machblock.bblock) (ep: bool
Fixpoint transl_blocks (f: Machblock.function) (lmb: list Machblock.bblock) (ep: bool) :=
match lmb with
| nil => OK nil
- | mb :: lmb =>
+ | mb :: lmb =>
do lb <- transl_block f mb (if Machblock.header mb then ep else false);
do lb' <- transl_blocks f lmb false;
OK (lb @@ lb')
diff --git a/mppa_k1c/Asmblockgenproof.v b/mppa_k1c/Asmblockgenproof.v
index bd2dc985..1a427112 100644
--- a/mppa_k1c/Asmblockgenproof.v
+++ b/mppa_k1c/Asmblockgenproof.v
@@ -16,7 +16,7 @@ Require Import Coqlib Errors.
Require Import Integers Floats AST Linking.
Require Import Values Memory Events Globalenvs Smallstep.
Require Import Op Locations Machblock Conventions Asmblock.
-Require Import Asmblockgen Asmblockgenproof0 Asmblockgenproof1.
+Require Import Asmblockgen Asmblockgenproof0 Asmblockgenproof1 Asmblockprops.
Require Import Axioms.
Module MB := Machblock.
@@ -899,7 +899,7 @@ Proof.
intros [tc' [rs' [A [B C]]]].
exploit ireg_val; eauto. rewrite H13. intros LD; inv LD.
-
+
repeat eexists.
rewrite H6. simpl extract_basic. simpl. eauto.
rewrite H7. simpl extract_ctl. simpl. Simpl. rewrite <- H1. unfold Mach.label in H14. unfold label. rewrite H14. eapply A.
@@ -922,7 +922,7 @@ Proof.
simpl. eauto.
intros EXEB.
assert (f1 = f) by congruence. subst f1.
-
+
repeat eexists.
rewrite H6. simpl extract_basic. eauto.
rewrite H7. simpl extract_ctl. simpl. reflexivity.
@@ -1120,7 +1120,7 @@ Proof.
apply preg_of_not_FP; auto.
- (* MBop *)
simpl in EQ0. rewrite Hheader in DXP.
-
+
assert (eval_operation tge sp op (map ms args) m' = Some v).
rewrite <- H. apply eval_operation_preserved. exact symbols_preserved.
exploit eval_operation_lessdef.
@@ -1175,6 +1175,71 @@ Local Transparent destroyed_by_op.
subst. rewrite <- DXP. rewrite R; try discriminate. reflexivity.
apply preg_of_not_FP; assumption. reflexivity.
+ - (* notrap1 cannot happen *)
+ simpl in EQ0. unfold transl_load in EQ0.
+ destruct addr; simpl in H.
+ all: unfold transl_load_rrrXS, transl_load_rrr, transl_load_rro in EQ0;
+ monadInv EQ0; unfold transl_memory_access2XS, transl_memory_access2, transl_memory_access in EQ2;
+ destruct args as [|h0 t0]; try discriminate;
+ destruct t0 as [|h1 t1]; try discriminate;
+ destruct t1 as [|h2 t2]; try discriminate.
+
+ - (* MBload notrap2 TODO *)
+ simpl in EQ0. rewrite Hheader in DXP.
+
+ assert (eval_addressing tge sp addr (map ms args) = Some a).
+ rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
+ exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
+ intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
+
+ destruct (Mem.loadv chunk m1 a') as [v' | ] eqn:Hload.
+ {
+ exploit transl_load_correct; eauto.
+ intros [rs2 [P [Q R]]].
+
+ eapply exec_straight_body in P.
+ 2: eapply code_to_basics_id; eauto.
+ destruct P as (l & ll & TBC & CTB & EXECB).
+ exists rs2, m1, ll.
+ eexists. eexists. split. instantiate (1 := x). eauto.
+ repeat (split; auto).
+ eapply basics_to_code_app; eauto.
+ eapply match_codestate_intro; eauto. simpl. rewrite Hheader in *.
+ simpl in EQ. assumption.
+
+ eapply agree_set_undef_mreg; eauto. intros; auto with asmgen.
+
+ simpl. intro.
+ rewrite R; try congruence.
+ apply DXP.
+ destruct ep0; simpl in *; congruence.
+ apply preg_of_not_FP.
+ destruct ep0; simpl in *; congruence.
+ }
+ {
+ exploit transl_load_correct_notrap2; eauto.
+ intros [rs2 [P [Q R]]].
+
+ eapply exec_straight_body in P.
+ 2: eapply code_to_basics_id; eauto.
+ destruct P as (l & ll & TBC & CTB & EXECB).
+ exists rs2, m1, ll.
+ eexists. eexists. split. instantiate (1 := x). eauto.
+ repeat (split; auto).
+ eapply basics_to_code_app; eauto.
+ remember {| MB.header := _; MB.body := _; MB.exit := _ |} as bb'.
+(* assert (Hheadereq: MB.header bb' = MB.header bb). { subst. auto. }
+ rewrite <- Hheadereq. *) subst.
+ eapply match_codestate_intro; eauto. simpl. rewrite Hheader in *. simpl in EQ. assumption.
+
+ eapply agree_set_undef_mreg; eauto. intros; auto with asmgen.
+ simpl. intro.
+ rewrite R; try congruence.
+ apply DXP.
+ destruct ep0; simpl in *; congruence.
+ apply preg_of_not_FP.
+ destruct ep0; simpl in *; congruence.
+ }
- (* MBstore *)
simpl in EQ0. rewrite Hheader in DXP.
@@ -1288,19 +1353,6 @@ Proof.
rewrite Happ. eapply exec_body_trans; eauto. rewrite Hcs2 in EXEB'; simpl in EXEB'. auto.
Qed.
-Lemma exec_body_pc:
- forall l rs1 m1 rs2 m2,
- exec_body tge l rs1 m1 = Next rs2 m2 ->
- rs2 PC = rs1 PC.
-Proof.
- induction l.
- - intros. inv H. auto.
- - intros until m2. intro EXEB.
- inv EXEB. destruct (exec_basic_instr _ _ _) eqn:EBI; try discriminate.
- eapply IHl in H0. rewrite H0.
- erewrite exec_basic_instr_pc; eauto.
-Qed.
-
Lemma exec_body_control:
forall b rs1 m1 rs2 m2 rs3 m3 fn,
exec_body tge (body b) rs1 m1 = Next rs2 m2 ->
@@ -1652,7 +1704,7 @@ Proof.
} destruct EXEC_PROLOGUE as (rs3' & EXEC_PROLOGUE & Heqrs3').
exploit exec_straight_steps_2; eauto using functions_transl.
simpl fn_blocks. simpl fn_blocks in g. omega. constructor.
- intros (ofs' & X & Y).
+ intros (ofs' & X & Y).
left; exists (State rs3' m3'); split.
eapply exec_straight_steps_1; eauto.
simpl fn_blocks. simpl fn_blocks in g. omega.
diff --git a/mppa_k1c/Asmblockgenproof1.v b/mppa_k1c/Asmblockgenproof1.v
index e1e2b0b0..00df01e3 100644
--- a/mppa_k1c/Asmblockgenproof1.v
+++ b/mppa_k1c/Asmblockgenproof1.v
@@ -20,9 +20,11 @@
Require Import Coqlib Errors Maps.
Require Import AST Integers Floats Values Memory Globalenvs.
Require Import Op Locations Machblock Conventions.
-Require Import Asmblock Asmblockgen Asmblockgenproof0.
+Require Import Asmblock Asmblockgen Asmblockgenproof0 Asmblockprops.
Require Import Chunks.
+Import PArithCoercions.
+
(** Decomposition of integer constants. *)
Lemma make_immed32_sound:
@@ -859,7 +861,7 @@ Proof.
destruct cmp; discriminate.
Qed.
-Local Hint Resolve Val_cmpu_bool_correct Val_cmplu_bool_correct.
+Local Hint Resolve Val_cmpu_bool_correct Val_cmplu_bool_correct: core.
Lemma transl_cbranch_correct_1:
forall cond args lbl k c m ms b sp rs m' tbb,
@@ -1163,7 +1165,7 @@ Proof.
split; intros; Simpl.
Qed.
-Local Hint Resolve Val_cmpu_correct Val_cmplu_correct.
+Local Hint Resolve Val_cmpu_correct Val_cmplu_correct: core.
Lemma transl_condimm_int32u_correct:
forall cmp rd r1 n k rs m,
@@ -1481,6 +1483,8 @@ Proof.
destruct (Z_lt_dec _ _); destruct (Z.eq_dec _ _); trivial; omega.
Qed.
+Ltac splitall := repeat match goal with |- _ /\ _ => split end.
+
Lemma transl_op_correct:
forall op args res k (rs: regset) m v c,
transl_op op args res k = OK c ->
@@ -1515,21 +1519,21 @@ Opaque Int.eq.
- (* Ocast8signed *)
econstructor; split.
eapply exec_straight_two. simpl;eauto. simpl;eauto.
- split; intros; simpl; Simpl.
+ repeat split; intros; simpl; Simpl.
assert (A: Int.ltu (Int.repr 24) Int.iwordsize = true) by auto.
destruct (rs x0); auto; simpl. rewrite A; simpl. Simpl. unfold Val.shr. rewrite A.
apply Val.lessdef_same. f_equal. apply Int.sign_ext_shr_shl. split; reflexivity.
- (* Ocast16signed *)
econstructor; split.
eapply exec_straight_two. simpl;eauto. simpl;eauto.
- split; intros; Simpl.
+ repeat split; intros; Simpl.
assert (A: Int.ltu (Int.repr 16) Int.iwordsize = true) by auto.
destruct (rs x0); auto; simpl. rewrite A; simpl. Simpl. unfold Val.shr. rewrite A.
apply Val.lessdef_same. f_equal. apply Int.sign_ext_shr_shl. split; reflexivity.
- (* Oshrximm *)
econstructor; split.
+ apply exec_straight_one. simpl. eauto.
- + split.
+ + repeat split.
* rewrite Pregmap.gss.
subst v.
destruct (rs x0); simpl; trivial.
@@ -1540,7 +1544,7 @@ Opaque Int.eq.
- (* Oshrxlimm *)
econstructor; split.
+ apply exec_straight_one. simpl. eauto.
- + split.
+ + repeat split.
* rewrite Pregmap.gss.
subst v.
destruct (rs x0); simpl; trivial.
@@ -1551,7 +1555,7 @@ Opaque Int.eq.
- (* Ocmp *)
exploit transl_cond_op_correct; eauto. intros (rs' & A & B & C).
- exists rs'; split. eexact A. eauto with asmgen.
+ exists rs'; repeat split; eauto with asmgen.
- (* Osel *)
unfold conditional_move in *.
@@ -1570,72 +1574,73 @@ Opaque Int.eq.
destruct c0; simpl in *.
- all:
- destruct c; simpl in *; inv EQ2;
- econstructor; split; try (apply exec_straight_one; constructor);
- split; try (simpl; intros; rewrite Pregmap.gso; trivial; assumption);
- unfold Val.select; simpl;
- unfold cmove, cmoveu;
- rewrite Pregmap.gss;
- destruct (rs x1); simpl; trivial;
- try rewrite int_ltu_to_neq;
- try rewrite int64_ltu_to_neq;
- try change (Int64.eq Int64.zero Int64.zero) with true;
- try destruct Archi.ptr64;
- repeat rewrite if_neg;
- simpl;
- trivial;
- try destruct (_ || _);
- trivial;
- try apply Val.lessdef_normalize.
+ all: destruct c.
+ all: simpl in *.
+ all: inv EQ2.
+ all: econstructor; splitall.
+ all: try apply exec_straight_one.
+ all: intros; simpl; trivial.
+ all: unfold Val.select, cmove, cmoveu; simpl.
+ all: destruct (rs x1); simpl; trivial.
+ all: try rewrite int_ltu_to_neq.
+ all: try rewrite int64_ltu_to_neq.
+ all: try change (Int64.eq Int64.zero Int64.zero) with true.
+ all: try destruct Archi.ptr64.
+ all: try rewrite Pregmap.gss.
+ all: repeat rewrite if_neg.
+ all: simpl.
+ all: try destruct (_ || _).
+ all: try apply Val.lessdef_normalize.
+ all: trivial. (* no more lessdef *)
+ all: apply Pregmap.gso; congruence.
- (* Oselimm *)
unfold conditional_move_imm32 in *.
destruct c0; simpl in *.
- all:
- destruct c; simpl in *; inv EQ0;
- econstructor; split; try (apply exec_straight_one; constructor);
- split; try (simpl; intros; rewrite Pregmap.gso; trivial; assumption);
- unfold Val.select; simpl;
- unfold cmove, cmoveu;
- rewrite Pregmap.gss;
- destruct (rs x0); simpl; trivial;
- try rewrite int_ltu_to_neq;
- try rewrite int64_ltu_to_neq;
- try change (Int64.eq Int64.zero Int64.zero) with true;
- try destruct Archi.ptr64;
- repeat rewrite if_neg;
- simpl;
- trivial;
- try destruct (_ || _);
- trivial;
- try apply Val.lessdef_normalize.
-
+ all: destruct c.
+ all: simpl in *.
+ all: inv EQ0.
+ all: econstructor; splitall.
+ all: try apply exec_straight_one.
+ all: intros; simpl; trivial.
+ all: unfold Val.select, cmove, cmoveu; simpl.
+ all: destruct (rs x0); simpl; trivial.
+ all: try rewrite int_ltu_to_neq.
+ all: try rewrite int64_ltu_to_neq.
+ all: try change (Int64.eq Int64.zero Int64.zero) with true.
+ all: try destruct Archi.ptr64.
+ all: try rewrite Pregmap.gss.
+ all: repeat rewrite if_neg.
+ all: simpl.
+ all: try destruct (_ || _).
+ all: try apply Val.lessdef_normalize.
+ all: trivial. (* no more lessdef *)
+ all: apply Pregmap.gso; congruence.
- (* Osellimm *)
unfold conditional_move_imm64 in *.
destruct c0; simpl in *.
- all:
- destruct c; simpl in *; inv EQ0;
- econstructor; split; try (apply exec_straight_one; constructor);
- split; try (simpl; intros; rewrite Pregmap.gso; trivial; assumption);
- unfold Val.select; simpl;
- unfold cmove, cmoveu;
- rewrite Pregmap.gss;
- destruct (rs x0); simpl; trivial;
- try rewrite int_ltu_to_neq;
- try rewrite int64_ltu_to_neq;
- try change (Int64.eq Int64.zero Int64.zero) with true;
- try destruct Archi.ptr64;
- repeat rewrite if_neg;
- simpl;
- trivial;
- try destruct (_ || _);
- trivial;
- try apply Val.lessdef_normalize.
-
+ all: destruct c.
+ all: simpl in *.
+ all: inv EQ0.
+ all: econstructor; splitall.
+ all: try apply exec_straight_one.
+ all: intros; simpl; trivial.
+ all: unfold Val.select, cmove, cmoveu; simpl.
+ all: destruct (rs x0); simpl; trivial.
+ all: try rewrite int_ltu_to_neq.
+ all: try rewrite int64_ltu_to_neq.
+ all: try change (Int64.eq Int64.zero Int64.zero) with true.
+ all: try destruct Archi.ptr64.
+ all: try rewrite Pregmap.gss.
+ all: repeat rewrite if_neg.
+ all: simpl.
+ all: try destruct (_ || _).
+ all: try apply Val.lessdef_normalize.
+ all: trivial. (* no more lessdef *)
+ all: apply Pregmap.gso; congruence.
Qed.
(** Memory accesses *)
@@ -1661,9 +1666,9 @@ Qed.
Lemma indexed_load_access_correct:
- forall chunk (mk_instr: ireg -> offset -> basic) rd m,
+ forall trap chunk (mk_instr: ireg -> offset -> basic) rd m,
(forall base ofs rs,
- exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset chunk rs m rd base ofs) ->
+ exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset trap chunk rs m rd base ofs) ->
forall (base: ireg) ofs k (rs: regset) v,
Mem.loadv chunk m (Val.offset_ptr rs#base ofs) = Some v ->
exists rs',
@@ -1716,7 +1721,7 @@ Proof.
/\ c = indexed_memory_access mk_instr base ofs :: k
/\ forall base' ofs' rs',
exec_basic_instr ge (mk_instr base' ofs') rs' m =
- exec_load_offset (chunk_of_type ty) rs' m rd base' ofs').
+ exec_load_offset TRAP (chunk_of_type ty) rs' m rd base' ofs').
{ unfold loadind in TR.
destruct ty, (preg_of dst); inv TR; econstructor; esplit; eauto. }
destruct A as (mk_instr & rd & rdEq & B & C). subst c. rewrite rdEq.
@@ -1784,7 +1789,9 @@ Lemma loadind_ptr_correct:
/\ forall r, r <> PC -> r <> dst -> rs'#r = rs#r.
Proof.
intros. eapply indexed_load_access_correct; eauto with asmgen.
- intros. unfold Mptr. assert (Archi.ptr64 = true). auto. rewrite H0. auto.
+ intros. unfold Mptr. assert (Archi.ptr64 = true). auto. rewrite H0.
+ instantiate (1 := TRAP).
+ auto.
Qed.
Lemma storeind_ptr_correct:
@@ -1877,11 +1884,11 @@ Proof.
Qed.
Lemma transl_load_access2_correct:
- forall chunk (mk_instr: ireg -> ireg -> basic) addr args k c rd (rs: regset) m v mro mr1 ro v',
+ forall trap chunk (mk_instr: ireg -> ireg -> basic) addr args k c rd (rs: regset) m v mro mr1 ro v',
args = mr1 :: mro :: nil ->
ireg_of mro = OK ro ->
(forall base rs,
- exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg chunk rs m rd base ro) ->
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg trap chunk rs m rd base ro) ->
transl_memory_access2 mk_instr addr args k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
Mem.loadv chunk m v = Some v' ->
@@ -1899,12 +1906,35 @@ Proof.
split; intros; Simpl. auto.
Qed.
+Lemma transl_load_access2_correct_notrap2:
+ forall chunk (mk_instr: ireg -> ireg -> basic) addr args k c rd (rs: regset) m v mro mr1 ro,
+ args = mr1 :: mro :: nil ->
+ ireg_of mro = OK ro ->
+ (forall base rs,
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg NOTRAP chunk rs m rd base ro) ->
+ transl_memory_access2 mk_instr addr args k = OK c ->
+ eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
+ Mem.loadv chunk m v = None ->
+ exists rs',
+ exec_straight ge (basics_to_code c) rs m (basics_to_code k) rs' m
+ /\ rs'#rd = concrete_default_notrap_load_value chunk
+ /\ forall r, r <> PC -> r <> RTMP -> r <> rd -> rs'#r = rs#r.
+Proof.
+ intros until ro; intros ARGS IREGE INSTR TR EV LOAD.
+ exploit transl_memory_access2_correct; eauto.
+ intros (base & ro2 & mro2 & mr2 & rs' & ARGSS & IREGEQ & A & B & C). rewrite ARGSS in ARGS. inversion ARGS. subst mr2 mro2. clear ARGS.
+ econstructor; split.
+ eapply exec_straight_opt_right. eexact A. apply exec_straight_one. assert (ro = ro2) by congruence. subst ro2.
+ rewrite INSTR. unfold exec_load_reg. unfold parexec_load_reg. rewrite B, LOAD. reflexivity. Simpl.
+ split; intros; Simpl. auto.
+Qed.
+
Lemma transl_load_access2XS_correct:
- forall chunk (mk_instr: ireg -> ireg -> basic) (scale : Z) args k c rd (rs: regset) m v mro mr1 ro v',
+ forall trap chunk (mk_instr: ireg -> ireg -> basic) (scale : Z) args k c rd (rs: regset) m v mro mr1 ro v',
args = mr1 :: mro :: nil ->
ireg_of mro = OK ro ->
(forall base rs,
- exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs chunk rs m rd base ro) ->
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs trap chunk rs m rd base ro) ->
transl_memory_access2XS chunk mk_instr scale args k = OK c ->
eval_addressing ge rs#SP (Aindexed2XS scale) (map rs (map preg_of args)) = Some v ->
Mem.loadv chunk m v = Some v' ->
@@ -1922,13 +1952,39 @@ Proof.
unfold scale_of_chunk.
subst scale.
rewrite B, LOAD. reflexivity. Simpl.
- split; intros; Simpl. auto.
+ split. trivial. intros. Simpl.
+Qed.
+
+Lemma transl_load_access2XS_correct_notrap2:
+ forall chunk (mk_instr: ireg -> ireg -> basic) (scale : Z) args k c rd (rs: regset) m v mro mr1 ro,
+ args = mr1 :: mro :: nil ->
+ ireg_of mro = OK ro ->
+ (forall base rs,
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs NOTRAP chunk rs m rd base ro) ->
+ transl_memory_access2XS chunk mk_instr scale args k = OK c ->
+ eval_addressing ge rs#SP (Aindexed2XS scale) (map rs (map preg_of args)) = Some v ->
+ Mem.loadv chunk m v = None ->
+ exists rs',
+ exec_straight ge (basics_to_code c) rs m (basics_to_code k) rs' m
+ /\ rs'#rd = concrete_default_notrap_load_value chunk
+ /\ forall r, r <> PC -> r <> RTMP -> r <> rd -> rs'#r = rs#r.
+Proof.
+ intros until ro; intros ARGS IREGE INSTR TR EV LOAD.
+ exploit transl_memory_access2XS_correct; eauto.
+ intros (base & ro2 & mro2 & mr2 & rs' & ARGSS & IREGEQ & A & B & C & D). rewrite ARGSS in ARGS. inversion ARGS. subst mr2 mro2. clear ARGS.
+ econstructor; split.
+ eapply exec_straight_opt_right. eexact A. apply exec_straight_one. assert (ro = ro2) by congruence. subst ro2.
+ rewrite INSTR. unfold exec_load_regxs. unfold parexec_load_regxs.
+ unfold scale_of_chunk.
+ subst scale.
+ rewrite B, LOAD. reflexivity. Simpl.
+ split. trivial. intros. Simpl.
Qed.
Lemma transl_load_access_correct:
- forall chunk (mk_instr: ireg -> offset -> basic) addr args k c rd (rs: regset) m v v',
+ forall trap chunk (mk_instr: ireg -> offset -> basic) addr args k c rd (rs: regset) m v v',
(forall base ofs rs,
- exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset chunk rs m rd base ofs) ->
+ exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset trap chunk rs m rd base ofs) ->
transl_memory_access mk_instr addr args k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
Mem.loadv chunk m v = Some v' ->
@@ -1946,54 +2002,119 @@ Proof.
split; intros; Simpl. auto.
Qed.
+Lemma transl_load_access_correct_notrap2:
+ forall chunk (mk_instr: ireg -> offset -> basic) addr args k c rd (rs: regset) m v,
+ (forall base ofs rs,
+ exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset NOTRAP chunk rs m rd base ofs) ->
+ transl_memory_access mk_instr addr args k = OK c ->
+ eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
+ Mem.loadv chunk m v = None ->
+ exists rs',
+ exec_straight ge (basics_to_code c) rs m (basics_to_code k) rs' m
+ /\ rs'#rd = concrete_default_notrap_load_value chunk
+ /\ forall r, r <> PC -> r <> RTMP -> r <> rd -> rs'#r = rs#r.
+Proof.
+ intros until v; intros INSTR TR EV LOAD.
+ exploit transl_memory_access_correct; eauto.
+ intros (base & ofs & rs' & ptr & A & PtrEq & B & C).
+ econstructor; split.
+ eapply exec_straight_opt_right. eexact A. apply exec_straight_one.
+ rewrite INSTR. unfold exec_load_offset. unfold parexec_load_offset. rewrite PtrEq, B, LOAD. reflexivity. Simpl.
+ split. trivial. intros. Simpl.
+Qed.
+
Lemma transl_load_memory_access_ok:
- forall addr chunk args dst k c rs a v m,
+ forall addr trap chunk args dst k c rs a v m,
(match addr with Aindexed2XS _ | Aindexed2 => False | _ => True end) ->
- transl_load chunk addr args dst k = OK c ->
+ transl_load trap chunk addr args dst k = OK c ->
eval_addressing ge (rs (IR SP)) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists mk_instr rd,
preg_of dst = IR rd
/\ transl_memory_access mk_instr addr args k = OK c
/\ forall base ofs rs,
- exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset chunk rs m rd base ofs.
+ exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset trap chunk rs m rd base ofs.
Proof.
intros until m. intros ADDR TR ? ?.
unfold transl_load in TR. destruct addr; try contradiction.
- monadInv TR. destruct chunk; ArgsInv; econstructor; (esplit; eauto).
- monadInv TR. destruct chunk. all: ArgsInv; destruct args; try discriminate; monadInv EQ0; eexists; eexists; split; try split;
- [ instantiate (1 := (PLoadRRO _ x)); simpl; reflexivity
+ [ instantiate (1 := (PLoadRRO _ _ x)); simpl; reflexivity
| eauto ].
- monadInv TR. destruct chunk. all: ArgsInv; destruct args; try discriminate; monadInv EQ0; eexists; eexists; split; try split;
- [ instantiate (1 := (PLoadRRO _ x)); simpl; reflexivity
+ [ instantiate (1 := (PLoadRRO _ _ x)); simpl; reflexivity
| eauto ].
Qed.
-Lemma transl_load_memory_access2_ok:
- forall addr chunk args dst k c rs a v m,
- addr = Aindexed2 ->
- transl_load chunk addr args dst k = OK c ->
+Lemma transl_load_memory_access_ok_notrap2:
+ forall addr chunk args dst k c rs a m,
+ (match addr with Aindexed2XS _ | Aindexed2 => False | _ => True end) ->
+ transl_load NOTRAP chunk addr args dst k = OK c ->
eval_addressing ge (rs (IR SP)) addr (map rs (map preg_of args)) = Some a ->
+ Mem.loadv chunk m a = None ->
+ exists mk_instr rd,
+ preg_of dst = IR rd
+ /\ transl_memory_access mk_instr addr args k = OK c
+ /\ forall base ofs rs,
+ exec_basic_instr ge (mk_instr base ofs) rs m = exec_load_offset NOTRAP chunk rs m rd base ofs.
+Proof.
+ intros until m. intros ADDR TR ? ?.
+ unfold transl_load in TR. destruct addr; try contradiction.
+ - monadInv TR. destruct chunk; ArgsInv; econstructor; (esplit; eauto).
+ - monadInv TR. destruct chunk. all: ArgsInv; destruct args; try discriminate; monadInv EQ0; eexists; eexists; split; try split;
+ [ instantiate (1 := (PLoadRRO _ _ x)); simpl; reflexivity
+ | eauto ].
+ - monadInv TR. destruct chunk. all: ArgsInv; destruct args; try discriminate; monadInv EQ0; eexists; eexists; split; try split;
+ [ instantiate (1 := (PLoadRRO _ _ x)); simpl; reflexivity
+ | eauto ].
+Qed.
+
+Lemma transl_load_memory_access2_ok:
+ forall trap chunk args dst k c rs a v m,
+ transl_load trap chunk Aindexed2 args dst k = OK c ->
+ eval_addressing ge (rs (IR SP)) Aindexed2 (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists mk_instr mr0 mro rd ro,
args = mr0 :: mro :: nil
/\ preg_of dst = IR rd
/\ preg_of mro = IR ro
- /\ transl_memory_access2 mk_instr addr args k = OK c
+ /\ transl_memory_access2 mk_instr Aindexed2 args k = OK c
+ /\ forall base rs,
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg trap chunk rs m rd base ro.
+Proof.
+ intros until m. intros TR ? ?.
+ unfold transl_load in TR. subst. monadInv TR. destruct chunk. all:
+ unfold transl_memory_access2 in EQ0; repeat (destruct args; try discriminate); monadInv EQ0; ArgsInv; repeat eexists;
+ [ unfold ireg_of in EQ0; destruct (preg_of m1); eauto; try discriminate; monadInv EQ0; reflexivity
+ | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRR _ _ x)); simpl; reflexivity
+ | eauto].
+Qed.
+
+
+Lemma transl_load_memory_access2_ok_notrap2:
+ forall chunk args dst k c rs a m,
+ transl_load NOTRAP chunk Aindexed2 args dst k = OK c ->
+ eval_addressing ge (rs (IR SP)) Aindexed2 (map rs (map preg_of args)) = Some a ->
+ Mem.loadv chunk m a = None ->
+ exists mk_instr mr0 mro rd ro,
+ args = mr0 :: mro :: nil
+ /\ preg_of dst = IR rd
+ /\ preg_of mro = IR ro
+ /\ transl_memory_access2 mk_instr Aindexed2 args k = OK c
/\ forall base rs,
- exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg chunk rs m rd base ro.
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_reg NOTRAP chunk rs m rd base ro.
Proof.
- intros until m. intros ? TR ? ?.
+ intros until m. intros TR ? ?.
unfold transl_load in TR. subst. monadInv TR. destruct chunk. all:
unfold transl_memory_access2 in EQ0; repeat (destruct args; try discriminate); monadInv EQ0; ArgsInv; repeat eexists;
[ unfold ireg_of in EQ0; destruct (preg_of m1); eauto; try discriminate; monadInv EQ0; reflexivity
- | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRR _ x)); simpl; reflexivity
+ | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRR _ _ x)); simpl; reflexivity
| eauto].
Qed.
Lemma transl_load_memory_access2XS_ok:
- forall scale chunk args dst k c rs a v m,
- transl_load chunk (Aindexed2XS scale) args dst k = OK c ->
+ forall scale trap chunk args dst k c rs a v m,
+ transl_load trap chunk (Aindexed2XS scale) args dst k = OK c ->
eval_addressing ge (rs (IR SP)) (Aindexed2XS scale) (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists mk_instr mr0 mro rd ro,
@@ -2002,19 +2123,41 @@ Lemma transl_load_memory_access2XS_ok:
/\ preg_of mro = IR ro
/\ transl_memory_access2XS chunk mk_instr scale args k = OK c
/\ forall base rs,
- exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs chunk rs m rd base ro.
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs trap chunk rs m rd base ro.
Proof.
intros until m. intros TR ? ?.
unfold transl_load in TR. subst. monadInv TR. destruct chunk. all:
unfold transl_memory_access2XS in EQ0; repeat (destruct args; try discriminate); monadInv EQ0; ArgsInv; repeat eexists;
[ unfold ireg_of in EQ0; destruct (preg_of m1); eauto; try discriminate; monadInv EQ0; reflexivity
- | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRRXS _ x)); simpl; rewrite Heqb; eauto
+ | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRRXS _ _ x)); simpl; rewrite Heqb; eauto
+ | eauto].
+Qed.
+
+
+Lemma transl_load_memory_access2XS_ok_notrap2:
+ forall scale chunk args dst k c rs a m,
+ transl_load NOTRAP chunk (Aindexed2XS scale) args dst k = OK c ->
+ eval_addressing ge (rs (IR SP)) (Aindexed2XS scale) (map rs (map preg_of args)) = Some a ->
+ Mem.loadv chunk m a = None ->
+ exists mk_instr mr0 mro rd ro,
+ args = mr0 :: mro :: nil
+ /\ preg_of dst = IR rd
+ /\ preg_of mro = IR ro
+ /\ transl_memory_access2XS chunk mk_instr scale args k = OK c
+ /\ forall base rs,
+ exec_basic_instr ge (mk_instr base ro) rs m = exec_load_regxs NOTRAP chunk rs m rd base ro.
+Proof.
+ intros until m. intros TR ? ?.
+ unfold transl_load in TR. subst. monadInv TR. destruct chunk. all:
+ unfold transl_memory_access2XS in EQ0; repeat (destruct args; try discriminate); monadInv EQ0; ArgsInv; repeat eexists;
+ [ unfold ireg_of in EQ0; destruct (preg_of m1); eauto; try discriminate; monadInv EQ0; reflexivity
+ | rewrite EQ1; rewrite EQ0; simpl; instantiate (1 := (PLoadRRRXS _ _ x)); simpl; rewrite Heqb; eauto
| eauto].
Qed.
Lemma transl_load_correct:
- forall chunk addr args dst k c (rs: regset) m a v,
- transl_load chunk addr args dst k = OK c ->
+ forall trap chunk addr args dst k c (rs: regset) m a v,
+ transl_load trap chunk addr args dst k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
@@ -2038,6 +2181,32 @@ Proof.
eapply transl_load_access_correct; eauto with asmgen.
Qed.
+Lemma transl_load_correct_notrap2:
+ forall chunk addr args dst k c (rs: regset) m a,
+ transl_load NOTRAP chunk addr args dst k = OK c ->
+ eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some a ->
+ Mem.loadv chunk m a = None ->
+ exists rs',
+ exec_straight ge (basics_to_code c) rs m (basics_to_code k) rs' m
+ /\ rs'#(preg_of dst) = (concrete_default_notrap_load_value chunk)
+ /\ forall r, r <> PC -> r <> RTMP -> r <> preg_of dst -> rs'#r = rs#r.
+Proof.
+ intros until a; intros TR EV LOAD. destruct addr.
+ - exploit transl_load_memory_access2XS_ok_notrap2; eauto. intros (mk_instr & mr0 & mro & rd & ro & argsEq & rdEq & roEq & B & C).
+ rewrite rdEq. eapply transl_load_access2XS_correct_notrap2; eauto with asmgen. unfold ireg_of. rewrite roEq. reflexivity.
+ - exploit transl_load_memory_access2_ok_notrap2; eauto. intros (mk_instr & mr0 & mro & rd & ro & argsEq & rdEq & roEq & B & C).
+ rewrite rdEq. eapply transl_load_access2_correct_notrap2; eauto with asmgen. unfold ireg_of. rewrite roEq. reflexivity.
+ - exploit transl_load_memory_access_ok_notrap2; eauto; try discriminate; try (simpl; reflexivity).
+ intros A; destruct A as (mk_instr & rd & rdEq & B & C); rewrite rdEq;
+ eapply transl_load_access_correct_notrap2; eauto with asmgen.
+ - exploit transl_load_memory_access_ok_notrap2; eauto; try discriminate; try (simpl; reflexivity).
+ intros A; destruct A as (mk_instr & rd & rdEq & B & C); rewrite rdEq;
+ eapply transl_load_access_correct_notrap2; eauto with asmgen.
+ - exploit transl_load_memory_access_ok_notrap2; eauto; try discriminate; try (simpl; reflexivity).
+ intros A; destruct A as (mk_instr & rd & rdEq & B & C); rewrite rdEq;
+ eapply transl_load_access_correct_notrap2; eauto with asmgen.
+Qed.
+
Lemma transl_store_access2_correct:
forall chunk (mk_instr: ireg -> ireg -> basic) addr args k c r1 (rs: regset) m v mr1 mro ro m',
args = mr1 :: mro :: nil ->
diff --git a/mppa_k1c/Asmblockprops.v b/mppa_k1c/Asmblockprops.v
new file mode 100644
index 00000000..3c6ba534
--- /dev/null
+++ b/mppa_k1c/Asmblockprops.v
@@ -0,0 +1,343 @@
+(** Common definition and proofs on Asmblock required by various modules *)
+
+Require Import Coqlib.
+Require Import Integers.
+Require Import Memory.
+Require Import Globalenvs.
+Require Import Values.
+Require Import Asmblock.
+Require Import Axioms.
+
+Definition bblock_simu (ge: Genv.t fundef unit) (f: function) (bb bb': bblock) :=
+ forall rs m,
+ exec_bblock ge f bb rs m <> Stuck ->
+ exec_bblock ge f bb rs m = exec_bblock ge f bb' rs m.
+
+Hint Extern 2 (_ <> _) => congruence: asmgen.
+
+Lemma preg_of_data:
+ forall r, data_preg (preg_of r) = true.
+Proof.
+ intros. destruct r; reflexivity.
+Qed.
+Hint Resolve preg_of_data: asmgen.
+
+Lemma data_diff:
+ forall r r',
+ data_preg r = true -> data_preg r' = false -> r <> r'.
+Proof.
+ congruence.
+Qed.
+Hint Resolve data_diff: asmgen.
+
+Lemma preg_of_not_PC:
+ forall r, preg_of r <> PC.
+Proof.
+ intros. apply data_diff; auto with asmgen.
+Qed.
+
+Lemma preg_of_not_SP:
+ forall r, preg_of r <> SP.
+Proof.
+ intros. unfold preg_of; destruct r; simpl; congruence.
+Qed.
+
+Hint Resolve preg_of_not_SP preg_of_not_PC: asmgen.
+
+
+Lemma nextblock_pc:
+ forall b rs, (nextblock b rs)#PC = Val.offset_ptr rs#PC (Ptrofs.repr (size b)).
+Proof.
+ intros. apply Pregmap.gss.
+Qed.
+
+Lemma nextblock_inv:
+ forall b r rs, r <> PC -> (nextblock b rs)#r = rs#r.
+Proof.
+ intros. unfold nextblock. apply Pregmap.gso. red; intro; subst. auto.
+Qed.
+
+Lemma nextblock_inv1:
+ forall b r rs, data_preg r = true -> (nextblock b rs)#r = rs#r.
+Proof.
+ intros. apply nextblock_inv. red; intro; subst; discriminate.
+Qed.
+
+Ltac Simplif :=
+ ((rewrite nextblock_inv by eauto with asmgen)
+ || (rewrite nextblock_inv1 by eauto with asmgen)
+ || (rewrite Pregmap.gss)
+ || (rewrite nextblock_pc)
+ || (rewrite Pregmap.gso by eauto with asmgen)
+ ); auto with asmgen.
+
+Ltac Simpl := repeat Simplif.
+
+(* For Asmblockgenproof0 *)
+
+Theorem exec_basic_instr_pc:
+ forall ge b rs1 m1 rs2 m2,
+ exec_basic_instr ge b rs1 m1 = Next rs2 m2 ->
+ rs2 PC = rs1 PC.
+Proof.
+ intros. destruct b; try destruct i; try destruct i.
+ all: try (inv H; Simpl).
+ 1-10: unfold parexec_load_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.loadv _ _ _); unfold parexec_incorrect_load in *; destruct trap; try discriminate; unfold concrete_default_notrap_load_value in *; inv H1; Simpl; fail.
+
+ 1-20: unfold parexec_load_reg, parexec_load_regxs in H1; destruct (Mem.loadv _ _ _); unfold parexec_incorrect_load in *; destruct trap; try discriminate; unfold concrete_default_notrap_load_value in *; inv H1; Simpl; fail.
+
+ { (* PLoadQRRO *)
+ unfold parexec_load_q_offset in H1.
+ destruct (gpreg_q_expand _) as [r0 r1] in H1.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ inv H1. Simpl. }
+ { (* PLoadORRO *)
+ unfold parexec_load_o_offset in H1.
+ destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ inv H1. Simpl. }
+ 1-8: unfold parexec_store_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.storev _ _ _); [inv H1; auto | discriminate]; fail.
+ 1-8: unfold parexec_store_reg in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]; auto; fail.
+ 1-8: unfold parexec_store_regxs in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]; auto; fail.
+
+ { (* PStoreQRRO *)
+ unfold parexec_store_q_offset in H1.
+ destruct (gpreg_q_expand _) as [r0 r1] in H1.
+ unfold eval_offset in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ inv H1. Simpl. reflexivity. }
+ { (* PStoreORRO *)
+ unfold parexec_store_o_offset in H1.
+ destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
+ unfold eval_offset in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ inv H1. Simpl. reflexivity. }
+ - destruct (Mem.alloc _ _ _). destruct (Mem.store _ _ _ _ _). inv H1. Simpl. discriminate.
+ - destruct (Mem.loadv _ _ _); try discriminate. destruct (rs1 _); try discriminate.
+ destruct (Mem.free _ _ _ _). inv H1. Simpl. discriminate.
+ - destruct rs; try discriminate. inv H1. Simpl.
+ - destruct rd; try discriminate. inv H1; Simpl.
+ - reflexivity.
+Qed.
+
+(* For PostpassSchedulingproof *)
+
+Lemma regset_double_set:
+ forall r1 r2 (rs: regset) v1 v2,
+ r1 <> r2 ->
+ (rs # r1 <- v1 # r2 <- v2) = (rs # r2 <- v2 # r1 <- v1).
+Proof.
+ intros. apply functional_extensionality. intros r. destruct (preg_eq r r1).
+ - subst. rewrite Pregmap.gso; auto. repeat (rewrite Pregmap.gss). auto.
+ - destruct (preg_eq r r2).
+ + subst. rewrite Pregmap.gss. rewrite Pregmap.gso; auto. rewrite Pregmap.gss. auto.
+ + repeat (rewrite Pregmap.gso; auto).
+Qed.
+
+Lemma next_eq:
+ forall (rs rs': regset) m m',
+ rs = rs' -> m = m' -> Next rs m = Next rs' m'.
+Proof.
+ intros; apply f_equal2; auto.
+Qed.
+
+Lemma exec_load_offset_pc_var:
+ forall trap t rs m rd ra ofs rs' m' v,
+ exec_load_offset trap t rs m rd ra ofs = Next rs' m' ->
+ exec_load_offset trap t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_offset in *. unfold parexec_load_offset in *. rewrite Pregmap.gso; try discriminate. destruct (eval_offset ofs); try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_reg_pc_var:
+ forall trap t rs m rd ra ro rs' m' v,
+ exec_load_reg trap t rs m rd ra ro = Next rs' m' ->
+ exec_load_reg trap t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_reg in *. unfold parexec_load_reg in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_regxs_pc_var:
+ forall trap t rs m rd ra ro rs' m' v,
+ exec_load_regxs trap t rs m rd ra ro = Next rs' m' ->
+ exec_load_regxs trap t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_regxs in *. unfold parexec_load_regxs in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_offset_q_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_load_q_offset rs m rd ra ofs = Next rs' m' ->
+ exec_load_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_q_offset in *. unfold parexec_load_q_offset in *.
+ destruct (gpreg_q_expand rd) as [rd0 rd1].
+ (* destruct (ireg_eq rd0 ra); try discriminate. *)
+ rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ inv H.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ inv H1. f_equal.
+ rewrite (regset_double_set PC rd0) by discriminate.
+ rewrite (regset_double_set PC rd1) by discriminate.
+ reflexivity.
+Qed.
+
+Lemma exec_load_offset_o_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_load_o_offset rs m rd ra ofs = Next rs' m' ->
+ exec_load_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_o_offset in *. unfold parexec_load_o_offset in *.
+ destruct (gpreg_o_expand rd) as [[[rd0 rd1] rd2] rd3].
+(*
+ destruct (ireg_eq rd0 ra); try discriminate.
+ destruct (ireg_eq rd1 ra); try discriminate.
+ destruct (ireg_eq rd2 ra); try discriminate.
+*)
+ rewrite Pregmap.gso; try discriminate.
+ simpl in *.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ rewrite (regset_double_set PC rd0) by discriminate.
+ rewrite (regset_double_set PC rd1) by discriminate.
+ rewrite (regset_double_set PC rd2) by discriminate.
+ rewrite (regset_double_set PC rd3) by discriminate.
+ inv H.
+ trivial.
+Qed.
+
+Lemma exec_store_offset_pc_var:
+ forall t rs m rd ra ofs rs' m' v,
+ exec_store_offset t rs m rd ra ofs = Next rs' m' ->
+ exec_store_offset t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_offset in *. unfold parexec_store_offset in *. rewrite Pregmap.gso; try discriminate.
+ destruct (eval_offset ofs); try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Lemma exec_store_q_offset_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_store_q_offset rs m rd ra ofs = Next rs' m' ->
+ exec_store_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_q_offset in *. unfold parexec_store_q_offset in *. rewrite Pregmap.gso; try discriminate.
+ simpl in *.
+ destruct (gpreg_q_expand _) as [s0 s1].
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ inv H. apply next_eq; auto.
+Qed.
+
+Lemma exec_store_o_offset_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_store_o_offset rs m rd ra ofs = Next rs' m' ->
+ exec_store_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros.
+ unfold exec_store_o_offset in *. unfold parexec_store_o_offset in *.
+ destruct (gpreg_o_expand _) as [[[s0 s1] s2] s3].
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ inv H.
+ trivial.
+Qed.
+
+Lemma exec_store_reg_pc_var:
+ forall t rs m rd ra ro rs' m' v,
+ exec_store_reg t rs m rd ra ro = Next rs' m' ->
+ exec_store_reg t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_reg in *. unfold parexec_store_reg in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Lemma exec_store_regxs_pc_var:
+ forall t rs m rd ra ro rs' m' v,
+ exec_store_regxs t rs m rd ra ro = Next rs' m' ->
+ exec_store_regxs t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_regxs in *. unfold parexec_store_regxs in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Theorem exec_basic_instr_pc_var:
+ forall ge i rs m rs' m' v,
+ exec_basic_instr ge i rs m = Next rs' m' ->
+ exec_basic_instr ge i (rs # PC <- v) m = Next (rs' # PC <- v) m'.
+Proof.
+ intros. unfold exec_basic_instr in *. unfold bstep in *. destruct i.
+ - unfold exec_arith_instr in *. destruct i; destruct i.
+ all: try (exploreInst; inv H; apply next_eq; auto;
+ apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate).
+(*
+ (* Some cases treated seperately because exploreInst destructs too much *)
+ all: try (inv H; apply next_eq; auto; apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate). *)
+ - destruct i.
+ + exploreInst; apply exec_load_offset_pc_var; auto.
+ + exploreInst; apply exec_load_reg_pc_var; auto.
+ + exploreInst; apply exec_load_regxs_pc_var; auto.
+ + apply exec_load_offset_q_pc_var; auto.
+ + apply exec_load_offset_o_pc_var; auto.
+ - destruct i.
+ + exploreInst; apply exec_store_offset_pc_var; auto.
+ + exploreInst; apply exec_store_reg_pc_var; auto.
+ + exploreInst; apply exec_store_regxs_pc_var; auto.
+ + apply exec_store_q_offset_pc_var; auto.
+ + apply exec_store_o_offset_pc_var; auto.
+ - destruct (Mem.alloc _ _ _) as (m1 & stk). repeat (rewrite Pregmap.gso; try discriminate).
+ destruct (Mem.storev _ _ _ _); try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros.
+ rewrite (regset_double_set GPR32 PC); try discriminate.
+ rewrite (regset_double_set GPR12 PC); try discriminate.
+ rewrite (regset_double_set FP PC); try discriminate. reflexivity.
+ - repeat (rewrite Pregmap.gso; try discriminate).
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (rs GPR12); try discriminate.
+ destruct (Mem.free _ _ _ _); try discriminate.
+ inv H. apply next_eq; auto.
+ rewrite (regset_double_set GPR32 PC).
+ rewrite (regset_double_set GPR12 PC). reflexivity.
+ all: discriminate.
+ - destruct rs0; try discriminate. inv H. apply next_eq; auto.
+ repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
+ - destruct rd; try discriminate. inv H. apply next_eq; auto.
+ repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
+ - inv H. apply next_eq; auto.
+Qed.
+
+
diff --git a/mppa_k1c/Asmexpand.ml b/mppa_k1c/Asmexpand.ml
index 67ef6f52..8ab10bc5 100644
--- a/mppa_k1c/Asmexpand.ml
+++ b/mppa_k1c/Asmexpand.ml
@@ -190,10 +190,10 @@ let expand_builtin_memcpy_big sz al src dst =
end);
cpy tmpbuf2 16L (fun x y z -> Plq(x, y, z)) (fun x y z -> Psq(x, y, z));
- cpy tmpbuf 8L (fun x y z -> Pld(x, y, z)) (fun x y z -> Psd(x, y, z));
- cpy tmpbuf 4L (fun x y z -> Plw(x, y, z)) (fun x y z -> Psw(x, y, z));
- cpy tmpbuf 2L (fun x y z -> Plh(x, y, z)) (fun x y z -> Psh(x, y, z));
- cpy tmpbuf 1L (fun x y z -> Plb(x, y, z)) (fun x y z -> Psb(x, y, z));
+ cpy tmpbuf 8L (fun x y z -> Pld(TRAP, x, y, z)) (fun x y z -> Psd(x, y, z));
+ cpy tmpbuf 4L (fun x y z -> Plw(TRAP, x, y, z)) (fun x y z -> Psw(x, y, z));
+ cpy tmpbuf 2L (fun x y z -> Plh(TRAP, x, y, z)) (fun x y z -> Psh(x, y, z));
+ cpy tmpbuf 1L (fun x y z -> Plb(TRAP, x, y, z)) (fun x y z -> Psb(x, y, z));
assert (!remaining = 0L)
end
else
@@ -203,7 +203,7 @@ let expand_builtin_memcpy_big sz al src dst =
let lbl = new_label() in
emit (Ploopdo (tmpbuf, lbl));
emit Psemi;
- emit (Plb (tmpbuf, srcptr, AOff Z.zero));
+ emit (Plb (TRAP, tmpbuf, srcptr, AOff Z.zero));
emit (Paddil (srcptr, srcptr, Z.one));
emit Psemi;
emit (Psb (tmpbuf, dstptr, AOff Z.zero));
@@ -223,30 +223,30 @@ let expand_builtin_memcpy sz al args =
let expand_builtin_vload_common chunk base ofs res =
match chunk, res with
| Mint8unsigned, BR(Asmvliw.IR res) ->
- emit (Plbu (res, base, AOff ofs))
+ emit (Plbu (TRAP, res, base, AOff ofs))
| Mint8signed, BR(Asmvliw.IR res) ->
- emit (Plb (res, base, AOff ofs))
+ emit (Plb (TRAP, res, base, AOff ofs))
| Mint16unsigned, BR(Asmvliw.IR res) ->
- emit (Plhu (res, base, AOff ofs))
+ emit (Plhu (TRAP, res, base, AOff ofs))
| Mint16signed, BR(Asmvliw.IR res) ->
- emit (Plh (res, base, AOff ofs))
+ emit (Plh (TRAP, res, base, AOff ofs))
| Mint32, BR(Asmvliw.IR res) ->
- emit (Plw (res, base, AOff ofs))
+ emit (Plw (TRAP, res, base, AOff ofs))
| Mint64, BR(Asmvliw.IR res) ->
- emit (Pld (res, base, AOff ofs))
+ emit (Pld (TRAP, res, base, AOff ofs))
| Mint64, BR_splitlong(BR(Asmvliw.IR res1), BR(Asmvliw.IR res2)) ->
let ofs' = Integers.Ptrofs.add ofs _4 in
if base <> res2 then begin
- emit (Plw (res2, base, AOff ofs));
- emit (Plw (res1, base, AOff ofs'))
+ emit (Plw (TRAP, res2, base, AOff ofs));
+ emit (Plw (TRAP, res1, base, AOff ofs'))
end else begin
- emit (Plw (res1, base, AOff ofs'));
- emit (Plw (res2, base, AOff ofs))
+ emit (Plw (TRAP, res1, base, AOff ofs'));
+ emit (Plw (TRAP, res2, base, AOff ofs))
end
| Mfloat32, BR(Asmvliw.IR res) ->
- emit (Pfls (res, base, AOff ofs))
+ emit (Pfls (TRAP, res, base, AOff ofs))
| Mfloat64, BR(Asmvliw.IR res) ->
- emit (Pfld (res, base, AOff ofs))
+ emit (Pfld (TRAP, res, base, AOff ofs))
| _ ->
assert false
@@ -514,8 +514,8 @@ let expand_instruction instr =
end else begin
let below = Integers.Ptrofs.repr (Z.neg sz) in
expand_addptrofs stack_pointer stack_pointer below;
+ emit Psemi; (* Psemi required to fit in resource constraints *)
expand_storeind_ptr stack_pointer stack_pointer (Integers.Ptrofs.add ofs below);
- (* DM we don't need it emit Psemi; *)
vararg_start_ofs := None
end
| Pfreeframe (sz, ofs) ->
diff --git a/mppa_k1c/Asmvliw.v b/mppa_k1c/Asmvliw.v
index 54e9c847..946007c1 100644
--- a/mppa_k1c/Asmvliw.v
+++ b/mppa_k1c/Asmvliw.v
@@ -308,6 +308,16 @@ Inductive cf_instruction : Type :=
.
(** Loads **)
+Definition concrete_default_notrap_load_value (chunk : memory_chunk) :=
+ match chunk with
+ | Mint8signed | Mint8unsigned | Mint16signed | Mint16unsigned
+ | Mint32 => Vint Int.zero
+ | Mint64 => Vlong Int64.zero
+ | Many32 | Many64 => Vundef
+ | Mfloat32 => Vsingle Float32.zero
+ | Mfloat64 => Vfloat Float.zero
+ end.
+
Inductive load_name : Type :=
| Plb (**r load byte *)
| Plbu (**r load byte unsigned *)
@@ -322,9 +332,9 @@ Inductive load_name : Type :=
.
Inductive ld_instruction : Type :=
- | PLoadRRO (i: load_name) (rd: ireg) (ra: ireg) (ofs: offset)
- | PLoadRRR (i: load_name) (rd: ireg) (ra: ireg) (rofs: ireg)
- | PLoadRRRXS (i: load_name) (rd: ireg) (ra: ireg) (rofs: ireg)
+ | PLoadRRO (trap: trapping_mode) (i: load_name) (rd: ireg) (ra: ireg) (ofs: offset)
+ | PLoadRRR (trap: trapping_mode) (i: load_name) (rd: ireg) (ra: ireg) (rofs: ireg)
+ | PLoadRRRXS (trap: trapping_mode) (i: load_name) (rd: ireg) (ra: ireg) (rofs: ireg)
| PLoadQRRO (rd: gpreg_q) (ra: ireg) (ofs: offset)
| PLoadORRO (rd: gpreg_o) (ra: ireg) (ofs: offset)
.
@@ -545,6 +555,8 @@ Inductive ar_instruction : Type :=
| PArithARRI64 (i: arith_name_arri64) (rd rs: ireg) (imm: int64)
.
+Module PArithCoercions.
+
Coercion PArithR: arith_name_r >-> Funclass.
Coercion PArithRR: arith_name_rr >-> Funclass.
Coercion PArithRI32: arith_name_ri32 >-> Funclass.
@@ -559,6 +571,8 @@ Coercion PArithARR: arith_name_arr >-> Funclass.
Coercion PArithARRI32: arith_name_arri32 >-> Funclass.
Coercion PArithARRI64: arith_name_arri64 >-> Funclass.
+End PArithCoercions.
+
Inductive basic : Type :=
| PArith (i: ar_instruction)
| PLoad (i: ld_instruction)
@@ -1202,10 +1216,16 @@ Definition eval_offset (ofs: offset) : res ptrofs := OK ofs.
(** * load/store *)
-Definition parexec_load_offset (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a: ireg) (ofs: offset) :=
+Definition parexec_incorrect_load trap chunk d rsw mw :=
+ match trap with
+ | TRAP => Stuck
+ | NOTRAP => Next (rsw#d <- (concrete_default_notrap_load_value chunk)) mw
+ end.
+
+Definition parexec_load_offset (trap: trapping_mode) (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a: ireg) (ofs: offset) :=
match (eval_offset ofs) with
| OK ptr => match Mem.loadv chunk mr (Val.offset_ptr (rsr a) ptr) with
- | None => Stuck
+ | None => parexec_incorrect_load trap chunk d rsw mw
| Some v => Next (rsw#d <- v) mw
end
| _ => Stuck
@@ -1250,15 +1270,15 @@ Definition parexec_load_o_offset (rsr rsw: regset) (mr mw: mem) (d : gpreg_o) (a
end
end.
-Definition parexec_load_reg (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a ro: ireg) :=
+Definition parexec_load_reg (trap: trapping_mode) (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a ro: ireg) :=
match Mem.loadv chunk mr (Val.addl (rsr a) (rsr ro)) with
- | None => Stuck
+ | None => parexec_incorrect_load trap chunk d rsw mw
| Some v => Next (rsw#d <- v) mw
end.
-Definition parexec_load_regxs (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a ro: ireg) :=
+Definition parexec_load_regxs (trap: trapping_mode) (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (d a ro: ireg) :=
match Mem.loadv chunk mr (Val.addl (rsr a) (Val.shll (rsr ro) (scale_of_chunk chunk))) with
- | None => Stuck
+ | None => parexec_incorrect_load trap chunk d rsw mw
| Some v => Next (rsw#d <- v) mw
end.
@@ -1271,7 +1291,8 @@ Definition parexec_store_offset (chunk: memory_chunk) (rsr rsw: regset) (mr mw:
| _ => Stuck
end.
-Definition parexec_store_reg (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (s a ro: ireg) :=
+Definition parexec_store_reg
+ (chunk: memory_chunk) (rsr rsw: regset) (mr mw: mem) (s a ro: ireg) :=
match Mem.storev chunk mr (Val.addl (rsr a) (rsr ro)) (rsr s) with
| None => Stuck
| Some m' => Next rsw m'
@@ -1329,7 +1350,7 @@ Definition load_chunk n :=
| Pfls => Mfloat32
| Pfld => Mfloat64
end.
-
+
Definition store_chunk n :=
match n with
| Psb => Mint8unsigned
@@ -1348,12 +1369,12 @@ Definition bstep (bi: basic) (rsr rsw: regset) (mr mw: mem) :=
match bi with
| PArith ai => Next (parexec_arith_instr ai rsr rsw) mw
- | PLoadRRO n d a ofs => parexec_load_offset (load_chunk n) rsr rsw mr mw d a ofs
- | PLoadRRR n d a ro => parexec_load_reg (load_chunk n) rsr rsw mr mw d a ro
- | PLoadRRRXS n d a ro => parexec_load_regxs (load_chunk n) rsr rsw mr mw d a ro
- | PLoadQRRO d a ofs =>
+ | PLoad (PLoadRRO trap n d a ofs) => parexec_load_offset trap (load_chunk n) rsr rsw mr mw d a ofs
+ | PLoad (PLoadRRR trap n d a ro) => parexec_load_reg trap (load_chunk n) rsr rsw mr mw d a ro
+ | PLoad (PLoadRRRXS trap n d a ro) => parexec_load_regxs trap (load_chunk n) rsr rsw mr mw d a ro
+ | PLoad (PLoadQRRO d a ofs) =>
parexec_load_q_offset rsr rsw mr mw d a ofs
- | PLoadORRO d a ofs =>
+ | PLoad (PLoadORRO d a ofs) =>
parexec_load_o_offset rsr rsw mr mw d a ofs
| PStoreRRO n s a ofs => parexec_store_offset (store_chunk n) rsr rsw mr mw s a ofs
@@ -1692,7 +1713,7 @@ Proof.
Qed.
-Local Hint Resolve parexec_bblock_write_in_order.
+Local Hint Resolve parexec_bblock_write_in_order: core.
Lemma det_parexec_write_in_order f b rs m rs' m':
det_parexec f b rs m rs' m' -> parexec_wio_bblock f b rs m = Next rs' m'.
diff --git a/mppa_k1c/Builtins1.v b/mppa_k1c/Builtins1.v
index 6186961f..3b5cd419 100644
--- a/mppa_k1c/Builtins1.v
+++ b/mppa_k1c/Builtins1.v
@@ -43,18 +43,18 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with
| BI_fmin | BI_fmax =>
- mksignature (Tfloat :: Tfloat :: nil) (Some Tfloat) cc_default
+ mksignature (Tfloat :: Tfloat :: nil) Tfloat cc_default
| BI_fminf | BI_fmaxf =>
- mksignature (Tsingle :: Tsingle :: nil) (Some Tsingle) cc_default
+ mksignature (Tsingle :: Tsingle :: nil) Tsingle cc_default
| BI_fabsf =>
- mksignature (Tsingle :: nil) (Some Tsingle) cc_default
+ mksignature (Tsingle :: nil) Tsingle cc_default
| BI_fma =>
- mksignature (Tfloat :: Tfloat :: Tfloat :: nil) (Some Tfloat) cc_default
+ mksignature (Tfloat :: Tfloat :: Tfloat :: nil) Tfloat cc_default
| BI_fmaf =>
- mksignature (Tsingle :: Tsingle :: Tsingle :: nil) (Some Tsingle) cc_default
+ mksignature (Tsingle :: Tsingle :: Tsingle :: nil) Tsingle cc_default
end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with
| BI_fmin => mkbuiltin_n2t Tfloat Tfloat Tfloat ExtFloat.min
| BI_fmax => mkbuiltin_n2t Tfloat Tfloat Tfloat ExtFloat.max
diff --git a/mppa_k1c/CSE2deps.v b/mppa_k1c/CSE2deps.v
new file mode 100644
index 00000000..8ab9242a
--- /dev/null
+++ b/mppa_k1c/CSE2deps.v
@@ -0,0 +1,20 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs (Ptrofs.unsigned ofs') chunk' (Ptrofs.unsigned ofs) chunk)
+ else true | _, _, _, _ => true
+ end.
diff --git a/mppa_k1c/CSE2depsproof.v b/mppa_k1c/CSE2depsproof.v
new file mode 100644
index 00000000..a3811e78
--- /dev/null
+++ b/mppa_k1c/CSE2depsproof.v
@@ -0,0 +1,127 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Lemma ptrofs_size :
+ Ptrofs.wordsize = (if Archi.ptr64 then 64 else 32)%nat.
+Proof.
+ unfold Ptrofs.wordsize.
+ unfold Wordsize_Ptrofs.wordsize.
+ trivial.
+Qed.
+
+Lemma ptrofs_modulus :
+ Ptrofs.modulus = if Archi.ptr64 then 18446744073709551616 else 4294967296.
+Proof.
+ unfold Ptrofs.modulus.
+ rewrite ptrofs_size.
+ destruct Archi.ptr64; reflexivity.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : ptrofs.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= Ptrofs.unsigned ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= Ptrofs.unsigned ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : Ptrofs.unsigned ofsw + size_chunk chunkw <= Ptrofs.unsigned ofsr
+ \/ Ptrofs.unsigned ofsr + size_chunk chunkr <= Ptrofs.unsigned ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in *.
+
+ rewrite ptrofs_modulus in *.
+ simpl in *.
+ inv ADDRR.
+ inv ADDRW.
+ destruct base; try discriminate.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i ofsr) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i ofsw) as [OFSW | OFSW];
+ rewrite OFSW).
+ all: try rewrite ptrofs_modulus in *.
+ all: destruct Archi.ptr64.
+
+ all: intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs (Ptrofs.unsigned ofsr) chunkr (Ptrofs.unsigned ofsw) chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs (Ptrofs.unsigned i0) chunk' (Ptrofs.unsigned i) chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away with (F:=F) (V:=V) (genv:=genv) (sp:=sp); eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/mppa_k1c/Conventions1.v b/mppa_k1c/Conventions1.v
index d41f1095..48346a6d 100644
--- a/mppa_k1c/Conventions1.v
+++ b/mppa_k1c/Conventions1.v
@@ -90,12 +90,17 @@ Definition is_float_reg (r: mreg) := false.
returned value. We treat a function without result as a function
with one integer result. *)
+
Definition loc_result (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R0
- | Some (Tint | Tany32) => One R0
- | Some (Tfloat | Tsingle | Tany64) => One R0
- | Some Tlong => if Archi.ptr64 then One R0 else One R0
+ match s.(sig_res) with
+ | Tvoid => One R0
+ | Tint8signed => One R0
+ | Tint8unsigned => One R0
+ | Tint16signed => One R0
+ | Tint16unsigned => One R0
+ | Tint | Tany32 => One R0
+ | Tfloat | Tsingle | Tany64 => One R0
+ | Tlong => if Archi.ptr64 then One R0 else One R0
end.
(** The result registers have types compatible with that given in the signature. *)
@@ -104,8 +109,8 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result, mreg_type;
- destruct (sig_res sig) as [[]|]; auto; destruct Archi.ptr64; auto.
+ intros. unfold proj_sig_res, loc_result, mreg_type.
+ destruct (sig_res sig); try destruct Archi.ptr64; simpl; trivial; destruct t; trivial.
Qed.
(** The result locations are caller-save registers *)
@@ -115,7 +120,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros. unfold loc_result, is_callee_save;
- destruct (sig_res s) as [[]|]; simpl; auto; destruct Archi.ptr64; simpl; auto.
+ destruct (sig_res s); simpl; auto; try destruct Archi.ptr64; simpl; auto; try destruct t; simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -125,14 +130,15 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
intros.
- unfold loc_result; destruct (sig_res sg) as [[]|]; auto.
- unfold mreg_type; destruct Archi.ptr64; auto.
+ unfold loc_result; destruct (sig_res sg); auto;
+ unfold mreg_type; try destruct Archi.ptr64; auto;
+ destruct t; auto.
Qed.
(** The location of the result depends only on the result part of the signature *)
@@ -409,3 +415,6 @@ Lemma loc_arguments_main:
Proof.
reflexivity.
Qed.
+
+
+Definition return_value_needs_normalization (t: rettype) : bool := false.
diff --git a/mppa_k1c/DuplicateOpcodeHeuristic.ml b/mppa_k1c/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..2ec314c1
--- /dev/null
+++ b/mppa_k1c/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,27 @@
+(* open Camlcoq *)
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccomplimm (c, n) | Ccompluimm (c, n) -> if n == Integers.Int64.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c | Ccompfs c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c | Cnotcompfs c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
diff --git a/mppa_k1c/Op.v b/mppa_k1c/Op.v
index f9a774e8..92061d04 100644
--- a/mppa_k1c/Op.v
+++ b/mppa_k1c/Op.v
@@ -1030,6 +1030,34 @@ Proof with (try exact I; try reflexivity; auto using Val.Vptr_has_type).
+ constructor.
Qed.
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivl | Odivu | Odivlu
+ | Omod | Omodl | Omodu | Omodlu
+ | Oshrximm _ | Oshrxlimm _
+ | Ointoffloat | Ointuoffloat
+ | Ointofsingle | Ointuofsingle
+ | Olongoffloat | Olonguoffloat
+ | Olongofsingle | Olonguofsingle
+ | Osingleofint | Osingleofintu
+ | Osingleoflong | Osingleoflongu
+ | Ofloatoflong | Ofloatoflongu => true
+ | _ => false
+ end.
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -1706,6 +1734,27 @@ Proof.
- apply Val.offset_ptr_inject; auto.
Qed.
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *.
+ 1,2: inv Hinjvl; trivial;
+ inv H0; trivial;
+ inv H2; trivial;
+ discriminate.
+ 2,3: inv Hinjvl; trivial; discriminate.
+ inv Hinjvl; trivial; inv H0; trivial;
+ inv H; trivial; discriminate.
+Qed.
+
End EVAL_COMPAT.
(** Compatibility of the evaluation functions with the ``is less defined'' relation over values. *)
@@ -1812,6 +1861,24 @@ Proof.
destruct H1 as [v2 [A B]]. exists v2; split; auto. rewrite val_inject_lessdef; auto.
Qed.
+
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros until vl2. intros Hlessdef Heval1.
+ destruct addr; simpl in *.
+ 1, 2, 4, 5: inv Hlessdef; trivial;
+ inv H0; trivial;
+ inv H2; trivial;
+ discriminate.
+ inv Hlessdef; trivial.
+ inv H0; trivial.
+ discriminate.
+Qed.
+
End EVAL_LESSDEF.
(** Compatibility of the evaluation functions with memory injections. *)
@@ -1864,6 +1931,19 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/mppa_k1c/Peephole.v b/mppa_k1c/Peephole.v
index 7c8f65a8..0611fdda 100644
--- a/mppa_k1c/Peephole.v
+++ b/mppa_k1c/Peephole.v
@@ -2,6 +2,7 @@ Require Import Coqlib.
Require Import Asmvliw.
Require Import Values.
Require Import Integers.
+Require Import AST.
Require Compopts.
Definition gpreg_q_list : list gpreg_q :=
@@ -89,8 +90,8 @@ Fixpoint coalesce_mem (insns : list basic) : list basic :=
| None => h0 :: (coalesce_mem t0)
end
- | (PLoadRRO Pld_a rd0 ra0 ofs0),
- (PLoadRRO Pld_a rd1 ra1 ofs1) =>
+ | (PLoad (PLoadRRO TRAP Pld_a rd0 ra0 ofs0)),
+ (PLoad (PLoadRRO TRAP Pld_a rd1 ra1 ofs1)) =>
match gpreg_q_search rd0 rd1 with
| Some rd0rd1 =>
let zofs0 := Ptrofs.signed ofs0 in
@@ -100,8 +101,8 @@ Fixpoint coalesce_mem (insns : list basic) : list basic :=
if coalesce_octuples
then
match t1 with
- | (PLoadRRO Pld_a rd2 ra2 ofs2) ::
- (PLoadRRO Pld_a rd3 ra3 ofs3) :: t3 =>
+ | (PLoad (PLoadRRO TRAP Pld_a rd2 ra2 ofs2)) ::
+ (PLoad (PLoadRRO TRAP Pld_a rd3 ra3 ofs3)) :: t3 =>
match gpreg_o_search rd0 rd1 rd2 rd3 with
| Some octuple =>
let zofs2 := Ptrofs.signed ofs2 in
diff --git a/mppa_k1c/PostpassScheduling.v b/mppa_k1c/PostpassScheduling.v
index 8b6de1e2..31180cea 100644
--- a/mppa_k1c/PostpassScheduling.v
+++ b/mppa_k1c/PostpassScheduling.v
@@ -12,7 +12,7 @@
Require Import Coqlib Errors AST Integers.
Require Import Asmblock Axioms Memory Globalenvs.
-Require Import Asmblockdeps Asmblockgenproof0.
+Require Import Asmblockdeps Asmblockgenproof0 Asmblockprops.
Require Peephole.
Local Open Scope error_monad_scope.
diff --git a/mppa_k1c/PostpassSchedulingOracle.ml b/mppa_k1c/PostpassSchedulingOracle.ml
index 327901f3..686979a6 100644
--- a/mppa_k1c/PostpassSchedulingOracle.ml
+++ b/mppa_k1c/PostpassSchedulingOracle.ml
@@ -302,7 +302,7 @@ let arith_rec i =
| PArithR (i, rd) -> arith_r_rec i (IR rd)
let load_rec i = match i with
- | PLoadRRO (i, rs1, rs2, imm) ->
+ | PLoadRRO (trap, i, rs1, rs2, imm) ->
{ inst = load_real i; write_locs = [Reg (IR rs1)]; read_locs = [Mem; Reg (IR rs2)]; imm = (Some (Off imm)) ; is_control = false;
read_at_id = []; read_at_e1 = [] }
| PLoadQRRO(rs, ra, imm) ->
@@ -313,7 +313,7 @@ let load_rec i = match i with
let (((rs0, rs1), rs2), rs3) = gpreg_o_expand rs in
{ inst = loadorro_real; write_locs = [Reg (IR rs0); Reg (IR rs1); Reg (IR rs2); Reg (IR rs3)]; read_locs = [Mem; Reg (IR ra)];
imm = (Some (Off imm)) ; is_control = false; read_at_id = []; read_at_e1 = []}
- | PLoadRRR (i, rs1, rs2, rs3) | PLoadRRRXS (i, rs1, rs2, rs3) ->
+ | PLoadRRR (trap, i, rs1, rs2, rs3) | PLoadRRRXS (trap, i, rs1, rs2, rs3) ->
{ inst = load_real i; write_locs = [Reg (IR rs1)]; read_locs = [Mem; Reg (IR rs2); Reg (IR rs3)]; imm = None ; is_control = false;
read_at_id = []; read_at_e1 = [] }
@@ -442,7 +442,9 @@ let encode_imm (imm:int64) =
else failwith @@ sprintf "encode_imm: integer too big! (%Ld)" imm
(** Resources *)
-let resource_names = ["ISSUE"; "TINY"; "LITE"; "ALU"; "LSU"; "MAU"; "BCU"; "ACC"; "DATA"; "TCA"; "BRE"; "BRO"; "NOP"]
+type rname = Rissue | Rtiny | Rlite | Rfull | Rlsu | Rmau | Rbcu | Rtca | Rauxr | Rauxw | Rcrrp | Rcrwl | Rcrwh | Rnop
+
+let resource_names = [Rissue; Rtiny; Rlite; Rfull; Rlsu; Rmau; Rbcu; Rtca; Rauxr; Rauxw; Rcrrp; Rcrwl; Rcrwh; Rnop]
let rec find_index elt l =
match l with
@@ -454,98 +456,110 @@ let resource_id resource : int = find_index resource resource_names
let resource_bound resource : int =
match resource with
- | "ISSUE" -> 8
- | "TINY" -> 4
- | "LITE" -> 2
- | "ALU" -> 1
- | "LSU" -> 1
- | "MAU" -> 1
- | "BCU" -> 1
- | "ACC" -> 1
- | "DATA" -> 1
- | "TCA" -> 1
- | "BRE" -> 1
- | "BRO" -> 1
- | "NOP" -> 4
- | _ -> raise Not_found
+ | Rissue -> 8
+ | Rtiny -> 4
+ | Rlite -> 2
+ | Rfull -> 1
+ | Rlsu -> 1
+ | Rmau -> 1
+ | Rbcu -> 1
+ | Rtca -> 1
+ | Rauxr -> 1
+ | Rauxw -> 1
+ | Rcrrp -> 1
+ | Rcrwl -> 1
+ | Rcrwh -> 1
+ | Rnop -> 4
let resource_bounds : int array = Array.of_list (List.map resource_bound resource_names)
(** Reservation tables *)
-let alu_tiny : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | _ -> 0
- in Array.of_list (List.map resmap resource_names)
-
-let alu_tiny_x : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 2 | "TINY" -> 1 | _ -> 0
- in Array.of_list (List.map resmap resource_names)
-
-let alu_tiny_y : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 3 | "TINY" -> 1 | _ -> 0
+let alu_full : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | Rlite -> 1 | Rfull -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let alu_lite : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | "LITE" -> 1 | _ -> 0
+ | Rissue -> 1 | Rtiny -> 1 | Rlite -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let alu_lite_x : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 2 | "TINY" -> 1 | "LITE" -> 1 | _ -> 0
+ | Rissue -> 2 | Rtiny -> 1 | Rlite -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let alu_lite_y : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 3 | "TINY" -> 1 | "LITE" -> 1 | _ -> 0
- in Array.of_list (List.map resmap resource_names)
-
-let alu_full : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | "LITE" -> 1 | "ALU" -> 1 | _ -> 0
+ | Rissue -> 3 | Rtiny -> 1 | Rlite -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let alu_nop : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "NOP" -> 1 | _ -> 0
+ | Rissue -> 1 | Rnop -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let mau : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | "MAU" -> 1 | _ -> 0
+let alu_tiny : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let mau_x : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 2 | "TINY" -> 1 | "MAU" -> 1 | _ -> 0
+let alu_tiny_x : int array = let resmap = fun r -> match r with
+ | Rissue -> 2 | Rtiny -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let mau_y : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 3 | "TINY" -> 1 | "MAU" -> 1 | _ -> 0
+let alu_tiny_y : int array = let resmap = fun r -> match r with
+ | Rissue -> 3 | Rtiny -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let bcu : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "BCU" -> 1 | _ -> 0
+ | Rissue -> 1 | Rbcu -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
let bcu_tiny_tiny_mau_xnop : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 2 | "MAU" -> 1 | "BCU" -> 1 | "NOP" -> 4 | _ -> 0
+ | Rissue -> 1 | Rtiny -> 2 | Rmau -> 1 | Rbcu -> 1 | Rnop -> 4 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxr : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | Rlsu -> 1 | Rauxr -> 1 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxr_x : int array = let resmap = fun r -> match r with
+ | Rissue -> 2 | Rtiny -> 1 | Rlsu -> 1 | Rauxr -> 1 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxr_y : int array = let resmap = fun r -> match r with
+ | Rissue -> 3 | Rtiny -> 1 | Rlsu -> 1 | Rauxr -> 1 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxw : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | Rlsu -> 1 | Rauxw -> 1 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxw_x : int array = let resmap = fun r -> match r with
+ | Rissue -> 2 | Rtiny -> 1 | Rlsu -> 1 | Rauxw -> 1 | _ -> 0
+ in Array.of_list (List.map resmap resource_names)
+
+let lsu_auxw_y : int array = let resmap = fun r -> match r with
+ | Rissue -> 3 | Rtiny -> 1 | Rlsu -> 1 | Rauxw -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_acc : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | "LSU" -> 1 | "ACC" -> 1 | _ -> 0
+let mau : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | Rmau -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_acc_x : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 2 | "TINY" -> 1 | "LSU" -> 1 | "ACC" -> 1 | _ -> 0
+let mau_x : int array = let resmap = fun r -> match r with
+ | Rissue -> 2 | Rtiny -> 1 | Rmau -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_acc_y : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 3 | "TINY" -> 1 | "LSU" -> 1 | "ACC" -> 1 | _ -> 0
+let mau_y : int array = let resmap = fun r -> match r with
+ | Rissue -> 3 | Rtiny -> 1 | Rmau -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_data : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 1 | "TINY" -> 1 | "LSU" -> 1 | "DATA" -> 1 | _ -> 0
+let mau_auxr : int array = let resmap = fun r -> match r with
+ | Rissue -> 1 | Rtiny -> 1 | Rmau -> 1 | Rauxr -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_data_x : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 2 | "TINY" -> 1 | "LSU" -> 1 | "DATA" -> 1 | _ -> 0
+let mau_auxr_x : int array = let resmap = fun r -> match r with
+ | Rissue -> 2 | Rtiny -> 1 | Rmau -> 1 | Rauxr -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
-let lsu_data_y : int array = let resmap = fun r -> match r with
- | "ISSUE" -> 3 | "TINY" -> 1 | "LSU" -> 1 | "DATA" -> 1 | _ -> 0
+let mau_auxr_y : int array = let resmap = fun r -> match r with
+ | Rissue -> 3 | Rtiny -> 1 | Rmau -> 1 | Rauxr -> 1 | _ -> 0
in Array.of_list (List.map resmap resource_names)
(** Real instructions *)
@@ -599,10 +613,16 @@ let rec_to_usage r =
| Some U27L5 | Some U27L10 -> alu_tiny_x
| Some E27U27L10 -> alu_tiny_y
| _ -> raise InvalidEncoding)
- | Mulw| Maddw | Msbfw -> (match encoding with None -> mau
+ | Maddw -> (match encoding with None -> mau_auxr
+ | Some U6 | Some S10 | Some U27L5 -> mau_auxr_x
+ | _ -> raise InvalidEncoding)
+ | Maddd -> (match encoding with None | Some U6 | Some S10 -> mau_auxr
+ | Some U27L5 | Some U27L10 -> mau_auxr_x
+ | Some E27U27L10 -> mau_auxr_y)
+ | Mulw| Msbfw -> (match encoding with None -> mau
| Some U6 | Some S10 | Some U27L5 -> mau_x
| _ -> raise InvalidEncoding)
- | Muld | Maddd | Msbfd -> (match encoding with None | Some U6 | Some S10 -> mau
+ | Muld | Msbfd -> (match encoding with None | Some U6 | Some S10 -> mau
| Some U27L5 | Some U27L10 -> mau_x
| Some E27U27L10 -> mau_y)
| Nop -> alu_nop
@@ -612,13 +632,13 @@ let rec_to_usage r =
| Extfz | Extfs | Insf -> (match encoding with None -> alu_lite | _ -> raise InvalidEncoding)
| Fixeduwz | Fixedwz | Floatwz | Floatuwz | Fixeddz | Fixedudz | Floatdz | Floatudz -> mau
| Lbs | Lbz | Lhs | Lhz | Lws | Ld | Lq | Lo ->
- (match encoding with None | Some U6 | Some S10 -> lsu_data
- | Some U27L5 | Some U27L10 -> lsu_data_x
- | Some E27U27L10 -> lsu_data_y)
+ (match encoding with None | Some U6 | Some S10 -> lsu_auxw
+ | Some U27L5 | Some U27L10 -> lsu_auxw_x
+ | Some E27U27L10 -> lsu_auxw_y)
| Sb | Sh | Sw | Sd | Sq | So ->
- (match encoding with None | Some U6 | Some S10 -> lsu_acc
- | Some U27L5 | Some U27L10 -> lsu_acc_x
- | Some E27U27L10 -> lsu_acc_y)
+ (match encoding with None | Some U6 | Some S10 -> lsu_auxr
+ | Some U27L5 | Some U27L10 -> lsu_auxr_x
+ | Some E27U27L10 -> lsu_auxr_y)
| Icall | Call | Cb | Igoto | Goto | Ret | Set -> bcu
| Get -> bcu_tiny_tiny_mau_xnop
| Fnegd | Fnegw | Fabsd | Fabsw | Fwidenlwd
diff --git a/mppa_k1c/PostpassSchedulingproof.v b/mppa_k1c/PostpassSchedulingproof.v
index 21af276b..8cc7f0ab 100644
--- a/mppa_k1c/PostpassSchedulingproof.v
+++ b/mppa_k1c/PostpassSchedulingproof.v
@@ -14,7 +14,7 @@ Require Import Coqlib Errors.
Require Import Integers Floats AST Linking.
Require Import Values Memory Events Globalenvs Smallstep.
Require Import Op Locations Machblock Conventions Asmblock.
-Require Import Asmblockgenproof0.
+Require Import Asmblockgenproof0 Asmblockprops.
Require Import PostpassScheduling.
Require Import Asmblockgenproof.
Require Import Axioms.
@@ -30,62 +30,6 @@ Proof.
intros. eapply match_transform_partial_program; eauto.
Qed.
-Remark builtin_body_nil:
- forall bb ef args res, exit bb = Some (PExpand (Pbuiltin ef args res)) -> body bb = nil.
-Proof.
- intros. destruct bb as [hd bdy ex WF]. simpl in *.
- apply wf_bblock_refl in WF. inv WF. unfold builtin_alone in H1.
- eapply H1; eauto.
-Qed.
-
-Lemma exec_body_app:
- forall l l' ge rs m rs'' m'',
- exec_body ge (l ++ l') rs m = Next rs'' m'' ->
- exists rs' m',
- exec_body ge l rs m = Next rs' m'
- /\ exec_body ge l' rs' m' = Next rs'' m''.
-Proof.
- induction l.
- - intros. simpl in H. repeat eexists. auto.
- - intros. rewrite <- app_comm_cons in H. simpl in H.
- destruct (exec_basic_instr ge a rs m) eqn:EXEBI.
- + apply IHl in H. destruct H as (rs1 & m1 & EXEB1 & EXEB2).
- repeat eexists. simpl. rewrite EXEBI. eauto. auto.
- + discriminate.
-Qed.
-
-Lemma exec_body_pc:
- forall l ge rs1 m1 rs2 m2,
- exec_body ge l rs1 m1 = Next rs2 m2 ->
- rs2 PC = rs1 PC.
-Proof.
- induction l.
- - intros. inv H. auto.
- - intros until m2. intro EXEB.
- inv EXEB. destruct (exec_basic_instr _ _ _) eqn:EBI; try discriminate.
- eapply IHl in H0. rewrite H0.
- erewrite exec_basic_instr_pc; eauto.
-Qed.
-
-Lemma next_eq:
- forall (rs rs': regset) m m',
- rs = rs' -> m = m' -> Next rs m = Next rs' m'.
-Proof.
- intros; apply f_equal2; auto.
-Qed.
-
-Lemma regset_double_set:
- forall r1 r2 (rs: regset) v1 v2,
- r1 <> r2 ->
- (rs # r1 <- v1 # r2 <- v2) = (rs # r2 <- v2 # r1 <- v1).
-Proof.
- intros. apply functional_extensionality. intros r. destruct (preg_eq r r1).
- - subst. rewrite Pregmap.gso; auto. repeat (rewrite Pregmap.gss). auto.
- - destruct (preg_eq r r2).
- + subst. rewrite Pregmap.gss. rewrite Pregmap.gso; auto. rewrite Pregmap.gss. auto.
- + repeat (rewrite Pregmap.gso; auto).
-Qed.
-
Lemma regset_double_set_id:
forall r (rs: regset) v1 v2,
(rs # r <- v1 # r <- v2) = (rs # r <- v2).
@@ -95,191 +39,6 @@ Proof.
- repeat (rewrite Pregmap.gso); auto.
Qed.
-Lemma exec_load_offset_pc_var:
- forall t rs m rd ra ofs rs' m' v,
- exec_load_offset t rs m rd ra ofs = Next rs' m' ->
- exec_load_offset t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_load_offset in *. unfold parexec_load_offset in *. rewrite Pregmap.gso; try discriminate. destruct (eval_offset ofs); try discriminate.
- destruct (Mem.loadv _ _ _).
- - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
- - discriminate.
-Qed.
-
-Lemma exec_load_reg_pc_var:
- forall t rs m rd ra ro rs' m' v,
- exec_load_reg t rs m rd ra ro = Next rs' m' ->
- exec_load_reg t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_load_reg in *. unfold parexec_load_reg in *. rewrite Pregmap.gso; try discriminate.
- destruct (Mem.loadv _ _ _).
- - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
- - discriminate.
-Qed.
-
-Lemma exec_load_regxs_pc_var:
- forall t rs m rd ra ro rs' m' v,
- exec_load_regxs t rs m rd ra ro = Next rs' m' ->
- exec_load_regxs t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_load_regxs in *. unfold parexec_load_regxs in *. rewrite Pregmap.gso; try discriminate.
- destruct (Mem.loadv _ _ _).
- - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
- - discriminate.
-Qed.
-
-Lemma exec_load_offset_q_pc_var:
- forall rs m rd ra ofs rs' m' v,
- exec_load_q_offset rs m rd ra ofs = Next rs' m' ->
- exec_load_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_load_q_offset in *. unfold parexec_load_q_offset in *.
- destruct (gpreg_q_expand rd) as [rd0 rd1].
- (* destruct (ireg_eq rd0 ra); try discriminate. *)
- rewrite Pregmap.gso; try discriminate.
- destruct (Mem.loadv _ _ _); try discriminate.
- inv H.
- destruct (Mem.loadv _ _ _); try discriminate.
- inv H1. f_equal.
- rewrite (regset_double_set PC rd0) by discriminate.
- rewrite (regset_double_set PC rd1) by discriminate.
- reflexivity.
-Qed.
-
-Lemma exec_load_offset_o_pc_var:
- forall rs m rd ra ofs rs' m' v,
- exec_load_o_offset rs m rd ra ofs = Next rs' m' ->
- exec_load_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_load_o_offset in *. unfold parexec_load_o_offset in *.
- destruct (gpreg_o_expand rd) as [[[rd0 rd1] rd2] rd3].
-(*
- destruct (ireg_eq rd0 ra); try discriminate.
- destruct (ireg_eq rd1 ra); try discriminate.
- destruct (ireg_eq rd2 ra); try discriminate.
-*)
- rewrite Pregmap.gso; try discriminate.
- simpl in *.
- destruct (Mem.loadv _ _ _); try discriminate.
- destruct (Mem.loadv _ _ _); try discriminate.
- destruct (Mem.loadv _ _ _); try discriminate.
- destruct (Mem.loadv _ _ _); try discriminate.
- rewrite (regset_double_set PC rd0) by discriminate.
- rewrite (regset_double_set PC rd1) by discriminate.
- rewrite (regset_double_set PC rd2) by discriminate.
- rewrite (regset_double_set PC rd3) by discriminate.
- inv H.
- trivial.
-Qed.
-
-Lemma exec_store_offset_pc_var:
- forall t rs m rd ra ofs rs' m' v,
- exec_store_offset t rs m rd ra ofs = Next rs' m' ->
- exec_store_offset t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_store_offset in *. unfold parexec_store_offset in *. rewrite Pregmap.gso; try discriminate.
- destruct (eval_offset ofs); try discriminate.
- destruct (Mem.storev _ _ _).
- - inv H. apply next_eq; auto.
- - discriminate.
-Qed.
-
-Lemma exec_store_q_offset_pc_var:
- forall rs m rd ra ofs rs' m' v,
- exec_store_q_offset rs m rd ra ofs = Next rs' m' ->
- exec_store_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_store_q_offset in *. unfold parexec_store_q_offset in *. rewrite Pregmap.gso; try discriminate.
- simpl in *.
- destruct (gpreg_q_expand _) as [s0 s1].
- destruct (Mem.storev _ _ _); try discriminate.
- destruct (Mem.storev _ _ _); try discriminate.
- inv H. apply next_eq; auto.
-Qed.
-
-Lemma exec_store_o_offset_pc_var:
- forall rs m rd ra ofs rs' m' v,
- exec_store_o_offset rs m rd ra ofs = Next rs' m' ->
- exec_store_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
-Proof.
- intros.
- unfold exec_store_o_offset in *. unfold parexec_store_o_offset in *.
- destruct (gpreg_o_expand _) as [[[s0 s1] s2] s3].
- destruct (Mem.storev _ _ _); try discriminate.
- destruct (Mem.storev _ _ _); try discriminate.
- destruct (Mem.storev _ _ _); try discriminate.
- destruct (Mem.storev _ _ _); try discriminate.
- inv H.
- trivial.
-Qed.
-
-Lemma exec_store_reg_pc_var:
- forall t rs m rd ra ro rs' m' v,
- exec_store_reg t rs m rd ra ro = Next rs' m' ->
- exec_store_reg t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_store_reg in *. unfold parexec_store_reg in *. rewrite Pregmap.gso; try discriminate.
- destruct (Mem.storev _ _ _).
- - inv H. apply next_eq; auto.
- - discriminate.
-Qed.
-
-Lemma exec_store_regxs_pc_var:
- forall t rs m rd ra ro rs' m' v,
- exec_store_regxs t rs m rd ra ro = Next rs' m' ->
- exec_store_regxs t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
-Proof.
- intros. unfold exec_store_regxs in *. unfold parexec_store_regxs in *. rewrite Pregmap.gso; try discriminate.
- destruct (Mem.storev _ _ _).
- - inv H. apply next_eq; auto.
- - discriminate.
-Qed.
-
-Lemma exec_basic_instr_pc_var:
- forall ge i rs m rs' m' v,
- exec_basic_instr ge i rs m = Next rs' m' ->
- exec_basic_instr ge i (rs # PC <- v) m = Next (rs' # PC <- v) m'.
-Proof.
- intros. unfold exec_basic_instr in *. unfold bstep in *. destruct i.
- - unfold exec_arith_instr in *. destruct i; destruct i.
- all: try (exploreInst; inv H; apply next_eq; auto;
- apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate).
-(*
- (* Some cases treated seperately because exploreInst destructs too much *)
- all: try (inv H; apply next_eq; auto; apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate). *)
- - destruct i.
- + exploreInst; apply exec_load_offset_pc_var; auto.
- + exploreInst; apply exec_load_reg_pc_var; auto.
- + exploreInst; apply exec_load_regxs_pc_var; auto.
- + apply exec_load_offset_q_pc_var; auto.
- + apply exec_load_offset_o_pc_var; auto.
- - destruct i.
- + exploreInst; apply exec_store_offset_pc_var; auto.
- + exploreInst; apply exec_store_reg_pc_var; auto.
- + exploreInst; apply exec_store_regxs_pc_var; auto.
- + apply exec_store_q_offset_pc_var; auto.
- + apply exec_store_o_offset_pc_var; auto.
- - destruct (Mem.alloc _ _ _) as (m1 & stk). repeat (rewrite Pregmap.gso; try discriminate).
- destruct (Mem.storev _ _ _ _); try discriminate.
- inv H. apply next_eq; auto. apply functional_extensionality. intros.
- rewrite (regset_double_set GPR32 PC); try discriminate.
- rewrite (regset_double_set GPR12 PC); try discriminate.
- rewrite (regset_double_set FP PC); try discriminate. reflexivity.
- - repeat (rewrite Pregmap.gso; try discriminate).
- destruct (Mem.loadv _ _ _); try discriminate.
- destruct (rs GPR12); try discriminate.
- destruct (Mem.free _ _ _ _); try discriminate.
- inv H. apply next_eq; auto.
- rewrite (regset_double_set GPR32 PC).
- rewrite (regset_double_set GPR12 PC). reflexivity.
- all: discriminate.
- - destruct rs0; try discriminate. inv H. apply next_eq; auto.
- repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
- - destruct rd; try discriminate. inv H. apply next_eq; auto.
- repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
- - inv H. apply next_eq; auto.
-Qed.
-
Lemma exec_body_pc_var:
forall l ge rs m rs' m' v,
exec_body ge l rs m = Next rs' m' ->
@@ -302,9 +61,9 @@ Proof.
- subst. repeat (rewrite Pregmap.gss); auto.
destruct v; simpl; auto.
rewrite Ptrofs.add_assoc.
- cutrewrite (Ptrofs.repr (x + y) = Ptrofs.add (Ptrofs.repr x) (Ptrofs.repr y)); auto.
+ enough (Ptrofs.repr (x + y) = Ptrofs.add (Ptrofs.repr x) (Ptrofs.repr y)) as ->; auto.
unfold Ptrofs.add.
- cutrewrite (x + y = Ptrofs.unsigned (Ptrofs.repr x) + Ptrofs.unsigned (Ptrofs.repr y)); auto.
+ enough (x + y = Ptrofs.unsigned (Ptrofs.repr x) + Ptrofs.unsigned (Ptrofs.repr y)) as ->; auto.
repeat (rewrite Ptrofs.unsigned_repr); auto.
- repeat (rewrite Pregmap.gso; auto).
Qed.
@@ -461,7 +220,8 @@ Proof.
destruct (zeq pos 0).
+ inv H. exists lbb. constructor; auto.
+ apply IHlbb in H. destruct H as (c & TAIL). exists c.
- cutrewrite (pos = pos - size a + size a). apply code_tail_S; auto.
+ enough (pos = pos - size a + size a) as ->.
+ apply code_tail_S; auto.
omega.
Qed.
@@ -776,12 +536,8 @@ Qed.
End PRESERVATION_ASMBLOCK.
-
-
-
Require Import Asmvliw.
-
Lemma verified_par_checks_alls_bundles lb x: forall bundle,
verify_par lb = OK x ->
List.In bundle lb -> verify_par_bblock bundle = OK tt.
@@ -792,7 +548,6 @@ Proof.
destruct x0; auto.
Qed.
-
Lemma verified_schedule_nob_checks_alls_bundles bb lb bundle:
verified_schedule_nob bb = OK lb ->
List.In bundle lb -> verify_par_bblock bundle = OK tt.
@@ -813,7 +568,7 @@ Proof.
unfold builtin_alone in H0. erewrite H0; eauto.
Qed.
-Local Hint Resolve verified_schedule_nob_checks_alls_bundles.
+Local Hint Resolve verified_schedule_nob_checks_alls_bundles: core.
Lemma verified_schedule_checks_alls_bundles bb lb bundle:
verified_schedule bb = OK lb ->
@@ -914,9 +669,6 @@ Qed.
End PRESERVATION_ASMVLIW.
-
-
-
Section PRESERVATION.
Variables prog tprog: program.
diff --git a/mppa_k1c/TargetPrinter.ml b/mppa_k1c/TargetPrinter.ml
index 0c179a07..930b1c51 100644
--- a/mppa_k1c/TargetPrinter.ml
+++ b/mppa_k1c/TargetPrinter.ml
@@ -251,6 +251,10 @@ module Target (*: TARGET*) =
| ARegXS _ -> fprintf oc ".xs"
| _ -> ()
+ let lsvariant oc = function
+ | TRAP -> ()
+ | NOTRAP -> output_string oc ".s"
+
let icond_name = let open Asmvliw in function
| ITne | ITneu -> "ne"
| ITeq | ITequ -> "eq"
@@ -420,18 +424,18 @@ module Target (*: TARGET*) =
section oc Section_text
(* Load/Store instructions *)
- | Plb(rd, ra, adr) ->
- fprintf oc " lbs%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
- | Plbu(rd, ra, adr) ->
- fprintf oc " lbz%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
- | Plh(rd, ra, adr) ->
- fprintf oc " lhs%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
- | Plhu(rd, ra, adr) ->
- fprintf oc " lhz%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
- | Plw(rd, ra, adr) | Plw_a(rd, ra, adr) | Pfls(rd, ra, adr) ->
- fprintf oc " lws%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
- | Pld(rd, ra, adr) | Pfld(rd, ra, adr) | Pld_a(rd, ra, adr) -> assert Archi.ptr64;
- fprintf oc " ld%a %a = %a[%a]\n" xscale adr ireg rd addressing adr ireg ra
+ | Plb(trap, rd, ra, adr) ->
+ fprintf oc " lbs%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
+ | Plbu(trap, rd, ra, adr) ->
+ fprintf oc " lbz%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
+ | Plh(trap, rd, ra, adr) ->
+ fprintf oc " lhs%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
+ | Plhu(trap, rd, ra, adr) ->
+ fprintf oc " lhz%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
+ | Plw(trap, rd, ra, adr) | Plw_a(trap, rd, ra, adr) | Pfls(trap, rd, ra, adr) ->
+ fprintf oc " lws%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
+ | Pld(trap, rd, ra, adr) | Pfld(trap, rd, ra, adr) | Pld_a(trap, rd, ra, adr) -> assert Archi.ptr64;
+ fprintf oc " ld%a%a %a = %a[%a]\n" lsvariant trap xscale adr ireg rd addressing adr ireg ra
| Plq(rd, ra, adr) ->
fprintf oc " lq%a %a = %a[%a]\n" xscale adr gpreg_q rd addressing adr ireg ra
| Plo(rd, ra, adr) ->
diff --git a/mppa_k1c/ValueAOp.v b/mppa_k1c/ValueAOp.v
index 2c9bdf3e..7d84447e 100644
--- a/mppa_k1c/ValueAOp.v
+++ b/mppa_k1c/ValueAOp.v
@@ -472,6 +472,24 @@ Proof.
rewrite Ptrofs.add_zero_l; eauto with va.
Qed.
+Theorem eval_static_addressing_sound_none:
+ forall addr vargs aargs,
+ eval_addressing ge (Vptr sp Ptrofs.zero) addr vargs = None ->
+ list_forall2 (vmatch bc) vargs aargs ->
+ (eval_static_addressing addr aargs) = Vbot.
+Proof.
+ unfold eval_addressing, eval_static_addressing.
+ intros until aargs. intros Heval_none Hlist.
+ inv Hlist.
+ destruct addr; trivial; discriminate.
+ inv H0.
+ destruct addr; trivial; discriminate.
+ inv H2.
+ destruct addr; trivial; discriminate.
+ inv H3;
+ destruct addr; trivial; discriminate.
+Qed.
+
Theorem eval_static_operation_sound:
forall op vargs m vres aargs,
eval_operation ge (Vptr sp Ptrofs.zero) op vargs m = Some vres ->
diff --git a/mppa_k1c/abstractbb/AbstractBasicBlocksDef.v b/mppa_k1c/abstractbb/AbstractBasicBlocksDef.v
index 5c94d435..cf46072f 100644
--- a/mppa_k1c/abstractbb/AbstractBasicBlocksDef.v
+++ b/mppa_k1c/abstractbb/AbstractBasicBlocksDef.v
@@ -403,7 +403,7 @@ Proof.
* eapply H2; eauto. intros; eapply H0; eauto. rewrite rev_append_rev, in_app_iff; auto.
* intros; eapply H0; eauto. rewrite rev_append_rev, in_app_iff, <- in_rev; auto.
Qed.
-Local Hint Resolve app_fail_allvalid_correct.
+Local Hint Resolve app_fail_allvalid_correct: core.
Lemma app_fail_correct l pt t1 t2:
match_pt t1 pt ->
diff --git a/mppa_k1c/abstractbb/ImpSimuTest.v b/mppa_k1c/abstractbb/ImpSimuTest.v
index ea55b735..7a77ec15 100644
--- a/mppa_k1c/abstractbb/ImpSimuTest.v
+++ b/mppa_k1c/abstractbb/ImpSimuTest.v
@@ -304,12 +304,12 @@ Proof.
rewrite <- EQT; eauto.
+ exploit smem_valid_set_decompose_1; eauto.
- clear DM0. unfold hsmem_post_eval, hsmem_post_eval in * |- *; simpl.
- Local Hint Resolve smem_valid_set_decompose_1.
+ Local Hint Resolve smem_valid_set_decompose_1: core.
intros; case (R.eq_dec x x0).
+ intros; subst; rewrite !Dict.set_spec_eq; simpl; eauto.
+ intros; rewrite !Dict.set_spec_diff; simpl; eauto.
Qed.
-Local Hint Resolve naive_set_correct.
+Local Hint Resolve naive_set_correct: core.
Definition equiv_hsmem ge (hd1 hd2: hsmem) :=
(forall m, allvalid ge hd1.(hpre) m <-> allvalid ge hd2.(hpre) m)
@@ -523,7 +523,7 @@ Lemma hinst_smem_correct i: forall hd hod,
WHEN hinst_smem i hd hod ~> hd' THEN
forall ge od d, smem_model ge od hod -> smem_model ge d hd -> (forall m, smem_valid ge d m -> smem_valid ge od m) -> smem_model ge (inst_smem i d od) hd'.
Proof.
- Local Hint Resolve smem_valid_set_proof.
+ Local Hint Resolve smem_valid_set_proof: core.
induction i; simpl; wlp_simplify; eauto 15 with wlp.
Qed.
Global Opaque hinst_smem.
@@ -563,7 +563,7 @@ Definition bblock_hsmem: bblock -> ?? hsmem
Lemma bblock_hsmem_correct p:
WHEN bblock_hsmem p ~> hd THEN forall ge, smem_model ge (bblock_smem p) hd.
Proof.
- Local Hint Resolve hsmem_empty_correct.
+ Local Hint Resolve hsmem_empty_correct: core.
wlp_simplify.
Qed.
Global Opaque bblock_hsmem.
@@ -775,7 +775,7 @@ Proof.
intro H; erewrite <- list_term_eval_set_hid; rewrite H. apply list_term_eval_set_hid.
Qed.
-Local Hint Resolve term_eval_set_hid_equiv list_term_eval_set_hid_equiv.
+Local Hint Resolve term_eval_set_hid_equiv list_term_eval_set_hid_equiv: core.
Program Definition bblock_simu_test (p1 p2: bblock): ?? bool :=
DO log <~ count_logger ();;
@@ -802,7 +802,7 @@ Obligation 2.
wlp_simplify.
Qed.
-Local Hint Resolve g_bblock_simu_test_correct.
+Local Hint Resolve g_bblock_simu_test_correct: core.
Theorem bblock_simu_test_correct p1 p2:
WHEN bblock_simu_test p1 p2 ~> b THEN b=true -> forall ge, bblock_simu ge p1 p2.
@@ -1123,7 +1123,7 @@ Definition get {A} (d:t A) (x:R.t): option A
Definition set {A} (d:t A) (x:R.t) (v:A): t A
:= PositiveMap.add x v d.
-Local Hint Unfold PositiveMap.E.eq.
+Local Hint Unfold PositiveMap.E.eq: core.
Lemma set_spec_eq A d x (v: A):
get (set d x v) x = Some v.
diff --git a/mppa_k1c/abstractbb/Impure/ImpHCons.v b/mppa_k1c/abstractbb/Impure/ImpHCons.v
index d8002375..637116cc 100644
--- a/mppa_k1c/abstractbb/Impure/ImpHCons.v
+++ b/mppa_k1c/abstractbb/Impure/ImpHCons.v
@@ -95,7 +95,7 @@ Proof.
wlp_simplify.
Qed.
Global Opaque assert_list_incl.
-Hint Resolve assert_list_incl_correct.
+Hint Resolve assert_list_incl_correct: wlp.
End Sets.
@@ -165,7 +165,7 @@ Lemma hConsV_correct A (hasheq: A -> A -> ?? bool):
(forall x y, WHEN hasheq x y ~> b THEN b=true -> x=y) ->
forall x, WHEN hco.(hC) x ~> x' THEN x.(hdata).(data)=x'.(data).
Proof.
- Local Hint Resolve f_equal2.
+ Local Hint Resolve f_equal2: core.
wlp_simplify.
exploit H; eauto.
+ wlp_simplify.
diff --git a/mppa_k1c/abstractbb/Parallelizability.v b/mppa_k1c/abstractbb/Parallelizability.v
index 22809095..30904b5d 100644
--- a/mppa_k1c/abstractbb/Parallelizability.v
+++ b/mppa_k1c/abstractbb/Parallelizability.v
@@ -332,7 +332,7 @@ Fixpoint bblock_wframe(p:bblock): list R.t :=
| i::p' => (inst_wframe i)++(bblock_wframe p')
end.
-Local Hint Resolve Permutation_app_head Permutation_app_tail Permutation_app_comm.
+Local Hint Resolve Permutation_app_head Permutation_app_tail Permutation_app_comm: core.
Lemma bblock_wframe_Permutation p p':
Permutation p p' -> Permutation (bblock_wframe p) (bblock_wframe p').
@@ -620,7 +620,7 @@ Include ParallelizablityChecking L.
Section PARALLEL2.
Variable ge: genv.
-Local Hint Resolve S.empty_match_frame S.add_match_frame S.union_match_frame S.is_disjoint_match_frame.
+Local Hint Resolve S.empty_match_frame S.add_match_frame S.union_match_frame S.is_disjoint_match_frame: core.
(** Now, refinement of each operation toward parallelizable *)
@@ -659,14 +659,14 @@ Fixpoint inst_sframe (i: inst): S.t :=
| a::i' => S.add (fst a) (S.union (exp_sframe (snd a)) (inst_sframe i'))
end.
-Local Hint Resolve exp_sframe_correct.
+Local Hint Resolve exp_sframe_correct: core.
Lemma inst_sframe_correct i: S.match_frame (inst_sframe i) (inst_frame i).
Proof.
induction i as [|[y e] i']; simpl; auto.
Qed.
-Local Hint Resolve inst_wsframe_correct inst_sframe_correct.
+Local Hint Resolve inst_wsframe_correct inst_sframe_correct: core.
Fixpoint is_pararec (p: bblock) (wsframe: S.t): bool :=
match p with
diff --git a/mppa_k1c/abstractbb/SeqSimuTheory.v b/mppa_k1c/abstractbb/SeqSimuTheory.v
index 649dd083..e234883f 100644
--- a/mppa_k1c/abstractbb/SeqSimuTheory.v
+++ b/mppa_k1c/abstractbb/SeqSimuTheory.v
@@ -102,9 +102,6 @@ Fixpoint bblock_smem_rec (p: bblock) (d: smem): smem :=
let d':=inst_smem i d d in
bblock_smem_rec p' d'
end.
-(*
-Local Hint Resolve smem_eval_empty.
-*)
Definition bblock_smem: bblock -> smem
:= fun p => bblock_smem_rec p smem_empty.
@@ -124,7 +121,7 @@ Proof.
intros d a H; eapply inst_smem_pre_monotonic; eauto.
Qed.
-Local Hint Resolve inst_smem_pre_monotonic bblock_smem_pre_monotonic.
+Local Hint Resolve inst_smem_pre_monotonic bblock_smem_pre_monotonic: core.
Lemma term_eval_exp e (od:smem) m0 old:
(forall x, term_eval ge (od x) m0 = Some (old x)) ->
@@ -185,7 +182,7 @@ Lemma bblocks_smem_rec_Some_correct1 p m0: forall (m1 m2: mem) (d: smem),
(forall x, term_eval ge (d x) m0 = Some (m1 x)) ->
forall x, term_eval ge (bblock_smem_rec p d x) m0 = Some (m2 x).
Proof.
- Local Hint Resolve inst_smem_Some_correct1.
+ Local Hint Resolve inst_smem_Some_correct1: core.
induction p as [ | i p]; simpl; intros m1 m2 d H.
- inversion_clear H; eauto.
- intros H0 x0.
@@ -299,7 +296,7 @@ Lemma block_smem_rec_valid p m0: forall (m1 m2: mem) (d:smem),
(forall x, term_eval ge (d x) m0 = Some (m1 x)) ->
pre (bblock_smem_rec p d) ge m0.
Proof.
- Local Hint Resolve inst_valid.
+ Local Hint Resolve inst_valid: core.
induction p as [ | i p]; simpl; intros m1 d H; auto.
intros H0 H1.
destruct (inst_run ge i m1 m1) eqn: Heqov; eauto.
@@ -326,7 +323,7 @@ Theorem bblock_smem_simu p1 p2:
smem_simu (bblock_smem p1) (bblock_smem p2) ->
bblock_simu ge p1 p2.
Proof.
- Local Hint Resolve bblock_smem_valid bblock_smem_Some_correct1.
+ Local Hint Resolve bblock_smem_valid bblock_smem_Some_correct1: core.
intros (INCL & EQUIV) m DONTFAIL; unfold smem_valid in * |-.
destruct (run ge p1 m) as [m1|] eqn: RUN1; simpl; try congruence.
assert (X: forall x, term_eval ge (bblock_smem p1 x) m = Some (m1 x)); eauto.
diff --git a/mppa_k1c/Asmblockgenproof0.v b/mppa_k1c/lib/Asmblockgenproof0.v
index decc3e2e..58455ada 100644
--- a/mppa_k1c/Asmblockgenproof0.v
+++ b/mppa_k1c/lib/Asmblockgenproof0.v
@@ -22,16 +22,10 @@ Require Import Asmblockgen.
Require Import Conventions1.
Require Import Axioms.
Require Import Machblockgenproof. (* FIXME: only use to import [is_tail_app] and [is_tail_app_inv] *)
+Require Import Asmblockprops.
Module MB:=Machblock.
-Module AB:=Asmvliw.
-
-Hint Extern 2 (_ <> _) => congruence: asmgen.
-
-Definition bblock_simu (ge: Genv.t fundef unit) (f: function) (bb bb': bblock) :=
- forall rs m,
- exec_bblock ge f bb rs m <> Stuck ->
- exec_bblock ge f bb rs m = exec_bblock ge f bb' rs m.
+Module AB:=Asmblock.
Lemma ireg_of_eq:
forall r r', ireg_of r = OK r' -> preg_of r = IR r'.
@@ -51,53 +45,6 @@ Proof.
destruct r1; destruct r2; simpl; intros; reflexivity || discriminate.
Qed.
-Lemma preg_of_data:
- forall r, data_preg (preg_of r) = true.
-Proof.
- intros. destruct r; reflexivity.
-Qed.
-Hint Resolve preg_of_data: asmgen.
-
-Lemma data_diff:
- forall r r',
- data_preg r = true -> data_preg r' = false -> r <> r'.
-Proof.
- congruence.
-Qed.
-Hint Resolve data_diff: asmgen.
-
-Lemma preg_of_not_SP:
- forall r, preg_of r <> SP.
-Proof.
- intros. unfold preg_of; destruct r; simpl; congruence.
-Qed.
-
-Lemma preg_of_not_PC:
- forall r, preg_of r <> PC.
-Proof.
- intros. apply data_diff; auto with asmgen.
-Qed.
-
-Hint Resolve preg_of_not_SP preg_of_not_PC: asmgen.
-
-Lemma nextblock_pc:
- forall b rs, (nextblock b rs)#PC = Val.offset_ptr rs#PC (Ptrofs.repr (size b)).
-Proof.
- intros. apply Pregmap.gss.
-Qed.
-
-Lemma nextblock_inv:
- forall b r rs, r <> PC -> (nextblock b rs)#r = rs#r.
-Proof.
- intros. unfold nextblock. apply Pregmap.gso. red; intro; subst. auto.
-Qed.
-
-Lemma nextblock_inv1:
- forall b r rs, data_preg r = true -> (nextblock b rs)#r = rs#r.
-Proof.
- intros. apply nextblock_inv. red; intro; subst; discriminate.
-Qed.
-
Lemma undef_regs_other:
forall r rl rs,
(forall r', In r' rl -> r <> r') ->
@@ -294,9 +241,9 @@ Qed.
Lemma agree_undef_caller_save_regs:
forall ms sp rs,
agree ms sp rs ->
- agree (Mach.undef_caller_save_regs ms) sp (Asmvliw.undef_caller_save_regs rs).
+ agree (Mach.undef_caller_save_regs ms) sp (undef_caller_save_regs rs).
Proof.
- intros. destruct H. unfold Mach.undef_caller_save_regs, Asmvliw.undef_caller_save_regs; split.
+ intros. destruct H. unfold Mach.undef_caller_save_regs, undef_caller_save_regs; split.
- unfold proj_sumbool; rewrite dec_eq_true. auto.
- auto.
- intros. unfold proj_sumbool. rewrite dec_eq_false by (apply preg_of_not_SP).
@@ -467,7 +414,7 @@ Proof.
Qed.
-Local Hint Resolve code_tail_0 code_tail_S.
+Local Hint Resolve code_tail_0 code_tail_S: core.
Lemma code_tail_next:
forall fn ofs c0,
@@ -511,7 +458,7 @@ Proof.
omega.
Qed.
-Local Hint Resolve code_tail_next.
+Local Hint Resolve code_tail_next: core.
Lemma code_tail_next_int:
forall fn ofs bi c,
@@ -752,6 +699,19 @@ Proof.
intros. destruct H. auto.
Qed.
+Lemma exec_body_pc:
+ forall ge l rs1 m1 rs2 m2,
+ exec_body ge l rs1 m1 = Next rs2 m2 ->
+ rs2 PC = rs1 PC.
+Proof.
+ induction l.
+ - intros. inv H. auto.
+ - intros until m2. intro EXEB.
+ inv EXEB. destruct (exec_basic_instr _ _ _ _) eqn:EBI; try discriminate.
+ eapply IHl in H0. rewrite H0.
+ erewrite exec_basic_instr_pc; eauto.
+Qed.
+
Section STRAIGHTLINE.
Variable ge: genv.
@@ -880,67 +840,6 @@ Qed.
(** Linking exec_straight with exec_straight_blocks *)
-Ltac Simplif :=
- ((rewrite nextblock_inv by eauto with asmgen)
- || (rewrite nextblock_inv1 by eauto with asmgen)
- || (rewrite Pregmap.gss)
- || (rewrite nextblock_pc)
- || (rewrite Pregmap.gso by eauto with asmgen)
- ); auto with asmgen.
-
-Ltac Simpl := repeat Simplif.
-
-Lemma exec_basic_instr_pc:
- forall b rs1 m1 rs2 m2,
- exec_basic_instr ge b rs1 m1 = Next rs2 m2 ->
- rs2 PC = rs1 PC.
-Proof.
- intros. destruct b; try destruct i; try destruct i.
- all: try (inv H; Simpl).
- 1-10: try (unfold parexec_load_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.loadv _ _ _); [inv H1; Simpl | discriminate]).
- 1-10: try (unfold parexec_load_reg in H1; destruct (Mem.loadv _ _ _); [inv H1; Simpl | discriminate]).
- 1-10: try (unfold parexec_load_regxs in H1; destruct (Mem.loadv _ _ _); [inv H1; Simpl | discriminate]).
- 1-10: try (unfold parexec_store_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.storev _ _ _); [inv H1; auto | discriminate]).
- 1-10: try (unfold parexec_store_reg in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]); auto.
- 1-10: try (unfold parexec_store_regxs in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]); auto.
- - (* PLoadQRRO *)
- unfold parexec_load_q_offset in H1.
- destruct (gpreg_q_expand _) as [r0 r1] in H1.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- inv H1. Simpl.
- - (* PLoadORRO *)
- unfold parexec_load_o_offset in H1.
- destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- destruct (Mem.loadv _ _ _) in H1; try discriminate.
- inv H1. Simpl.
- - (* PStoreQRRO *)
- unfold parexec_store_q_offset in H1.
- destruct (gpreg_q_expand _) as [r0 r1] in H1.
- unfold eval_offset in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- inv H1. Simpl. reflexivity.
- - (* PStoreORRO *)
- unfold parexec_store_o_offset in H1.
- destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
- unfold eval_offset in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- destruct (Mem.storev _ _ _) in H1; try discriminate.
- inv H1. Simpl. reflexivity.
- - destruct (Mem.alloc _ _ _). destruct (Mem.store _ _ _ _ _). inv H1. Simpl. discriminate.
- - destruct (Mem.loadv _ _ _); try discriminate. destruct (rs1 _); try discriminate.
- destruct (Mem.free _ _ _ _). inv H1. Simpl. discriminate.
- - destruct rs; try discriminate. inv H1. Simpl.
- - destruct rd; try discriminate. inv H1; Simpl.
- - reflexivity.
-Qed.
-
Lemma exec_straight_pc:
forall c c' rs1 m1 rs2 m2,
exec_straight c rs1 m1 c' rs2 m2 ->
diff --git a/mppa_k1c/lib/ForwardSimulationBlock.v b/mppa_k1c/lib/ForwardSimulationBlock.v
index 39dd2234..224eda0a 100644
--- a/mppa_k1c/lib/ForwardSimulationBlock.v
+++ b/mppa_k1c/lib/ForwardSimulationBlock.v
@@ -21,7 +21,7 @@ Section starN_lemma.
Variable L: semantics.
-Local Hint Resolve starN_refl starN_step Eapp_assoc.
+Local Hint Resolve starN_refl starN_step Eapp_assoc: core.
Lemma starN_split n s t s':
starN (step L) (globalenv L) n s t s' ->
@@ -93,7 +93,7 @@ Hypothesis simu_end_block:
(** Introduction d'une sémantique par bloc sur L1 appelée "memoL1" *)
-Local Hint Resolve starN_refl starN_step.
+Local Hint Resolve starN_refl starN_step: core.
Definition follows_in_block (head current: state L1): Prop :=
dist_end_block head >= dist_end_block current
@@ -164,7 +164,7 @@ Inductive is_well_memorized (s s': memostate): Prop :=
memorized s' = None ->
is_well_memorized s s'.
-Local Hint Resolve StartBloc MidBloc ExitBloc.
+Local Hint Resolve StartBloc MidBloc ExitBloc: core.
Definition memoL1 := {|
state := memostate;
diff --git a/mppa_k1c/lib/Machblock.v b/mppa_k1c/lib/Machblock.v
index 2759c49d..5a7f1782 100644
--- a/mppa_k1c/lib/Machblock.v
+++ b/mppa_k1c/lib/Machblock.v
@@ -20,7 +20,7 @@ Inductive basic_inst: Type :=
| MBsetstack: mreg -> ptrofs -> typ -> basic_inst
| MBgetparam: ptrofs -> typ -> mreg -> basic_inst
| MBop: operation -> list mreg -> mreg -> basic_inst
- | MBload: memory_chunk -> addressing -> list mreg -> mreg -> basic_inst
+ | MBload: trapping_mode -> memory_chunk -> addressing -> list mreg -> mreg -> basic_inst
| MBstore: memory_chunk -> addressing -> list mreg -> mreg -> basic_inst
.
@@ -207,11 +207,22 @@ Inductive basic_step (s: list stackframe) (fb: block) (sp: val) (rs: regset) (m:
rs' = ((undef_regs (destroyed_by_op op) rs)#res <- v) ->
basic_step s fb sp rs m (MBop op args res) rs' m
| exec_MBload:
- forall addr args a v rs' chunk dst,
+ forall addr args a v rs' trap chunk dst,
eval_addressing ge sp addr rs##args = Some a ->
Mem.loadv chunk m a = Some v ->
rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- v) ->
- basic_step s fb sp rs m (MBload chunk addr args dst) rs' m
+ basic_step s fb sp rs m (MBload trap chunk addr args dst) rs' m
+ | exec_MBload_notrap1:
+ forall addr args rs' chunk dst,
+ eval_addressing ge sp addr rs##args = None ->
+ rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- (default_notrap_load_value chunk)) ->
+ basic_step s fb sp rs m (MBload NOTRAP chunk addr args dst) rs' m
+ | exec_MBload_notrap2:
+ forall addr args a rs' chunk dst,
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs' = ((undef_regs (destroyed_by_load chunk addr) rs)#dst <- (default_notrap_load_value chunk)) ->
+ basic_step s fb sp rs m (MBload NOTRAP chunk addr args dst) rs' m
| exec_MBstore:
forall chunk addr args src m' a rs',
eval_addressing ge sp addr rs##args = Some a ->
diff --git a/mppa_k1c/lib/Machblockgen.v b/mppa_k1c/lib/Machblockgen.v
index db48934e..2ba42814 100644
--- a/mppa_k1c/lib/Machblockgen.v
+++ b/mppa_k1c/lib/Machblockgen.v
@@ -33,7 +33,7 @@ Definition trans_inst (i:Mach.instruction) : Machblock_inst :=
| Msetstack src ofs ty => MB_basic (MBsetstack src ofs ty)
| Mgetparam ofs ty dst => MB_basic (MBgetparam ofs ty dst)
| Mop op args res => MB_basic (MBop op args res)
- | Mload chunk addr args dst => MB_basic (MBload chunk addr args dst)
+ | Mload trap chunk addr args dst=> MB_basic (MBload trap chunk addr args dst)
| Mstore chunk addr args src => MB_basic (MBstore chunk addr args src)
| Mlabel l => MB_label l
end.
@@ -105,7 +105,7 @@ Inductive is_end_block: Machblock_inst -> code -> Prop :=
| End_basic bi bh bl: header bh <> nil -> is_end_block (MB_basic bi) (bh::bl)
| End_cfi cfi bl: bl <> nil -> is_end_block (MB_cfi cfi) bl.
-Local Hint Resolve End_empty End_basic End_cfi.
+Local Hint Resolve End_empty End_basic End_cfi: core.
Inductive is_trans_code: Mach.code -> code -> Prop :=
| Tr_nil: is_trans_code nil nil
@@ -123,7 +123,7 @@ Inductive is_trans_code: Mach.code -> code -> Prop :=
header bh = nil ->
is_trans_code (i::c) (add_basic bi bh::bl).
-Local Hint Resolve Tr_nil Tr_end_block.
+Local Hint Resolve Tr_nil Tr_end_block: core.
Lemma add_to_code_is_trans_code i c bl:
is_trans_code c bl ->
@@ -145,7 +145,7 @@ Proof.
rewrite <- Heqti. eapply End_cfi. congruence.
Qed.
-Local Hint Resolve add_to_code_is_trans_code.
+Local Hint Resolve add_to_code_is_trans_code: core.
Lemma trans_code_is_trans_code_rev c1: forall c2 mbi,
is_trans_code c2 mbi ->
@@ -185,7 +185,7 @@ Proof.
exists mbi1. split; congruence.
Qed.
-Local Hint Resolve trans_code_is_trans_code.
+Local Hint Resolve trans_code_is_trans_code: core.
Theorem is_trans_code_inv c bl: is_trans_code c bl <-> bl=(trans_code c).
Proof.
diff --git a/mppa_k1c/lib/Machblockgenproof.v b/mppa_k1c/lib/Machblockgenproof.v
index 8da610ad..0de2df52 100644
--- a/mppa_k1c/lib/Machblockgenproof.v
+++ b/mppa_k1c/lib/Machblockgenproof.v
@@ -72,7 +72,7 @@ Proof.
apply match_states_trans_state.
Qed.
-Local Hint Resolve match_states_trans_state.
+Local Hint Resolve match_states_trans_state: core.
Lemma symbols_preserved:
forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
@@ -284,7 +284,7 @@ Proof.
Qed.
Local Hint Resolve symbols_preserved senv_preserved init_mem_preserved prog_main_preserved functions_translated
- parent_sp_preserved.
+ parent_sp_preserved: core.
Definition dist_end_block_code (c: Mach.code) :=
@@ -299,8 +299,8 @@ Definition dist_end_block (s: Mach.state): nat :=
| _ => 0
end.
-Local Hint Resolve exec_nil_body exec_cons_body.
-Local Hint Resolve exec_MBgetstack exec_MBsetstack exec_MBgetparam exec_MBop exec_MBload exec_MBstore.
+Local Hint Resolve exec_nil_body exec_cons_body: core.
+Local Hint Resolve exec_MBgetstack exec_MBsetstack exec_MBgetparam exec_MBop exec_MBload exec_MBstore: core.
Lemma size_add_label l bh: size (add_label l bh) = size bh + 1.
Proof.
@@ -336,7 +336,7 @@ Proof.
omega.
Qed.
-Local Hint Resolve dist_end_block_code_simu_mid_block.
+Local Hint Resolve dist_end_block_code_simu_mid_block: core.
Lemma size_nonzero c b bl:
@@ -392,8 +392,8 @@ destruct i; congruence.
Qed.
-Local Hint Resolve Mlabel_is_not_cfi.
-Local Hint Resolve MBbasic_is_not_cfi.
+Local Hint Resolve Mlabel_is_not_cfi: core.
+Local Hint Resolve MBbasic_is_not_cfi: core.
Lemma add_to_new_block_is_label i:
header (add_to_new_bblock (trans_inst i)) <> nil -> exists l, i = Mlabel l.
@@ -408,7 +408,7 @@ Proof.
+ unfold cfi_bblock in H; simpl in H; congruence.
Qed.
-Local Hint Resolve Mlabel_is_not_basic.
+Local Hint Resolve Mlabel_is_not_basic: core.
Lemma trans_code_decompose c: forall b bl,
is_trans_code c (b::bl) ->
@@ -483,6 +483,10 @@ Proof.
unfold Genv.symbol_address; rewrite symbols_preserved; auto.
- eapply exec_MBload; eauto; rewrite <- H; destruct a; simpl; auto; destruct (rs ## l); simpl; auto;
unfold Genv.symbol_address; rewrite symbols_preserved; auto.
+ - eapply exec_MBload_notrap1; eauto; rewrite <- H; destruct a; simpl; auto; destruct (rs ## l); simpl; auto;
+ unfold Genv.symbol_address; rewrite symbols_preserved; auto.
+ - eapply exec_MBload_notrap2; eauto; rewrite <- H; destruct a; simpl; auto; destruct (rs ## l); simpl; auto;
+ unfold Genv.symbol_address; rewrite symbols_preserved; auto.
- eapply exec_MBstore; eauto; rewrite <- H; destruct a; simpl; auto; destruct (rs ## l); simpl; auto;
unfold Genv.symbol_address; rewrite symbols_preserved; auto.
Qed.
@@ -506,8 +510,8 @@ Proof.
rewrite Hs2, Hb2; eauto.
Qed.
-Local Hint Resolve exec_MBcall exec_MBtailcall exec_MBbuiltin exec_MBgoto exec_MBcond_true exec_MBcond_false exec_MBjumptable exec_MBreturn exec_Some_exit exec_None_exit.
-Local Hint Resolve eval_builtin_args_preserved external_call_symbols_preserved find_funct_ptr_same.
+Local Hint Resolve exec_MBcall exec_MBtailcall exec_MBbuiltin exec_MBgoto exec_MBcond_true exec_MBcond_false exec_MBjumptable exec_MBreturn exec_Some_exit exec_None_exit: core.
+Local Hint Resolve eval_builtin_args_preserved external_call_symbols_preserved find_funct_ptr_same: core.
Lemma match_states_concat_trans_code st f sp c rs m h:
diff --git a/powerpc/Archi.v b/powerpc/Archi.v
index ab348c14..10f38391 100644
--- a/powerpc/Archi.v
+++ b/powerpc/Archi.v
@@ -30,6 +30,10 @@ Definition align_float64 := 8%Z.
(** Can we use the 64-bit extensions to the PowerPC architecture? *)
Parameter ppc64 : bool.
+(** Should single-precision FP arguments passed on stack be passed
+ as singles or use double FP format. *)
+Parameter single_passed_as_single : bool.
+
Definition splitlong := negb ppc64.
Lemma splitlong_ptr32: splitlong = true -> ptr64 = false.
diff --git a/powerpc/Asm.v b/powerpc/Asm.v
index b9300fd7..4fb38ff8 100644
--- a/powerpc/Asm.v
+++ b/powerpc/Asm.v
@@ -864,7 +864,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Pisel rd r1 r2 bit =>
let v :=
match rs#(reg_of_crbit bit) with
- | Vint n => if Int.eq n Int.zero then rs#r2 else rs#r1
+ | Vint n => if Int.eq n Int.zero then rs#r2 else (gpr_or_zero rs r1)
| _ => Vundef
end in
Next (nextinstr (rs #rd <- v #GPR0 <- Vundef)) m
diff --git a/powerpc/Asmexpand.ml b/powerpc/Asmexpand.ml
index 704b0aba..ce88778c 100644
--- a/powerpc/Asmexpand.ml
+++ b/powerpc/Asmexpand.ml
@@ -852,7 +852,7 @@ let expand_instruction instr =
if variadic then begin
emit (Pmflr GPR0);
emit (Pbl(intern_string "__compcert_va_saveregs",
- {sig_args = []; sig_res = None; sig_cc = cc_default}));
+ {sig_args = []; sig_res = Tvoid; sig_cc = cc_default}));
emit (Pmtlr GPR0)
end;
current_function_stacksize := sz;
diff --git a/powerpc/Asmgen.v b/powerpc/Asmgen.v
index a686414a..29e2c028 100644
--- a/powerpc/Asmgen.v
+++ b/powerpc/Asmgen.v
@@ -783,8 +783,13 @@ Definition transl_memory_access
Error(msg "Asmgen.transl_memory_access")
end.
-Definition transl_load (chunk: memory_chunk) (addr: addressing)
- (args: list mreg) (dst: mreg) (k: code) :=
+Definition transl_load
+ (trap : trapping_mode)
+ (chunk: memory_chunk) (addr: addressing)
+ (args: list mreg) (dst: mreg) (k: code) :=
+ match trap with
+ | NOTRAP => Error (msg "Asmgen.transl_load non-trapping loads unsupported on PPC")
+ | TRAP =>
match chunk with
| Mint8signed =>
do r <- ireg_of dst;
@@ -812,6 +817,7 @@ Definition transl_load (chunk: memory_chunk) (addr: addressing)
transl_memory_access (Plfd r) (Plfdx r) addr args GPR12 k
| _ =>
Error (msg "Asmgen.transl_load")
+ end
end.
Definition transl_store (chunk: memory_chunk) (addr: addressing)
@@ -869,8 +875,8 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
loadind GPR1 f.(fn_link_ofs) Tint R11 k1)
| Mop op args res =>
transl_op op args res k
- | Mload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | Mload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| Mstore chunk addr args src =>
transl_store chunk addr args src k
| Mcall sig (inl r) =>
diff --git a/powerpc/Asmgenproof.v b/powerpc/Asmgenproof.v
index d653633c..21d5ce48 100644
--- a/powerpc/Asmgenproof.v
+++ b/powerpc/Asmgenproof.v
@@ -328,6 +328,7 @@ Proof.
eapply loadind_label; eauto.
eapply tail_nolabel_trans; eapply loadind_label; eauto.
eapply transl_op_label; eauto.
+ destruct t; try discriminate.
destruct m; monadInv H; (eapply tail_nolabel_trans; [eapply transl_memory_access_label; TailNoLabel|TailNoLabel]).
destruct m; monadInv H; eapply transl_memory_access_label; TailNoLabel.
destruct s0; monadInv H; TailNoLabel.
@@ -657,6 +658,13 @@ Opaque loadind.
split. simpl; congruence.
apply R; auto with asmgen.
+
+- (* Mload notrap *) (* isn't there a nicer way? *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
- (* Mstore *)
assert (eval_addressing tge sp addr rs##args = Some a).
rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
diff --git a/powerpc/Asmgenproof1.v b/powerpc/Asmgenproof1.v
index 884d5366..1b797999 100644
--- a/powerpc/Asmgenproof1.v
+++ b/powerpc/Asmgenproof1.v
@@ -1284,7 +1284,9 @@ Proof.
reflexivity.
+ Simpl.
rewrite <- (C r1), <- (C r2) by auto.
- rewrite B. destruct dir; destruct ob as [[]|]; simpl; auto using Val.lessdef_normalize.
+ rewrite B, gpr_or_zero_not_zero.
+ destruct dir; destruct ob as [[]|]; simpl; auto using Val.lessdef_normalize.
+ destruct dir; intros e; subst; discriminate.
+ intros. Simpl.
Qed.
@@ -1677,8 +1679,8 @@ Qed.
(** Translation of loads *)
Lemma transl_load_correct:
- forall chunk addr args dst k c (rs: regset) m a v,
- transl_load chunk addr args dst k = OK c ->
+ forall trap chunk addr args dst k c (rs: regset) m a v,
+ transl_load trap chunk addr args dst k = OK c ->
eval_addressing ge (rs#GPR1) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
@@ -1687,6 +1689,7 @@ Lemma transl_load_correct:
/\ forall r, r <> PC -> r <> GPR12 -> r <> GPR0 -> r <> preg_of dst -> rs' r = rs r.
Proof.
intros.
+ destruct trap; try discriminate.
assert (LD: forall v, Val.lessdef a v -> v = a).
{ intros. inv H2; auto. discriminate H1. }
assert (BASE: forall mk1 mk2 k' chunk' v',
diff --git a/powerpc/Builtins1.v b/powerpc/Builtins1.v
index f6e643d2..53c83d7e 100644
--- a/powerpc/Builtins1.v
+++ b/powerpc/Builtins1.v
@@ -29,5 +29,5 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with end.
diff --git a/powerpc/CSE2deps.v b/powerpc/CSE2deps.v
new file mode 100644
index 00000000..9db51bbb
--- /dev/null
+++ b/powerpc/CSE2deps.v
@@ -0,0 +1,20 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs (Int.unsigned ofs') chunk' (Int.unsigned ofs) chunk)
+ else true | _, _, _, _ => true
+ end.
diff --git a/powerpc/CSE2depsproof.v b/powerpc/CSE2depsproof.v
new file mode 100644
index 00000000..fdded9b6
--- /dev/null
+++ b/powerpc/CSE2depsproof.v
@@ -0,0 +1,135 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Lemma ptrofs_size :
+ Ptrofs.wordsize = if Archi.ptr64 then 64%nat else 32%nat.
+Proof.
+ unfold Ptrofs.wordsize.
+ unfold Wordsize_Ptrofs.wordsize.
+ trivial.
+Qed.
+
+Lemma ptrofs_modulus :
+ Ptrofs.modulus = if Archi.ptr64 then 18446744073709551616 else 4294967296.
+Proof.
+ unfold Ptrofs.modulus.
+ rewrite ptrofs_size.
+ destruct Archi.ptr64; reflexivity.
+Qed.
+
+Lemma ptrofs_max_unsigned :
+ Ptrofs.max_unsigned = if Archi.ptr64 then 18446744073709551615 else 4294967295.
+Proof.
+ unfold Ptrofs.max_unsigned.
+ rewrite ptrofs_modulus.
+ destruct Archi.ptr64; reflexivity.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : int.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= Int.unsigned ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= Int.unsigned ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : Int.unsigned ofsw + size_chunk chunkw <= Int.unsigned ofsr
+ \/ Int.unsigned ofsr + size_chunk chunkr <= Int.unsigned ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in *.
+
+ rewrite ptrofs_modulus in *.
+ simpl in *.
+ inv ADDRR.
+ inv ADDRW.
+ destruct base; try discriminate.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.of_int ofsr)) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i (Ptrofs.of_int ofsw)) as [OFSW | OFSW];
+ rewrite OFSW).
+ all: unfold Ptrofs.of_int.
+
+ all: repeat rewrite Ptrofs.unsigned_repr by (unfold Ptrofs.max_unsigned; rewrite ptrofs_modulus; destruct Archi.ptr64; lia).
+ all: repeat rewrite ptrofs_modulus.
+ all: destruct Archi.ptr64; intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs (Int.unsigned ofsr) chunkr (Int.unsigned ofsw) chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs (Int.unsigned i0) chunk' (Int.unsigned i) chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away with (F:=F) (V:=V) (genv:=genv) (sp:=sp); eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/powerpc/Conventions1.v b/powerpc/Conventions1.v
index 1de55c1a..5c9cbd4f 100644
--- a/powerpc/Conventions1.v
+++ b/powerpc/Conventions1.v
@@ -117,18 +117,16 @@ Definition dummy_float_reg := F0. (**r Used in [Coloring]. *)
We treat a function without result as a function with one integer result. *)
Definition loc_result_32 (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R3
- | Some (Tint | Tany32) => One R3
- | Some (Tfloat | Tsingle | Tany64) => One F1
- | Some Tlong => Twolong R3 R4
+ match proj_sig_res s with
+ | Tint | Tany32 => One R3
+ | Tfloat | Tsingle | Tany64 => One F1
+ | Tlong => Twolong R3 R4
end.
Definition loc_result_64 (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R3
- | Some (Tint | Tlong | Tany32 | Tany64) => One R3
- | Some (Tfloat | Tsingle) => One F1
+ match proj_sig_res s with
+ | Tint | Tlong | Tany32 | Tany64 => One R3
+ | Tfloat | Tsingle => One F1
end.
Definition loc_result :=
@@ -140,8 +138,8 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result, loc_result_32, loc_result_64, mreg_type.
- destruct Archi.ptr64 eqn:?; destruct (sig_res sig) as [[]|]; destruct Archi.ppc64; simpl; auto.
+ intros. unfold loc_result, loc_result_32, loc_result_64, mreg_type.
+ destruct Archi.ptr64 eqn:?; destruct (proj_sig_res sig); destruct Archi.ppc64; simpl; auto.
Qed.
(** The result locations are caller-save registers *)
@@ -151,7 +149,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros. unfold loc_result, loc_result_32, loc_result_64, is_callee_save;
- destruct Archi.ptr64; destruct (sig_res s) as [[]|]; simpl; auto.
+ destruct Archi.ptr64; destruct (proj_sig_res s); simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -161,13 +159,13 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
intros; unfold loc_result, loc_result_32, loc_result_64, mreg_type;
- destruct Archi.ptr64; destruct (sig_res sg) as [[]|]; destruct Archi.ppc64; simpl; auto.
+ destruct Archi.ptr64; destruct (proj_sig_res sg); destruct Archi.ppc64; simpl; auto.
split; auto. congruence.
split; auto. congruence.
Qed.
@@ -177,7 +175,7 @@ Qed.
Lemma loc_result_exten:
forall s1 s2, s1.(sig_res) = s2.(sig_res) -> loc_result s1 = loc_result s2.
Proof.
- intros. unfold loc_result, loc_result_32, loc_result_64.
+ intros. unfold loc_result, loc_result_32, loc_result_64, proj_sig_res.
destruct Archi.ptr64; rewrite H; auto.
Qed.
@@ -210,7 +208,16 @@ Fixpoint loc_arguments_rec
| Some ireg =>
One (R ireg) :: loc_arguments_rec tys (ir + 1) fr ofs
end
- | (Tfloat | Tsingle | Tany64) as ty :: tys =>
+ | Tsingle as ty :: tys =>
+ match list_nth_z float_param_regs fr with
+ | None =>
+ let ty := if Archi.single_passed_as_single then Tsingle else Tany64 in
+ let ofs := align ofs (typesize ty) in
+ One (S Outgoing ofs ty) :: loc_arguments_rec tys ir fr (ofs + (typesize ty))
+ | Some freg =>
+ One (R freg) :: loc_arguments_rec tys ir (fr + 1) ofs
+ end
+ | (Tfloat | Tany64) as ty :: tys =>
match list_nth_z float_param_regs fr with
| None =>
let ofs := align ofs 2 in
@@ -238,33 +245,6 @@ Fixpoint loc_arguments_rec
Definition loc_arguments (s: signature) : list (rpair loc) :=
loc_arguments_rec s.(sig_args) 0 0 0.
-(** [size_arguments s] returns the number of [Outgoing] slots used
- to call a function with signature [s]. *)
-
-Fixpoint size_arguments_rec (tyl: list typ) (ir fr ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => ofs
- | (Tint | Tany32) :: tys =>
- match list_nth_z int_param_regs ir with
- | None => size_arguments_rec tys ir fr (ofs + 1)
- | Some ireg => size_arguments_rec tys (ir + 1) fr ofs
- end
- | (Tfloat | Tsingle | Tany64) :: tys =>
- match list_nth_z float_param_regs fr with
- | None => size_arguments_rec tys ir fr (align ofs 2 + 2)
- | Some freg => size_arguments_rec tys ir (fr + 1) ofs
- end
- | Tlong :: tys =>
- let ir := align ir 2 in
- match list_nth_z int_param_regs ir, list_nth_z int_param_regs (ir + 1) with
- | Some r1, Some r2 => size_arguments_rec tys (ir + 2) fr ofs
- | _, _ => size_arguments_rec tys ir fr (align ofs 2 + 2)
- end
- end.
-
-Definition size_arguments (s: signature) : Z :=
- size_arguments_rec s.(sig_args) 0 0 0.
-
(** Argument locations are either caller-save registers or [Outgoing]
stack slots at nonnegative offsets. *)
@@ -324,12 +304,14 @@ Opaque list_nth_z.
apply align_divides; omega. apply Z.divide_1_l. apply Z.divide_1_l.
eapply Y; eauto. omega.
- (* single *)
+ assert (ofs <= align ofs 1) by (apply align_le; omega).
assert (ofs <= align ofs 2) by (apply align_le; omega).
destruct (list_nth_z float_param_regs fr) as [r|] eqn:E; destruct H.
subst. right. eapply list_nth_z_in; eauto.
eapply IHtyl; eauto.
- subst. split. omega. apply Z.divide_1_l.
- eapply Y; eauto. omega.
+ subst. split. destruct Archi.single_passed_as_single; simpl; omega.
+ destruct Archi.single_passed_as_single; simpl; apply Z.divide_1_l.
+ eapply Y; eauto. destruct Archi.single_passed_as_single; simpl; omega.
- (* any32 *)
destruct (list_nth_z int_param_regs ir) as [r|] eqn:E; destruct H.
subst. left. eapply list_nth_z_in; eauto.
@@ -361,107 +343,14 @@ Qed.
Hint Resolve loc_arguments_acceptable: locs.
-(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
-
-Remark size_arguments_rec_above:
- forall tyl ir fr ofs0,
- ofs0 <= size_arguments_rec tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- omega.
- destruct a.
- destruct (list_nth_z int_param_regs ir); eauto. apply Z.le_trans with (ofs0 + 1); auto; omega.
- destruct (list_nth_z float_param_regs fr); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- set (ir' := align ir 2).
- destruct (list_nth_z int_param_regs ir'); eauto.
- destruct (list_nth_z int_param_regs (ir' + 1)); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- destruct (list_nth_z float_param_regs fr); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
- destruct (list_nth_z int_param_regs ir); eauto. apply Z.le_trans with (ofs0 + 1); auto; omega.
- destruct (list_nth_z float_param_regs fr); eauto.
- apply Z.le_trans with (align ofs0 2). apply align_le; omega.
- apply Z.le_trans with (align ofs0 2 + 2); auto; omega.
-Qed.
-
-Lemma size_arguments_above:
- forall s, size_arguments s >= 0.
-Proof.
- intros; unfold size_arguments. apply Z.le_ge.
- apply size_arguments_rec_above.
-Qed.
-
-Lemma loc_arguments_bounded:
- forall (s: signature) (ofs: Z) (ty: typ),
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
- ofs + typesize ty <= size_arguments s.
-Proof.
- intros.
- assert (forall tyl ir fr ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_rec tyl ir fr ofs0)) ->
- ofs + typesize ty <= size_arguments_rec tyl ir fr ofs0).
-{
- induction tyl; simpl; intros.
- elim H0.
- destruct a.
-- (* int *)
- destruct (list_nth_z int_param_regs ir); destruct H0.
- congruence.
- eauto.
- inv H0. apply size_arguments_rec_above.
- eauto.
-- (* float *)
- destruct (list_nth_z float_param_regs fr); destruct H0.
- congruence.
- eauto.
- inv H0. apply size_arguments_rec_above. eauto.
-- (* long *)
- set (ir' := align ir 2) in *.
- assert (DFL:
- In (S Outgoing ofs ty) (regs_of_rpairs
- ((if Archi.ptr64
- then One (S Outgoing (align ofs0 2) Tlong)
- else Twolong (S Outgoing (align ofs0 2) Tint)
- (S Outgoing (align ofs0 2 + 1) Tint))
- :: loc_arguments_rec tyl ir' fr (align ofs0 2 + 2))) ->
- ofs + typesize ty <= size_arguments_rec tyl ir' fr (align ofs0 2 + 2)).
- { destruct Archi.ptr64; intros IN.
- - destruct IN. inv H1. apply size_arguments_rec_above. auto.
- - destruct IN. inv H1. transitivity (align ofs0 2 + 2). simpl; omega. apply size_arguments_rec_above.
- destruct H1. inv H1. transitivity (align ofs0 2 + 2). simpl; omega. apply size_arguments_rec_above.
- auto. }
- destruct (list_nth_z int_param_regs ir'); auto.
- destruct (list_nth_z int_param_regs (ir' + 1)); auto.
- destruct H0. congruence. destruct H0. congruence. eauto.
-- (* single *)
- destruct (list_nth_z float_param_regs fr); destruct H0.
- congruence.
- eauto.
- inv H0. transitivity (align ofs0 2 + 2). simpl; omega. apply size_arguments_rec_above.
- eauto.
-- (* any32 *)
- destruct (list_nth_z int_param_regs ir); destruct H0.
- congruence.
- eauto.
- inv H0. apply size_arguments_rec_above.
- eauto.
-- (* any64 *)
- destruct (list_nth_z float_param_regs fr); destruct H0.
- congruence.
- eauto.
- inv H0. apply size_arguments_rec_above. eauto.
- }
- eauto.
-Qed.
-
Lemma loc_arguments_main:
loc_arguments signature_main = nil.
Proof.
reflexivity.
Qed.
+
+(** ** Normalization of function results *)
+
+(** No normalization needed. *)
+
+Definition return_value_needs_normalization (t: rettype) := false.
diff --git a/powerpc/DuplicateOpcodeHeuristic.ml b/powerpc/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..33be79e8
--- /dev/null
+++ b/powerpc/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,27 @@
+(* open Camlcoq *)
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccomplimm (c, n) | Ccompluimm (c, n) -> if n == Integers.Int64.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
diff --git a/powerpc/Op.v b/powerpc/Op.v
index 0f082c1f..b73cb14b 100644
--- a/powerpc/Op.v
+++ b/powerpc/Op.v
@@ -581,6 +581,30 @@ Proof with (try exact I; try reflexivity).
unfold Val.select. destruct (eval_condition c vl m). apply Val.normalize_type. exact I.
Qed.
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivl | Odivu | Odivlu
+ | Oshrximm _ | Oshrxlimm _
+ | Ointoffloat | Ointuoffloat
+ | Ofloatofint | Ofloatofintu
+ | Olongoffloat
+ | Ofloatoflong => true
+ | _ => false
+ end.
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -1032,6 +1056,21 @@ Proof.
apply Val.add_inject; auto. apply H; simpl; auto.
Qed.
+
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *;
+ inv Hinjvl; trivial; try discriminate; inv H0; trivial; try discriminate; inv H2; trivial; try discriminate.
+Qed.
End EVAL_COMPAT.
(** Compatibility of the evaluation functions with the ``is less defined'' relation over values. *)
@@ -1098,6 +1137,20 @@ Proof.
rewrite <- val_inject_list_lessdef. eauto. auto.
Qed.
+
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros until vl2. intros Hlessdef Heval1.
+ destruct addr; simpl in *;
+ inv Hlessdef; trivial; try discriminate;
+ inv H0; trivial; try discriminate;
+ inv H2; trivial; try discriminate.
+Qed.
+
Lemma eval_operation_lessdef:
forall sp op vl1 vl2 v1 m1 m2,
Val.lessdef_list vl1 vl2 ->
@@ -1189,6 +1242,19 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/powerpc/extractionMachdep.v b/powerpc/extractionMachdep.v
index 7482435f..a3e945bf 100644
--- a/powerpc/extractionMachdep.v
+++ b/powerpc/extractionMachdep.v
@@ -34,3 +34,6 @@ Extract Constant Archi.ppc64 =>
| ""e5500"" -> true
| _ -> false
end".
+
+(* Choice of passing of single *)
+Extract Constant Archi.single_passed_as_single => "Configuration.gnu_toolchain".
diff --git a/riscV/Asmexpand.ml b/riscV/Asmexpand.ml
index 3e734747..7e36abf8 100644
--- a/riscV/Asmexpand.ml
+++ b/riscV/Asmexpand.ml
@@ -23,7 +23,7 @@ open Asm
open Asmexpandaux
open AST
open Camlcoq
-open !Integers
+open! Integers
exception Error of string
@@ -63,44 +63,44 @@ let expand_storeind_ptr src base ofs =
let int_param_regs = [| X10; X11; X12; X13; X14; X15; X16; X17 |]
let float_param_regs = [| F10; F11; F12; F13; F14; F15; F16; F17 |]
-let rec fixup_variadic_call pos tyl =
- if pos < 8 then
+let rec fixup_variadic_call ri rf tyl =
+ if ri < 8 then
match tyl with
| [] ->
()
| (Tint | Tany32) :: tyl ->
- fixup_variadic_call (pos + 1) tyl
+ fixup_variadic_call (ri + 1) rf tyl
| Tsingle :: tyl ->
- let rs =float_param_regs.(pos)
- and rd = int_param_regs.(pos) in
+ let rs = float_param_regs.(rf)
+ and rd = int_param_regs.(ri) in
emit (Pfmvxs(rd, rs));
- fixup_variadic_call (pos + 1) tyl
+ fixup_variadic_call (ri + 1) (rf + 1) tyl
| Tlong :: tyl ->
- let pos' = if Archi.ptr64 then pos + 1 else align pos 2 + 2 in
- fixup_variadic_call pos' tyl
+ let ri' = if Archi.ptr64 then ri + 1 else align ri 2 + 2 in
+ fixup_variadic_call ri' rf tyl
| (Tfloat | Tany64) :: tyl ->
if Archi.ptr64 then begin
- let rs = float_param_regs.(pos)
- and rd = int_param_regs.(pos) in
+ let rs = float_param_regs.(rf)
+ and rd = int_param_regs.(ri) in
emit (Pfmvxd(rd, rs));
- fixup_variadic_call (pos + 1) tyl
+ fixup_variadic_call (ri + 1) (rf + 1) tyl
end else begin
- let pos = align pos 2 in
- if pos < 8 then begin
- let rs = float_param_regs.(pos)
- and rd1 = int_param_regs.(pos)
- and rd2 = int_param_regs.(pos + 1) in
+ let ri = align ri 2 in
+ if ri < 8 then begin
+ let rs = float_param_regs.(rf)
+ and rd1 = int_param_regs.(ri)
+ and rd2 = int_param_regs.(ri + 1) in
emit (Paddiw(X2, X X2, Integers.Int.neg _16));
emit (Pfsd(rs, X2, Ofsimm _0));
emit (Plw(rd1, X2, Ofsimm _0));
emit (Plw(rd2, X2, Ofsimm _4));
emit (Paddiw(X2, X X2, _16));
- fixup_variadic_call (pos + 2) tyl
+ fixup_variadic_call (ri + 2) (rf + 1) tyl
end
end
let fixup_call sg =
- if sg.sig_cc.cc_vararg then fixup_variadic_call 0 sg.sig_args
+ if sg.sig_cc.cc_vararg then fixup_variadic_call 0 0 sg.sig_args
(* Handling of annotations *)
@@ -483,7 +483,7 @@ let expand_instruction instr =
emit (Pmv (X30, X2));
if sg.sig_cc.cc_vararg then begin
let n = arguments_size sg in
- let extra_sz = if n >= 8 then 0 else align 16 ((8 - n) * wordsize) in
+ let extra_sz = if n >= 8 then 0 else align ((8 - n) * wordsize) 16 in
let full_sz = Z.add sz (Z.of_uint extra_sz) in
expand_addptrofs X2 X2 (Ptrofs.repr (Z.neg full_sz));
expand_storeind_ptr X30 X2 ofs;
@@ -501,7 +501,7 @@ let expand_instruction instr =
let extra_sz =
if sg.sig_cc.cc_vararg then begin
let n = arguments_size sg in
- if n >= 8 then 0 else align 16 ((8 - n) * wordsize)
+ if n >= 8 then 0 else align ((8 - n) * wordsize) 16
end else 0 in
expand_addptrofs X2 X2 (Ptrofs.repr (Z.add sz (Z.of_uint extra_sz)))
diff --git a/riscV/Asmgen.v b/riscV/Asmgen.v
index 631693b9..b431d63d 100644
--- a/riscV/Asmgen.v
+++ b/riscV/Asmgen.v
@@ -505,11 +505,16 @@ Definition transl_op
OK (Psrliw rd rs n :: k)
| Oshrximm n, a1 :: nil =>
do rd <- ireg_of res; do rs <- ireg_of a1;
- OK (if Int.eq n Int.zero then Pmv rd rs :: k else
- Psraiw X31 rs (Int.repr 31) ::
- Psrliw X31 X31 (Int.sub Int.iwordsize n) ::
- Paddw X31 rs X31 ::
- Psraiw rd X31 n :: k)
+ OK (if Int.eq n Int.zero
+ then Pmv rd rs :: k
+ else if Int.eq n Int.one
+ then Psrliw X31 rs (Int.repr 31) ::
+ Paddw X31 rs X31 ::
+ Psraiw rd X31 Int.one :: k
+ else Psraiw X31 rs (Int.repr 31) ::
+ Psrliw X31 X31 (Int.sub Int.iwordsize n) ::
+ Paddw X31 rs X31 ::
+ Psraiw rd X31 n :: k)
(* [Omakelong], [Ohighlong] should not occur *)
| Olowlong, a1 :: nil =>
@@ -594,11 +599,16 @@ Definition transl_op
OK (Psrlil rd rs n :: k)
| Oshrxlimm n, a1 :: nil =>
do rd <- ireg_of res; do rs <- ireg_of a1;
- OK (if Int.eq n Int.zero then Pmv rd rs :: k else
- Psrail X31 rs (Int.repr 63) ::
- Psrlil X31 X31 (Int.sub Int64.iwordsize' n) ::
- Paddl X31 rs X31 ::
- Psrail rd X31 n :: k)
+ OK (if Int.eq n Int.zero
+ then Pmv rd rs :: k
+ else if Int.eq n Int.one
+ then Psrlil X31 rs (Int.repr 63) ::
+ Paddl X31 rs X31 ::
+ Psrail rd X31 Int.one :: k
+ else Psrail X31 rs (Int.repr 63) ::
+ Psrlil X31 X31 (Int.sub Int64.iwordsize' n) ::
+ Paddl X31 rs X31 ::
+ Psrail rd X31 n :: k)
| Onegf, a1 :: nil =>
do rd <- freg_of res; do rs <- freg_of a1;
@@ -772,9 +782,13 @@ Definition transl_memory_access
Error(msg "Asmgen.transl_memory_access")
end.
-Definition transl_load (chunk: memory_chunk) (addr: addressing)
+Definition transl_load (trap : trapping_mode)
+ (chunk: memory_chunk) (addr: addressing)
(args: list mreg) (dst: mreg) (k: code) :=
- match chunk with
+ match trap with
+ | NOTRAP => Error (msg "Asmgen.transl_load non-trapping loads unsupported on Arm")
+ | TRAP =>
+ match chunk with
| Mint8signed =>
do r <- ireg_of dst;
transl_memory_access (Plb r) addr args k
@@ -801,6 +815,7 @@ Definition transl_load (chunk: memory_chunk) (addr: addressing)
transl_memory_access (Pfld r) addr args k
| _ =>
Error (msg "Asmgen.transl_load")
+ end
end.
Definition transl_store (chunk: memory_chunk) (addr: addressing)
@@ -850,8 +865,8 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
else loadind_ptr SP f.(fn_link_ofs) X30 c)
| Mop op args res =>
transl_op op args res k
- | Mload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | Mload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| Mstore chunk addr args src =>
transl_store chunk addr args src k
| Mcall sig (inl r) =>
diff --git a/riscV/Asmgenproof.v b/riscV/Asmgenproof.v
index 5ec57886..8e9f022c 100644
--- a/riscV/Asmgenproof.v
+++ b/riscV/Asmgenproof.v
@@ -285,12 +285,12 @@ Opaque Int.eq.
- apply opimm32_label; intros; exact I.
- apply opimm32_label; intros; exact I.
- apply opimm32_label; intros; exact I.
-- destruct (Int.eq n Int.zero); TailNoLabel.
+- destruct (Int.eq n Int.zero); try destruct (Int.eq n Int.one); TailNoLabel.
- apply opimm64_label; intros; exact I.
- apply opimm64_label; intros; exact I.
- apply opimm64_label; intros; exact I.
- apply opimm64_label; intros; exact I.
-- destruct (Int.eq n Int.zero); TailNoLabel.
+- destruct (Int.eq n Int.zero); try destruct (Int.eq n Int.one); TailNoLabel.
- eapply transl_cond_op_label; eauto.
Qed.
@@ -359,7 +359,7 @@ Proof.
- destruct ep. eapply loadind_label; eauto.
eapply tail_nolabel_trans. apply loadind_ptr_label. eapply loadind_label; eauto.
- eapply transl_op_label; eauto.
-- destruct m; monadInv H; eapply transl_memory_access_label; eauto; intros; exact I.
+- destruct t; (try discriminate); destruct m; monadInv H; eapply transl_memory_access_label; eauto; intros; exact I.
- destruct m; monadInv H; eapply transl_memory_access_label; eauto; intros; exact I.
- destruct s0; monadInv H; TailNoLabel.
- destruct s0; monadInv H; (eapply tail_nolabel_trans; [eapply make_epilogue_label|TailNoLabel]).
@@ -725,6 +725,12 @@ Local Transparent destroyed_by_op.
intros; auto with asmgen.
simpl; congruence.
+- (* Mload notrap *) (* isn't there a nicer way? *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
- (* Mstore *)
assert (eval_addressing tge sp addr (map rs args) = Some a).
rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
diff --git a/riscV/Asmgenproof1.v b/riscV/Asmgenproof1.v
index c20c4e49..8678a5dc 100644
--- a/riscV/Asmgenproof1.v
+++ b/riscV/Asmgenproof1.v
@@ -1035,17 +1035,23 @@ Opaque Int.eq.
intros (rs' & A & B & C).
exists rs'; split; eauto. rewrite B; auto with asmgen.
- (* shrximm *)
- clear H. exploit Val.shrx_shr_2; eauto. intros E; subst v; clear EV.
+ clear H. exploit Val.shrx_shr_3; eauto. intros E; subst v; clear EV.
destruct (Int.eq n Int.zero).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
split; intros; Simpl.
-+ change (Int.repr 32) with Int.iwordsize. set (n' := Int.sub Int.iwordsize n).
- econstructor; split.
- eapply exec_straight_step. simpl; reflexivity. auto.
- eapply exec_straight_step. simpl; reflexivity. auto.
- eapply exec_straight_step. simpl; reflexivity. auto.
- apply exec_straight_one. simpl; reflexivity. auto.
- split; intros; Simpl.
++ destruct (Int.eq n Int.one).
+ * econstructor; split.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ apply exec_straight_one. simpl; reflexivity. auto.
+ split; intros; Simpl.
+ * change (Int.repr 32) with Int.iwordsize. set (n' := Int.sub Int.iwordsize n).
+ econstructor; split.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ apply exec_straight_one. simpl; reflexivity. auto.
+ split; intros; Simpl.
- (* longofintu *)
econstructor; split.
eapply exec_straight_three. simpl; eauto. simpl; eauto. simpl; eauto. auto. auto. auto.
@@ -1070,17 +1076,24 @@ Opaque Int.eq.
intros (rs' & A & B & C).
exists rs'; split; eauto. rewrite B; auto with asmgen.
- (* shrxlimm *)
- clear H. exploit Val.shrxl_shrl_2; eauto. intros E; subst v; clear EV.
+ clear H. exploit Val.shrxl_shrl_3; eauto. intros E; subst v; clear EV.
destruct (Int.eq n Int.zero).
+ econstructor; split. apply exec_straight_one. simpl; eauto. auto.
split; intros; Simpl.
-+ change (Int.repr 64) with Int64.iwordsize'. set (n' := Int.sub Int64.iwordsize' n).
- econstructor; split.
- eapply exec_straight_step. simpl; reflexivity. auto.
- eapply exec_straight_step. simpl; reflexivity. auto.
- eapply exec_straight_step. simpl; reflexivity. auto.
- apply exec_straight_one. simpl; reflexivity. auto.
- split; intros; Simpl.
++ destruct (Int.eq n Int.one).
+ * econstructor; split.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ apply exec_straight_one. simpl; reflexivity. auto.
+ split; intros; Simpl.
+
+ * change (Int.repr 64) with Int64.iwordsize'. set (n' := Int.sub Int64.iwordsize' n).
+ econstructor; split.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ eapply exec_straight_step. simpl; reflexivity. auto.
+ apply exec_straight_one. simpl; reflexivity. auto.
+ split; intros; Simpl.
- (* cond *)
exploit transl_cond_op_correct; eauto. intros (rs' & A & B & C).
exists rs'; split. eexact A. eauto with asmgen.
@@ -1302,8 +1315,8 @@ Proof.
Qed.
Lemma transl_load_correct:
- forall chunk addr args dst k c (rs: regset) m a v,
- transl_load chunk addr args dst k = OK c ->
+ forall trap chunk addr args dst k c (rs: regset) m a v,
+ transl_load trap chunk addr args dst k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
@@ -1311,7 +1324,8 @@ Lemma transl_load_correct:
/\ rs'#(preg_of dst) = v
/\ forall r, r <> PC -> r <> X31 -> r <> preg_of dst -> rs'#r = rs#r.
Proof.
- intros until v; intros TR EV LOAD.
+ intros until v; intros TR EV LOAD.
+ destruct trap; try (simpl in *; discriminate).
assert (A: exists mk_instr,
transl_memory_access mk_instr addr args k = OK c
/\ forall base ofs rs,
diff --git a/riscV/Builtins1.v b/riscV/Builtins1.v
index f6e643d2..53c83d7e 100644
--- a/riscV/Builtins1.v
+++ b/riscV/Builtins1.v
@@ -29,5 +29,5 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with end.
diff --git a/riscV/CSE2deps.v b/riscV/CSE2deps.v
new file mode 100644
index 00000000..8ab9242a
--- /dev/null
+++ b/riscV/CSE2deps.v
@@ -0,0 +1,20 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs (Ptrofs.unsigned ofs') chunk' (Ptrofs.unsigned ofs) chunk)
+ else true | _, _, _, _ => true
+ end.
diff --git a/riscV/CSE2depsproof.v b/riscV/CSE2depsproof.v
new file mode 100644
index 00000000..a3811e78
--- /dev/null
+++ b/riscV/CSE2depsproof.v
@@ -0,0 +1,127 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Lemma ptrofs_size :
+ Ptrofs.wordsize = (if Archi.ptr64 then 64 else 32)%nat.
+Proof.
+ unfold Ptrofs.wordsize.
+ unfold Wordsize_Ptrofs.wordsize.
+ trivial.
+Qed.
+
+Lemma ptrofs_modulus :
+ Ptrofs.modulus = if Archi.ptr64 then 18446744073709551616 else 4294967296.
+Proof.
+ unfold Ptrofs.modulus.
+ rewrite ptrofs_size.
+ destruct Archi.ptr64; reflexivity.
+Qed.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : ptrofs.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= Ptrofs.unsigned ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= Ptrofs.unsigned ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : Ptrofs.unsigned ofsw + size_chunk chunkw <= Ptrofs.unsigned ofsr
+ \/ Ptrofs.unsigned ofsr + size_chunk chunkr <= Ptrofs.unsigned ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in *.
+
+ rewrite ptrofs_modulus in *.
+ simpl in *.
+ inv ADDRR.
+ inv ADDRW.
+ destruct base; try discriminate.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i ofsr) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i ofsw) as [OFSW | OFSW];
+ rewrite OFSW).
+ all: try rewrite ptrofs_modulus in *.
+ all: destruct Archi.ptr64.
+
+ all: intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs (Ptrofs.unsigned ofsr) chunkr (Ptrofs.unsigned ofsw) chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs (Ptrofs.unsigned i0) chunk' (Ptrofs.unsigned i) chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away with (F:=F) (V:=V) (genv:=genv) (sp:=sp); eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/riscV/Conventions1.v b/riscV/Conventions1.v
index df7ddfd2..17326139 100644
--- a/riscV/Conventions1.v
+++ b/riscV/Conventions1.v
@@ -105,7 +105,9 @@ Definition is_float_reg (r: mreg) :=
of function arguments), but this leaves much liberty in choosing actual
locations. To ensure binary interoperability of code generated by our
compiler with libraries compiled by another compiler, we
- implement the standard RISC-V conventions. *)
+ implement the standard RISC-V conventions as found here:
+ https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
+*)
(** ** Location of function result *)
@@ -115,11 +117,10 @@ Definition is_float_reg (r: mreg) :=
with one integer result. *)
Definition loc_result (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One R10
- | Some (Tint | Tany32) => One R10
- | Some (Tfloat | Tsingle | Tany64) => One F10
- | Some Tlong => if Archi.ptr64 then One R10 else Twolong R11 R10
+ match proj_sig_res s with
+ | Tint | Tany32 => One R10
+ | Tfloat | Tsingle | Tany64 => One F10
+ | Tlong => if Archi.ptr64 then One R10 else Twolong R11 R10
end.
(** The result registers have types compatible with that given in the signature. *)
@@ -128,8 +129,8 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result, mreg_type;
- destruct (sig_res sig) as [[]|]; auto; destruct Archi.ptr64; auto.
+ intros. unfold loc_result, mreg_type;
+ destruct (proj_sig_res sig); auto; destruct Archi.ptr64; auto.
Qed.
(** The result locations are caller-save registers *)
@@ -139,7 +140,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros. unfold loc_result, is_callee_save;
- destruct (sig_res s) as [[]|]; simpl; auto; destruct Archi.ptr64; simpl; auto.
+ destruct (proj_sig_res s); simpl; auto; destruct Archi.ptr64; simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -149,13 +150,13 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
intros.
- unfold loc_result; destruct (sig_res sg) as [[]|]; auto.
+ unfold loc_result; destruct (proj_sig_res sg); auto.
unfold mreg_type; destruct Archi.ptr64; auto.
split; auto. congruence.
Qed.
@@ -165,43 +166,37 @@ Qed.
Lemma loc_result_exten:
forall s1 s2, s1.(sig_res) = s2.(sig_res) -> loc_result s1 = loc_result s2.
Proof.
- intros. unfold loc_result. rewrite H; auto.
+ intros. unfold loc_result, proj_sig_res. rewrite H; auto.
Qed.
(** ** Location of function arguments *)
-(** The RISC-V ABI states the following convention for passing arguments
+(** The RISC-V ABI states the following conventions for passing arguments
to a function:
-- Arguments are passed in registers when possible.
-
-- Up to eight integer registers (ai: int_param_regs) and up to eight
- floating-point registers (fai: float_param_regs) are used for this
- purpose.
-
-- If the arguments to a function are conceptualized as fields of a C
- struct, each with pointer alignment, the argument registers are a
- shadow of the first eight pointer-words of that struct. If argument
- i < 8 is a floating-point type, it is passed in floating-point
- register fa_i; otherwise, it is passed in integer register a_i.
-
-- When primitive arguments twice the size of a pointer-word are passed
- on the stack, they are naturally aligned. When they are passed in the
- integer registers, they reside in an aligned even-odd register pair,
- with the even register holding the least-significant bits.
-
-- Floating-point arguments to variadic functions (except those that
- are explicitly named in the parameter list) are passed in integer
- registers.
-
-- The portion of the conceptual struct that is not passed in argument
- registers is passed on the stack. The stack pointer sp points to the
- first argument not passed in a register.
-
-The bit about variadic functions doesn't quite fit CompCert's model.
-We do our best by passing the FP arguments in registers, as usual,
-and reserving the corresponding integer registers, so that fixup
-code can be introduced in the Asmexpand pass.
+- RV64, not variadic: pass the first 8 integer arguments in
+ integer registers (a1...a8: int_param_regs), the first 8 FP arguments
+ in FP registers (fa1...fa8: float_param_regs), and the remaining
+ arguments on the stack, in 8-byte slots.
+
+- RV32, not variadic: same, but arguments of 64-bit integer type
+ are passed in two consecutive integer registers (a(i), a(i+1))
+ or in a(8) and on a 32-bit word on the stack. Stack-allocated
+ arguments are aligned to their natural alignment.
+
+- RV64, variadic: pass the first 8 arguments in integer registers
+ (a1...a8), including FP arguments; pass the remaining arguments on
+ the stack, in 8-byte slots.
+
+- RV32, variadic: same, but arguments of 64-bit types (integers as well
+ as floats) are passed in two consecutive aligned integer registers
+ (a(2i), a(2i+1)).
+
+The passing of FP arguments to variadic functions in integer registers
+doesn't quite fit CompCert's model. We do our best by passing the FP
+arguments in registers, as usual, and reserving the corresponding
+integer registers, so that fixup code can be introduced in the
+Asmexpand pass.
*)
Definition int_param_regs :=
@@ -209,80 +204,84 @@ Definition int_param_regs :=
Definition float_param_regs :=
F10 :: F11 :: F12 :: F13 :: F14 :: F15 :: F16 :: F17 :: nil.
-Definition one_arg (regs: list mreg) (rn: Z) (ofs: Z) (ty: typ)
- (rec: Z -> Z -> list (rpair loc)) :=
- match list_nth_z regs rn with
+Definition int_arg (ri rf ofs: Z) (ty: typ)
+ (rec: Z -> Z -> Z -> list (rpair loc)) :=
+ match list_nth_z int_param_regs ri with
| Some r =>
- One(R r) :: rec (rn + 1) ofs
+ One(R r) :: rec (ri + 1) rf ofs
| None =>
- let ofs := align ofs (typealign ty) in
- One(S Outgoing ofs ty) :: rec rn (ofs + (if Archi.ptr64 then 2 else typesize ty))
+ let ofs := align ofs (typesize ty) in
+ One(S Outgoing ofs ty)
+ :: rec ri rf (ofs + (if Archi.ptr64 then 2 else typesize ty))
end.
-Definition two_args (regs: list mreg) (rn: Z) (ofs: Z)
- (rec: Z -> Z -> list (rpair loc)) :=
- let rn := align rn 2 in
- match list_nth_z regs rn, list_nth_z regs (rn + 1) with
- | Some r1, Some r2 =>
- Twolong (R r2) (R r1) :: rec (rn + 2) ofs
- | _, _ =>
- let ofs := align ofs 2 in
- Twolong (S Outgoing (ofs + 1) Tint) (S Outgoing ofs Tint) ::
- rec rn (ofs + 2)
+Definition float_arg (va: bool) (ri rf ofs: Z) (ty: typ)
+ (rec: Z -> Z -> Z -> list (rpair loc)) :=
+ match list_nth_z float_param_regs rf with
+ | Some r =>
+ if va then
+ (let ri' := (* reserve 1 or 2 aligned integer registers *)
+ if Archi.ptr64 || zeq (typesize ty) 1 then ri + 1 else align ri 2 + 2 in
+ if zle ri' 8 then
+ (* we have enough integer registers, put argument in FP reg
+ and fixup code will put it in one or two integer regs *)
+ One (R r) :: rec ri' (rf + 1) ofs
+ else
+ (* we are out of integer registers, pass argument on stack *)
+ let ofs := align ofs (typesize ty) in
+ One(S Outgoing ofs ty)
+ :: rec ri' rf (ofs + (if Archi.ptr64 then 2 else typesize ty)))
+ else
+ One (R r) :: rec ri (rf + 1) ofs
+ | None =>
+ let ofs := align ofs (typesize ty) in
+ One(S Outgoing ofs ty)
+ :: rec ri rf (ofs + (if Archi.ptr64 then 2 else typesize ty))
end.
-Definition hybrid_arg (regs: list mreg) (rn: Z) (ofs: Z) (ty: typ)
- (rec: Z -> Z -> list (rpair loc)) :=
- let rn := align rn 2 in
- match list_nth_z regs rn with
- | Some r =>
- One (R r) :: rec (rn + 2) ofs
- | None =>
+Definition split_long_arg (va: bool) (ri rf ofs: Z)
+ (rec: Z -> Z -> Z -> list (rpair loc)) :=
+ let ri := if va then align ri 2 else ri in
+ match list_nth_z int_param_regs ri, list_nth_z int_param_regs (ri + 1) with
+ | Some r1, Some r2 =>
+ Twolong (R r2) (R r1) :: rec (ri + 2) rf ofs
+ | Some r1, None =>
+ Twolong (S Outgoing ofs Tint) (R r1) :: rec (ri + 1) rf (ofs + 1)
+ | None, _ =>
let ofs := align ofs 2 in
- One (S Outgoing ofs ty) :: rec rn (ofs + 2)
+ Twolong (S Outgoing (ofs + 1) Tint) (S Outgoing ofs Tint) ::
+ rec ri rf (ofs + 2)
end.
Fixpoint loc_arguments_rec (va: bool)
- (tyl: list typ) (r ofs: Z) {struct tyl} : list (rpair loc) :=
+ (tyl: list typ) (ri rf ofs: Z) {struct tyl} : list (rpair loc) :=
match tyl with
| nil => nil
| (Tint | Tany32) as ty :: tys =>
- one_arg int_param_regs r ofs ty (loc_arguments_rec va tys)
+ (* pass in one integer register or on stack *)
+ int_arg ri rf ofs ty (loc_arguments_rec va tys)
| Tsingle as ty :: tys =>
- one_arg float_param_regs r ofs ty (loc_arguments_rec va tys)
+ (* pass in one FP register or on stack.
+ If vararg, reserve 1 integer register. *)
+ float_arg va ri rf ofs ty (loc_arguments_rec va tys)
| Tlong as ty :: tys =>
- if Archi.ptr64
- then one_arg int_param_regs r ofs ty (loc_arguments_rec va tys)
- else two_args int_param_regs r ofs (loc_arguments_rec va tys)
+ if Archi.ptr64 then
+ (* pass in one integer register or on stack *)
+ int_arg ri rf ofs ty (loc_arguments_rec va tys)
+ else
+ (* pass in register pair or on stack; align register pair if vararg *)
+ split_long_arg va ri rf ofs(loc_arguments_rec va tys)
| (Tfloat | Tany64) as ty :: tys =>
- if va && negb Archi.ptr64
- then hybrid_arg float_param_regs r ofs ty (loc_arguments_rec va tys)
- else one_arg float_param_regs r ofs ty (loc_arguments_rec va tys)
+ (* pass in one FP register or on stack.
+ If vararg, reserve 1 or 2 integer registers. *)
+ float_arg va ri rf ofs ty (loc_arguments_rec va tys)
end.
(** [loc_arguments s] returns the list of locations where to store arguments
when calling a function with signature [s]. *)
Definition loc_arguments (s: signature) : list (rpair loc) :=
- loc_arguments_rec s.(sig_cc).(cc_vararg) s.(sig_args) 0 0.
-
-(** [size_arguments s] returns the number of [Outgoing] slots used
- to call a function with signature [s]. *)
-
-Definition max_outgoing_1 (accu: Z) (l: loc) : Z :=
- match l with
- | S Outgoing ofs ty => Z.max accu (ofs + typesize ty)
- | _ => accu
- end.
-
-Definition max_outgoing_2 (accu: Z) (rl: rpair loc) : Z :=
- match rl with
- | One l => max_outgoing_1 accu l
- | Twolong l1 l2 => max_outgoing_1 (max_outgoing_1 accu l1) l2
- end.
-
-Definition size_arguments (s: signature) : Z :=
- List.fold_left max_outgoing_2 (loc_arguments s) 0.
+ loc_arguments_rec s.(sig_cc).(cc_vararg) s.(sig_args) 0 0 0.
(** Argument locations are either non-temporary registers or [Outgoing]
stack slots at nonnegative offsets. *)
@@ -295,90 +294,87 @@ Definition loc_argument_acceptable (l: loc) : Prop :=
end.
Lemma loc_arguments_rec_charact:
- forall va tyl rn ofs p,
+ forall va tyl ri rf ofs p,
ofs >= 0 ->
- In p (loc_arguments_rec va tyl rn ofs) -> forall_rpair loc_argument_acceptable p.
+ In p (loc_arguments_rec va tyl ri rf ofs) -> forall_rpair loc_argument_acceptable p.
Proof.
set (OK := fun (l: list (rpair loc)) =>
forall p, In p l -> forall_rpair loc_argument_acceptable p).
- set (OKF := fun (f: Z -> Z -> list (rpair loc)) =>
- forall rn ofs, ofs >= 0 -> OK (f rn ofs)).
- set (OKREGS := fun (l: list mreg) => forall r, In r l -> is_callee_save r = false).
- assert (AL: forall ofs ty, ofs >= 0 -> align ofs (typealign ty) >= 0).
+ set (OKF := fun (f: Z -> Z -> Z -> list (rpair loc)) =>
+ forall ri rf ofs, ofs >= 0 -> OK (f ri rf ofs)).
+ assert (CSI: forall r, In r int_param_regs -> is_callee_save r = false).
+ { decide_goal. }
+ assert (CSF: forall r, In r float_param_regs -> is_callee_save r = false).
+ { decide_goal. }
+ assert (AL: forall ofs ty, ofs >= 0 -> align ofs (typesize ty) >= 0).
{ intros.
- assert (ofs <= align ofs (typealign ty)) by (apply align_le; apply typealign_pos).
+ assert (ofs <= align ofs (typesize ty)) by (apply align_le; apply typesize_pos).
omega. }
+ assert (ALD: forall ofs ty, ofs >= 0 -> (typealign ty | align ofs (typesize ty))).
+ { intros. eapply Z.divide_trans. apply typealign_typesize.
+ apply align_divides. apply typesize_pos. }
assert (SK: (if Archi.ptr64 then 2 else 1) > 0).
{ destruct Archi.ptr64; omega. }
assert (SKK: forall ty, (if Archi.ptr64 then 2 else typesize ty) > 0).
{ intros. destruct Archi.ptr64. omega. apply typesize_pos. }
- assert (A: forall regs rn ofs ty f,
- OKREGS regs -> OKF f -> ofs >= 0 -> OK (one_arg regs rn ofs ty f)).
- { intros until f; intros OR OF OO; red; unfold one_arg; intros.
- destruct (list_nth_z regs rn) as [r|] eqn:NTH; destruct H.
- - subst p; simpl. apply OR. eapply list_nth_z_in; eauto.
+ assert (A: forall ri rf ofs ty f,
+ OKF f -> ofs >= 0 -> OK (int_arg ri rf ofs ty f)).
+ { intros until f; intros OF OO; red; unfold int_arg; intros.
+ destruct (list_nth_z int_param_regs ri) as [r|] eqn:NTH; destruct H.
+ - subst p; simpl. apply CSI. eapply list_nth_z_in; eauto.
- eapply OF; eauto.
- subst p; simpl. auto using align_divides, typealign_pos.
- eapply OF; [idtac|eauto].
generalize (AL ofs ty OO) (SKK ty); omega.
}
- assert (B: forall regs rn ofs f,
- OKREGS regs -> OKF f -> ofs >= 0 -> OK (two_args regs rn ofs f)).
- { intros until f; intros OR OF OO; unfold two_args.
- set (rn' := align rn 2).
+ assert (B: forall va ri rf ofs ty f,
+ OKF f -> ofs >= 0 -> OK (float_arg va ri rf ofs ty f)).
+ { intros until f; intros OF OO; red; unfold float_arg; intros.
+ destruct (list_nth_z float_param_regs rf) as [r|] eqn:NTH.
+ - set (ri' := if Archi.ptr64 || zeq (typesize ty) 1 then ri + 1 else align ri 2 + 2) in *.
+ destruct va; [destruct (zle ri' 8)|idtac]; destruct H.
+ + subst p; simpl. apply CSF. eapply list_nth_z_in; eauto.
+ + eapply OF; eauto.
+ + subst p; repeat split; auto.
+ + eapply OF; [idtac|eauto]. generalize (AL ofs ty OO) (SKK ty); omega.
+ + subst p; simpl. apply CSF. eapply list_nth_z_in; eauto.
+ + eapply OF; eauto.
+ - destruct H.
+ + subst p; repeat split; auto.
+ + eapply OF; [idtac|eauto]. generalize (AL ofs ty OO) (SKK ty); omega.
+ }
+ assert (C: forall va ri rf ofs f,
+ OKF f -> ofs >= 0 -> OK (split_long_arg va ri rf ofs f)).
+ { intros until f; intros OF OO; unfold split_long_arg.
+ set (ri' := if va then align ri 2 else ri).
set (ofs' := align ofs 2).
assert (OO': ofs' >= 0) by (apply (AL ofs Tlong); auto).
- assert (DFL: OK (Twolong (S Outgoing (ofs' + 1) Tint) (S Outgoing ofs' Tint)
- :: f rn' (ofs' + 2))).
- { red; simpl; intros. destruct H.
- - subst p; simpl.
- repeat split; auto using Z.divide_1_l. omega.
- - eapply OF; [idtac|eauto]. omega.
- }
- destruct (list_nth_z regs rn') as [r1|] eqn:NTH1;
- destruct (list_nth_z regs (rn' + 1)) as [r2|] eqn:NTH2;
- try apply DFL.
- red; simpl; intros; destruct H.
- - subst p; simpl. split; apply OR; eauto using list_nth_z_in.
- - eapply OF; [idtac|eauto]. auto.
+ destruct (list_nth_z int_param_regs ri') as [r1|] eqn:NTH1;
+ [destruct (list_nth_z int_param_regs (ri'+1)) as [r2|] eqn:NTH2 | idtac].
+ - red; simpl; intros; destruct H.
+ + subst p; split; apply CSI; eauto using list_nth_z_in.
+ + eapply OF; [idtac|eauto]. omega.
+ - red; simpl; intros; destruct H.
+ + subst p; split. split; auto using Z.divide_1_l. apply CSI; eauto using list_nth_z_in.
+ + eapply OF; [idtac|eauto]. omega.
+ - red; simpl; intros; destruct H.
+ + subst p; repeat split; auto using Z.divide_1_l. omega.
+ + eapply OF; [idtac|eauto]. omega.
}
- assert (C: forall regs rn ofs ty f,
- OKREGS regs -> OKF f -> ofs >= 0 -> typealign ty = 1 -> OK (hybrid_arg regs rn ofs ty f)).
- { intros until f; intros OR OF OO OTY; unfold hybrid_arg; red; intros.
- set (rn' := align rn 2) in *.
- destruct (list_nth_z regs rn') as [r|] eqn:NTH; destruct H.
- - subst p; simpl. apply OR. eapply list_nth_z_in; eauto.
- - eapply OF; eauto.
- - subst p; simpl. rewrite OTY. split. apply (AL ofs Tlong OO). apply Z.divide_1_l.
- - eapply OF; [idtac|eauto]. generalize (AL ofs Tlong OO); simpl; omega.
- }
- assert (D: OKREGS int_param_regs).
- { red. decide_goal. }
- assert (E: OKREGS float_param_regs).
- { red. decide_goal. }
-
- cut (forall va tyl rn ofs, ofs >= 0 -> OK (loc_arguments_rec va tyl rn ofs)).
+ cut (forall va tyl ri rf ofs, ofs >= 0 -> OK (loc_arguments_rec va tyl ri rf ofs)).
unfold OK. eauto.
induction tyl as [ | ty1 tyl]; intros until ofs; intros OO; simpl.
- red; simpl; tauto.
- destruct ty1.
+ (* int *) apply A; auto.
-+ (* float *)
- destruct (va && negb Archi.ptr64).
- apply C; auto.
- apply A; auto.
++ (* float *) apply B; auto.
+ (* long *)
destruct Archi.ptr64.
apply A; auto.
- apply B; auto.
-+ (* single *)
- apply A; auto.
-+ (* any32 *)
- apply A; auto.
-+ (* any64 *)
- destruct (va && negb Archi.ptr64).
apply C; auto.
- apply A; auto.
++ (* single *) apply B; auto.
++ (* any32 *) apply A; auto.
++ (* any64 *) apply B; auto.
Qed.
Lemma loc_arguments_acceptable:
@@ -388,54 +384,14 @@ Proof.
unfold loc_arguments; intros. eapply loc_arguments_rec_charact; eauto. omega.
Qed.
-(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
-
-Remark fold_max_outgoing_above:
- forall l n, fold_left max_outgoing_2 l n >= n.
-Proof.
- assert (A: forall n l, max_outgoing_1 n l >= n).
- { intros; unfold max_outgoing_1. destruct l as [_ | []]; xomega. }
- induction l; simpl; intros.
- - omega.
- - eapply Zge_trans. eauto.
- destruct a; simpl. apply A. eapply Zge_trans; eauto.
-Qed.
-
-Lemma size_arguments_above:
- forall s, size_arguments s >= 0.
-Proof.
- intros. apply fold_max_outgoing_above.
-Qed.
-
-Lemma loc_arguments_bounded:
- forall (s: signature) (ofs: Z) (ty: typ),
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
- ofs + typesize ty <= size_arguments s.
-Proof.
- intros until ty.
- assert (A: forall n l, n <= max_outgoing_1 n l).
- { intros; unfold max_outgoing_1. destruct l as [_ | []]; xomega. }
- assert (B: forall p n,
- In (S Outgoing ofs ty) (regs_of_rpair p) ->
- ofs + typesize ty <= max_outgoing_2 n p).
- { intros. destruct p; simpl in H; intuition; subst; simpl.
- - xomega.
- - eapply Z.le_trans. 2: apply A. xomega.
- - xomega. }
- assert (C: forall l n,
- In (S Outgoing ofs ty) (regs_of_rpairs l) ->
- ofs + typesize ty <= fold_left max_outgoing_2 l n).
- { induction l; simpl; intros.
- - contradiction.
- - rewrite in_app_iff in H. destruct H.
- + eapply Z.le_trans. eapply B; eauto. apply Z.ge_le. apply fold_max_outgoing_above.
- + apply IHl; auto.
- }
- apply C.
-Qed.
-
Lemma loc_arguments_main:
loc_arguments signature_main = nil.
Proof.
reflexivity.
Qed.
+
+(** ** Normalization of function results *)
+
+(** No normalization needed. *)
+
+Definition return_value_needs_normalization (t: rettype) := false.
diff --git a/riscV/DuplicateOpcodeHeuristic.ml b/riscV/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..2ec314c1
--- /dev/null
+++ b/riscV/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,27 @@
+(* open Camlcoq *)
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccomplimm (c, n) | Ccompluimm (c, n) -> if n == Integers.Int64.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c | Ccompfs c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c | Cnotcompfs c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
diff --git a/riscV/Op.v b/riscV/Op.v
index bb04f786..a71696c7 100644
--- a/riscV/Op.v
+++ b/riscV/Op.v
@@ -666,6 +666,36 @@ Proof with (try exact I; try reflexivity; auto using Val.Vptr_has_type).
- destruct (eval_condition cond vl m)... destruct b...
Qed.
+
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivl | Odivu | Odivlu
+ | Omod | Omodl | Omodu | Omodlu
+ | Oshrximm _ | Oshrxlimm _
+ | Ointoffloat | Ointuoffloat
+ | Ointofsingle | Ointuofsingle
+ | Olongoffloat | Olonguoffloat
+ | Olongofsingle | Olonguofsingle
+ | Osingleofint | Osingleofintu
+ | Osingleoflong | Osingleoflongu
+ | Ofloatofint | Ofloatofintu
+ | Ofloatoflong | Ofloatoflongu => true
+ | _ => false
+ end.
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -1159,6 +1189,20 @@ Proof.
apply Val.offset_ptr_inject; auto.
Qed.
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *;
+ inv Hinjvl; trivial; try discriminate; inv H0; trivial; try discriminate; inv H2; trivial; try discriminate.
+Qed.
End EVAL_COMPAT.
(** Compatibility of the evaluation functions with the ``is less defined'' relation over values. *)
@@ -1265,6 +1309,18 @@ Proof.
destruct H1 as [v2 [A B]]. exists v2; split; auto. rewrite val_inject_lessdef; auto.
Qed.
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros until vl2. intros Hlessdef Heval1.
+ destruct addr; simpl in *;
+ inv Hlessdef; trivial; try discriminate;
+ inv H0; trivial; try discriminate;
+ inv H2; trivial; try discriminate.
+Qed.
End EVAL_LESSDEF.
(** Compatibility of the evaluation functions with memory injections. *)
@@ -1317,6 +1373,20 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/runtime/arm/i64_stof.S b/runtime/arm/i64_stof.S
index bcfa471c..11e00a2a 100644
--- a/runtime/arm/i64_stof.S
+++ b/runtime/arm/i64_stof.S
@@ -39,12 +39,11 @@
@@@ Conversion from signed 64-bit integer to single float
FUNCTION(__compcert_i64_stof)
- @ Check whether -2^53 <= X < 2^53
- ASR r2, Reg0HI, #21
- ASR r3, Reg0HI, #31 @ (r2,r3) = X >> 53
+ @ Check whether -2^53 <= X < 2^53
+ ASR r2, Reg0HI, #21 @ r2 = high 32 bits of X >> 53
+ @ -2^53 <= X < 2^53 iff r2 is -1 or 0, that is, iff r2 + 1 is 0 or 1
adds r2, r2, #1
- adc r3, r3, #0 @ (r2,r3) = X >> 53 + 1
- cmp r3, #2
+ cmp r2, #2
blo 1f
@ X is large enough that double rounding can occur.
@ Avoid it by nudging X away from the points where double rounding
diff --git a/runtime/include/math.h b/runtime/include/math.h
index 060968c8..01b8d8d8 100644
--- a/runtime/include/math.h
+++ b/runtime/include/math.h
@@ -1,8 +1,12 @@
#ifndef _COMPCERT_MATH_H
#define _COMPCERT_MATH_H
+#ifdef __K1C__
+
#define isfinite(__y) (fpclassify((__y)) >= FP_ZERO)
+#include_next <math.h>
+
#ifndef COMPCERT_NO_FP_MACROS
#define fmin(x, y) __builtin_fmin((x),(y))
#define fmax(x, y) __builtin_fmax((x),(y))
@@ -14,5 +18,9 @@
#define fmaf(x, y, z) __builtin_fmaf((x),(y),(z))
#endif
+#else
+
#include_next <math.h>
+
+#endif
#endif
diff --git a/runtime/mppa_k1c/vararg.S b/runtime/mppa_k1c/vararg.s
index 9e23e0b3..65c1eab8 100644
--- a/runtime/mppa_k1c/vararg.S
+++ b/runtime/mppa_k1c/vararg.s
@@ -1,7 +1,7 @@
-// typedef void * va_list;
-// unsigned int __compcert_va_int32(va_list * ap);
-// unsigned long long __compcert_va_int64(va_list * ap);
+# typedef void * va_list;
+# unsigned int __compcert_va_int32(va_list * ap);
+# unsigned long long __compcert_va_int64(va_list * ap);
.text
.balign 2
diff --git a/runtime/powerpc/i64_dtos.s b/runtime/powerpc/i64_dtos.s
new file mode 100644
index 00000000..85c60b27
--- /dev/null
+++ b/runtime/powerpc/i64_dtos.s
@@ -0,0 +1,100 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from double float to signed long
+
+ .balign 16
+ .globl __compcert_i64_dtos
+__compcert_i64_dtos:
+ stfdu f1, -16(r1) # extract LO (r4) and HI (r3) halves of double
+ lwz r3, 0(r1)
+ lwz r4, 4(r1)
+ addi r1, r1, 16
+ srawi r10, r3, 31 # save sign of double in r10
+ # extract unbiased exponent ((HI & 0x7FF00000) >> 20) - (1023 + 52)
+ rlwinm r5, r3, 12, 21, 31
+ addi r5, r5, -1075
+ # check range of exponent
+ cmpwi r5, -52 # if EXP < -52, abs(double) is < 1.0
+ blt 1f
+ cmpwi r5, 11 # if EXP >= 63 - 52, abs(double) is >= 2^63
+ bge 2f
+ # extract true mantissa
+ rlwinm r3, r3, 0, 12, 31 # HI &= ~0xFFF00000
+ oris r3, r3, 0x10 # HI |= 0x00100000
+ # shift it appropriately
+ cmpwi r5, 0
+ blt 3f
+ # if EXP >= 0, shift left by EXP. Note that EXP < 11.
+ subfic r6, r5, 32 # r6 = 32 - EXP
+ slw r3, r3, r5
+ srw r0, r4, r6
+ or r3, r3, r0
+ slw r4, r4, r5
+ b 4f
+ # if EXP < 0, shift right by -EXP. Note that -EXP <= 52 but can be >= 32.
+3: subfic r5, r5, 0 # r5 = -EXP = shift amount
+ subfic r6, r5, 32 # r6 = 32 - amount
+ addi r7, r5, -32 # r7 = amount - 32 (see i64_shr.s)
+ srw r4, r4, r5
+ slw r0, r3, r6
+ or r4, r4, r0
+ srw r0, r3, r7
+ or r4, r4, r0
+ srw r3, r3, r5
+ # apply sign to result
+4: xor r4, r4, r10
+ xor r3, r3, r10
+ subfc r4, r10, r4
+ subfe r3, r10, r3
+ blr
+ # Special cases
+1: li r3, 0 # result is 0
+ li r4, 0
+ blr
+2: li r4, -1 # result is MAX_SINT or MIN_SINT
+ bge 5f # depending on sign
+ li r4, -1 # result is MAX_SINT = 0x7FFF_FFFF
+ srwi r3, r4, 1
+ blr
+5: lis r3, 0x8000 # result is MIN_SINT = 0x8000_0000
+ li r4, 0
+ blr
+ .type __compcert_i64_dtos, @function
+ .size __compcert_i64_dtos, .-__compcert_i64_dtos
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_dtou.s b/runtime/powerpc/i64_dtou.s
new file mode 100644
index 00000000..67a721d4
--- /dev/null
+++ b/runtime/powerpc/i64_dtou.s
@@ -0,0 +1,92 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from double float to unsigned long
+
+ .balign 16
+ .globl __compcert_i64_dtou
+__compcert_i64_dtou:
+ stfdu f1, -16(r1) # extract LO (r4) and HI (r3) halves of double
+ lwz r3, 0(r1)
+ lwz r4, 4(r1)
+ addi r1, r1, 16
+ cmpwi r3, 0 # is double < 0?
+ blt 1f # then it converts to 0
+ # extract unbiased exponent ((HI & 0x7FF00000) >> 20) - (1023 + 52)
+ rlwinm r5, r3, 12, 21, 31
+ addi r5, r5, -1075
+ # check range of exponent
+ cmpwi r5, -52 # if EXP < -52, double is < 1.0
+ blt 1f
+ cmpwi r5, 12 # if EXP >= 64 - 52, double is >= 2^64
+ bge 2f
+ # extract true mantissa
+ rlwinm r3, r3, 0, 12, 31 # HI &= ~0xFFF00000
+ oris r3, r3, 0x10 # HI |= 0x00100000
+ # shift it appropriately
+ cmpwi r5, 0
+ blt 3f
+ # if EXP >= 0, shift left by EXP. Note that EXP < 12.
+ subfic r6, r5, 32 # r6 = 32 - EXP
+ slw r3, r3, r5
+ srw r0, r4, r6
+ or r3, r3, r0
+ slw r4, r4, r5
+ blr
+ # if EXP < 0, shift right by -EXP. Note that -EXP <= 52 but can be >= 32.
+3: subfic r5, r5, 0 # r5 = -EXP = shift amount
+ subfic r6, r5, 32 # r6 = 32 - amount
+ addi r7, r5, -32 # r7 = amount - 32 (see i64_shr.s)
+ srw r4, r4, r5
+ slw r0, r3, r6
+ or r4, r4, r0
+ srw r0, r3, r7
+ or r4, r4, r0
+ srw r3, r3, r5
+ blr
+ # Special cases
+1: li r3, 0 # result is 0
+ li r4, 0
+ blr
+2: li r3, -1 # result is MAX_UINT
+ li r4, -1
+ blr
+ .type __compcert_i64_dtou, @function
+ .size __compcert_i64_dtou, .-__compcert_i64_dtou
+
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_sar.s b/runtime/powerpc/i64_sar.s
new file mode 100644
index 00000000..c7da448f
--- /dev/null
+++ b/runtime/powerpc/i64_sar.s
@@ -0,0 +1,60 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+# Shift right signed
+
+ .balign 16
+ .globl __compcert_i64_sar
+__compcert_i64_sar:
+ andi. r5, r5, 63 # take amount modulo 64
+ cmpwi r5, 32
+ bge 1f # amount < 32?
+ subfic r6, r5, 32 # r6 = 32 - amount
+ srw r4, r4, r5 # RH = XH >>s amount
+ slw r0, r3, r6 # RL = XL >>u amount | XH << (32 - amount)
+ or r4, r4, r0
+ sraw r3, r3, r5
+ blr
+1: addi r6, r5, -32 # amount >= 32
+ sraw r4, r3, r6 # RL = XH >>s (amount - 32)
+ srawi r3, r3, 31 # RL = sign extension of XH
+ blr
+ .type __compcert_i64_sar, @function
+ .size __compcert_i64_sar, .-__compcert_i64_sar
+
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_sdiv.s b/runtime/powerpc/i64_sdiv.s
new file mode 100644
index 00000000..9787ea3b
--- /dev/null
+++ b/runtime/powerpc/i64_sdiv.s
@@ -0,0 +1,71 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Signed division
+
+ .balign 16
+ .globl __compcert_i64_sdiv
+__compcert_i64_sdiv:
+ mflr r0
+ stw r0, 4(r1) # save return address in caller's frame
+ xor r0, r3, r5 # compute sign of result (top bit)
+ mtctr r0 # save it in CTR (why not?)
+ srawi r0, r3, 31 # take absolute value of N
+ xor r4, r4, r0 # (i.e. N = N ^ r0 - r0,
+ xor r3, r3, r0 # where r0 = 0 if N >= 0 and r0 = -1 if N < 0)
+ subfc r4, r0, r4
+ subfe r3, r0, r3
+ srawi r0, r5, 31 # take absolute value of D
+ xor r6, r6, r0 # (same trick)
+ xor r5, r5, r0
+ subfc r6, r0, r6
+ subfe r5, r0, r5
+ bl __compcert_i64_udivmod # do unsigned division
+ lwz r0, 4(r1)
+ mtlr r0 # restore return address
+ mfctr r0
+ srawi r0, r0, 31 # apply expected sign to quotient
+ xor r6, r6, r0 # RES = Q if CTR >= 0, -Q if CTR < 0
+ xor r5, r5, r0
+ subfc r4, r0, r6
+ subfe r3, r0, r5
+ blr
+ .type __compcert_i64_sdiv, @function
+ .size __compcert_i64_sdiv, .-__compcert_i64_sdiv
+
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_shl.s b/runtime/powerpc/i64_shl.s
new file mode 100644
index 00000000..f6edb6c2
--- /dev/null
+++ b/runtime/powerpc/i64_shl.s
@@ -0,0 +1,64 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+# Shift left
+
+ .balign 16
+ .globl __compcert_i64_shl
+__compcert_i64_shl:
+# On PowerPC, shift instructions with amount mod 64 >= 32 return 0
+# hi = (hi << amount) | (lo >> (32 - amount)) | (lo << (amount - 32))
+# lo = lo << amount
+# if 0 <= amount < 32:
+# (amount - 32) mod 64 >= 32, hence lo << (amount - 32) == 0
+# if 32 <= amount < 64:
+# lo << amount == 0
+# (32 - amount) mod 64 >= 32, hence lo >> (32 - amount) == 0
+ andi. r5, r5, 63 # take amount modulo 64
+ subfic r6, r5, 32 # r6 = 32 - amount
+ addi r7, r5, -32 # r7 = amount - 32
+ slw r3, r3, r5
+ srw r0, r4, r6
+ or r3, r3, r0
+ slw r0, r4, r7
+ or r3, r3, r0
+ slw r4, r4, r5
+ blr
+ .type __compcert_i64_shl, @function
+ .size __compcert_i64_shl, .-__compcert_i64_shl
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_shr.s b/runtime/powerpc/i64_shr.s
new file mode 100644
index 00000000..b634aafd
--- /dev/null
+++ b/runtime/powerpc/i64_shr.s
@@ -0,0 +1,65 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+# Shift right unsigned
+
+ .balign 16
+ .globl __compcert_i64_shr
+__compcert_i64_shr:
+# On PowerPC, shift instructions with amount mod 64 >= 32 return 0
+# lo = (lo >> amount) | (hi << (32 - amount)) | (hi >> (amount - 32))
+# hi = hi >> amount
+# if 0 <= amount < 32:
+# (amount - 32) mod 64 >= 32, hence hi >> (amount - 32) == 0
+# if 32 <= amount < 64:
+# hi >> amount == 0
+# (32 - amount) mod 64 >= 32, hence hi << (32 - amount) == 0
+ andi. r5, r5, 63 # take amount modulo 64
+ subfic r6, r5, 32 # r6 = 32 - amount
+ addi r7, r5, -32 # r7 = amount - 32
+ srw r4, r4, r5
+ slw r0, r3, r6
+ or r4, r4, r0
+ srw r0, r3, r7
+ or r4, r4, r0
+ srw r3, r3, r5
+ blr
+ .type __compcert_i64_shr, @function
+ .size __compcert_i64_shr, .-__compcert_i64_shr
+
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_smod.s b/runtime/powerpc/i64_smod.s
new file mode 100644
index 00000000..6b4e1f89
--- /dev/null
+++ b/runtime/powerpc/i64_smod.s
@@ -0,0 +1,70 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+## Signed remainder
+
+ .balign 16
+ .globl __compcert_i64_smod
+__compcert_i64_smod:
+ mflr r0
+ stw r0, 4(r1) # save return address in caller's frame
+ mtctr r3 # save sign of result in CTR (sign of N)
+ srawi r0, r3, 31 # take absolute value of N
+ xor r4, r4, r0 # (i.e. N = N ^ r0 - r0,
+ xor r3, r3, r0 # where r0 = 0 if N >= 0 and r0 = -1 if N < 0)
+ subfc r4, r0, r4
+ subfe r3, r0, r3
+ srawi r0, r5, 31 # take absolute value of D
+ xor r6, r6, r0 # (same trick)
+ xor r5, r5, r0
+ subfc r6, r0, r6
+ subfe r5, r0, r5
+ bl __compcert_i64_udivmod # do unsigned division
+ lwz r0, 4(r1)
+ mtlr r0 # restore return address
+ mfctr r0
+ srawi r0, r0, 31 # apply expected sign to remainder
+ xor r4, r4, r0 # RES = R if CTR >= 0, -Q if CTR < 0
+ xor r3, r3, r0
+ subfc r4, r0, r4
+ subfe r3, r0, r3
+ blr
+ .type __compcert_i64_smod, @function
+ .size __compcert_i64_smod, .-__compcert_i64_smod
+
+ \ No newline at end of file
diff --git a/runtime/powerpc/i64_smulh.s b/runtime/powerpc/i64_smulh.s
new file mode 100644
index 00000000..73393fce
--- /dev/null
+++ b/runtime/powerpc/i64_smulh.s
@@ -0,0 +1,80 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris
+#
+# Copyright (c) 2016 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Signed multiply-high
+
+# Hacker's Delight section 8.3:
+# - compute high 64 bits of the unsigned product X * Y (see i64_umulh.S)
+# - subtract X if Y < 0
+# - subtract Y if X < 0
+
+ .balign 16
+ .globl __compcert_i64_smulh
+__compcert_i64_smulh:
+# r7:r8:r9 accumulate bits 127:32 of the full unsigned product
+ mulhwu r9, r4, r6 # r9 = high half of XL.YL
+ mullw r0, r4, r5 # r0 = low half of XL.YH
+ addc r9, r9, r0
+ mulhwu r0, r4, r5 # r0 = high half of XL.YH
+ addze r8, r0
+ mullw r0, r3, r6 # r0 = low half of XH.YL
+ addc r9, r9, r0
+ mulhwu r0, r3, r6 # r0 = high half of XH.YL
+ adde r8, r8, r0
+ li r7, 0
+ addze r7, r7
+ mullw r0, r3, r5 # r0 = low half of XH.YH
+ addc r8, r8, r0
+ mulhwu r0, r3, r5 # r0 = high half of XH.YH
+ adde r7, r7, r0
+# Here r7:r8 contains the high 64 bits of the unsigned product.
+# Now, test signs and subtract if needed
+ srawi r0, r3, 31 # r0 = -1 if X < 0, r0 = 0 if X >= 0
+ srawi r9, r5, 31 # r9 = -1 if Y < 0, r9 = 0 if Y >= 0
+ and r3, r3, r9 # set X = 0 if Y >= 0
+ and r4, r4, r9
+ and r5, r5, r0 # set Y = 0 if X >= 0
+ and r6, r6, r0
+ subfc r8, r4, r8 # subtract X
+ subfe r7, r3, r7
+ subfc r4, r6, r8 # subtract Y
+ subfe r3, r5, r7
+ blr
+ .type __compcert_i64_smulh, @function
+ .size __compcert_i64_smulh, .-__compcert_i64_smulh
+
diff --git a/runtime/powerpc/i64_stod.s b/runtime/powerpc/i64_stod.s
new file mode 100644
index 00000000..0c1ab720
--- /dev/null
+++ b/runtime/powerpc/i64_stod.s
@@ -0,0 +1,67 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+### Conversion from signed long to double float
+
+ .balign 16
+ .globl __compcert_i64_stod
+__compcert_i64_stod:
+ addi r1, r1, -16
+ lis r5, 0x4330
+ li r6, 0
+ stw r5, 0(r1)
+ stw r4, 4(r1) # 0(r1) = 2^52 + (double) XL
+ stw r5, 8(r1)
+ stw r6, 12(r1) # 8(r1) = 2^52
+ lfd f1, 0(r1)
+ lfd f2, 8(r1)
+ fsub f1, f1, f2 # f1 is XL (unsigned) as a double
+ lis r5, 0x4530
+ lis r6, 0x8000
+ stw r5, 0(r1) # 0(r1) = 2^84 + ((double)XH - 2^31) * 2^32
+ add r3, r3, r6
+ stw r3, 4(r1)
+ stw r5, 8(r1) # 8(r1) = 2^84 + 2^31 * 2^32
+ stw r6, 12(r1)
+ lfd f2, 0(r1)
+ lfd f3, 8(r1)
+ fsub f2, f2, f3 # f2 is XH (signed) * 2^32 as a double
+ fadd f1, f1, f2 # add both to get result
+ addi r1, r1, 16
+ blr
+ .type __compcert_i64_stod, @function
+ .size __compcert_i64_stod, .-__compcert_i64_stod
+
diff --git a/runtime/powerpc/i64_stof.s b/runtime/powerpc/i64_stof.s
new file mode 100644
index 00000000..ea23a1c8
--- /dev/null
+++ b/runtime/powerpc/i64_stof.s
@@ -0,0 +1,67 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from signed long to single float
+
+ .balign 16
+ .globl __compcert_i64_stof
+__compcert_i64_stof:
+ mflr r9
+ # Check whether -2^53 <= X < 2^53
+ srawi r5, r3, 21 # r5 = high 32 bits of X >> 53
+ # -2^53 <= X < 2^53 iff r5 is -1 or 0, that is, iff r5 + 1 is 0 or 1
+ addi r5, r5, 1
+ cmplwi r5, 2
+ blt 1f
+ # X is large enough that double rounding can occur.
+ # Avoid it by nudging X away from the points where double rounding
+ # occurs (the "round to odd" technique)
+ rlwinm r5, r4, 0, 21, 31 # extract bits 0 to 11 of X
+ addi r5, r5, 0x7FF # r5 = (X & 0x7FF) + 0x7FF
+ # bit 12 of r5 is 0 if all low 12 bits of X are 0, 1 otherwise
+ # bits 13-31 of r5 are 0
+ or r4, r4, r5 # correct bit number 12 of X
+ rlwinm r4, r4, 0, 0, 20 # set to 0 bits 0 to 11 of X
+ # Convert to double, then round to single
+1: bl __compcert_i64_stod
+ mtlr r9
+ frsp f1, f1
+ blr
+ .type __compcert_i64_stof, @function
+ .size __compcert_i64_stof, .-__compcert_i64_stof
+
diff --git a/runtime/powerpc/i64_udiv.s b/runtime/powerpc/i64_udiv.s
new file mode 100644
index 00000000..e2da855a
--- /dev/null
+++ b/runtime/powerpc/i64_udiv.s
@@ -0,0 +1,54 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Unsigned division
+
+ .balign 16
+ .globl __compcert_i64_udiv
+__compcert_i64_udiv:
+ mflr r0
+ stw r0, 4(r1) # save return address in caller's frame
+ bl __compcert_i64_udivmod # unsigned divide
+ lwz r0, 4(r1)
+ mtlr r0 # restore return address
+ mr r3, r5 # result = quotient
+ mr r4, r6
+ blr
+ .type __compcert_i64_udiv, @function
+ .size __compcert_i64_udiv, .-__compcert_i64_udiv
+
diff --git a/runtime/powerpc/i64_udivmod.s b/runtime/powerpc/i64_udivmod.s
new file mode 100644
index 00000000..e81c6cef
--- /dev/null
+++ b/runtime/powerpc/i64_udivmod.s
@@ -0,0 +1,234 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+# Unsigned division and modulus
+
+# This function computes both the quotient and the remainder of two
+# unsigned 64-bit integers.
+
+# Input: numerator N in (r3,r4), divisor D in (r5,r6)
+# Output: quotient Q in (r5,r6), remainder R in (r3,r4)
+# Destroys: all integer caller-save registers
+
+ .globl __compcert_i64_udivmod
+ .balign 16
+__compcert_i64_udivmod:
+ cmplwi r5, 0 # DH == 0 ?
+ stwu r1, -32(r1)
+ mflr r0
+ stw r0, 8(r1)
+ stw r31, 12(r1)
+ beq 1f
+# The general case
+ stw r30, 16(r1)
+ stw r29, 20(r1)
+ stw r28, 24(r1)
+ mr r28, r3 # Save N in (r28, r29)
+ mr r29, r4
+ mr r30, r5 # Save D in (r30, r31)
+ mr r31, r6
+ # Scale N and D down, giving N' and D', such that 2^31 <= D' < 2^32
+ cntlzw r7, r5 # r7 = leading zeros in DH = 32 - shift amount
+ subfic r8, r7, 32 # r8 = shift amount
+ slw r0, r3, r7 # N' = N >> shift amount
+ srw r3, r3, r8
+ srw r4, r4, r8
+ or r4, r4, r0
+ slw r0, r5, r7 # D' = D >> shift amount
+ srw r6, r6, r8
+ or r5, r6, r0
+ # Divide N' by D' to get an approximate quotient Q
+ bl __compcert_i64_udiv6432 # r3 = quotient, r4 = remainder
+ mr r6, r3 # low half of quotient Q
+ li r5, 0 # high half of quotient is 0
+ # Tentative quotient is either correct or one too high
+ # Compute Q * D in (r7, r8)
+4: mullw r7, r6, r30 # r7 = Q * DH
+ mullw r8, r6, r31 # r8 = low 32 bits of Q * DL
+ mulhwu r0, r6, r31 # r0 = high 32 bits of Q * DL
+ addc r7, r7, r0
+ subfe. r0, r0, r0 # test carry: EQ iff carry
+ beq 2f # handle overflow case
+ # Compute R = N - Q * D, with borrow
+ subfc r4, r8, r29
+ subfe r3, r7, r28
+ subfe. r0, r0, r0 # test borrow: EQ iff no borrow
+ beq 3f # no borrow: N >= Q * D, we are good
+ addi r6, r6, -1 # borrow: adjust Q down by 1
+ addc r4, r4, r31 # and R up by D
+ adde r3, r3, r30
+ # Finished
+3: lwz r0, 8(r1)
+ mtlr r0
+ lwz r31, 12(r1)
+ lwz r30, 16(r1)
+ lwz r29, 20(r1)
+ lwz r28, 24(r1)
+ addi r1, r1, 32
+ blr
+ # Special case when Q * D overflows
+2: addi r6, r6, -1 # adjust Q down by 1
+ b 4b # and redo computation and check of remainder
+ .balign 16
+# Special case 64 bits divided by 32 bits
+1: cmplwi r3, 0 # NH == 0?
+ beq 4f
+ divwu r31, r3, r6 # Divide NH by DL, quotient QH in r31
+ mullw r0, r31, r6
+ subf r3, r0, r3 # NH is remainder of this division
+ mr r5, r6
+ bl __compcert_i64_udiv6432 # divide NH : NL by DL
+ mr r5, r31 # high word of quotient
+ mr r6, r3 # low word of quotient
+ # r4 contains low word of remainder
+ li r3, 0 # high word of remainder = 0
+ lwz r0, 8(r1)
+ mtlr r0
+ lwz r31, 12(r1)
+ addi r1, r1, 32
+ blr
+ .balign 16
+# Special case 32 bits divided by 32 bits
+4: mr r0, r6
+ divwu r6, r4, r6 # low word of quotient
+ li r5, 0 # high word of quotient is 0
+ mullw r0, r6, r0
+ subf r4, r0, r4 # low word of remainder
+ li r3, 0 # high word of remainder is 0
+ addi r1, r1, 32
+ blr
+
+ .type __compcert_i64_udivmod, @function
+ .size __compcert_i64_udivmod, .-__compcert_i64_udivmod
+
+# Auxiliary division function: 64 bit integer divided by 32 bit integer
+# Not exported
+# Input: numerator N in (r3,r4), divisor D in r5
+# Output: quotient Q in r3, remainder R in r4
+# Destroys: all integer caller-save registers
+# Assumes: high word of N is less than D
+
+ .balign 16
+__compcert_i64_udiv6432:
+# Algorithm 9.3 from Hacker's Delight, section 9.4
+# Initially: u1 in r3, u0 in r4, v in r5
+# s = __builtin_clz(v);
+ cntlzw r6, r5 # s in r6
+# v = v << s;
+ slw r5, r5, r6
+# vn1 = v >> 16; # vn1 in r7
+ srwi r7, r5, 16
+# vn0 = v & 0xFFFF; # vn0 in r8
+ rlwinm r8, r5, 0, 16, 31
+# un32 = (u1 << s) | (u0 >> 32 - s);
+ subfic r0, r6, 32
+ srw r0, r4, r0
+ slw r3, r3, r6 # u1 dies, un32 in r3
+ or r3, r3, r0
+# un10 = u0 << s;
+ slw r4, r4, r6 # u0 dies, un10 in r4
+# un1 = un10 >> 16;
+ srwi r9, r4, 16 # un1 in r9
+# un0 = un10 & 0xFFFF;
+ rlwinm r4, r4, 0, 16, 31 # un10 dies, un0 in r4
+# q1 = un32/vn1;
+ divwu r10, r3, r7 # q in r10
+# rhat = un32 - q1*vn1;
+ mullw r0, r10, r7
+ subf r11, r0, r3 # rhat in r11
+# again1:
+1:
+# if (q1 >= b || q1*vn0 > b*rhat + un1) {
+ cmplwi r10, 0xFFFF
+ bgt 2f
+ mullw r0, r10, r8
+ slwi r12, r11, 16
+ add r12, r12, r9
+ cmplw r0, r12
+ ble 3f
+2:
+# q1 = q1 - 1;
+ addi r10, r10, -1
+# rhat = rhat + vn1;
+ add r11, r11, r7
+# if (rhat < b) goto again1;}
+ cmplwi r11, 0xFFFF
+ ble 1b
+3:
+# un21 = un32*b + un1 - q1*v;
+ slwi r0, r3, 16 # un32 dies
+ add r9, r0, r9 # un1 dies
+ mullw r0, r10, r5
+ subf r9, r0, r9 # un21 in r9
+# q0 = un21/vn1;
+ divwu r3, r9, r7 # q0 in r3
+# rhat = un21 - q0*vn1;
+ mullw r0, r3, r7
+ subf r11, r0, r9 # rhat in r11
+# again2:
+4:
+# if (q0 >= b || q0*vn0 > b*rhat + un0) {
+ cmplwi r3, 0xFFFF
+ bgt 5f
+ mullw r0, r3, r8
+ slwi r12, r11, 16
+ add r12, r12, r4
+ cmplw r0, r12
+ ble 6f
+5:
+# q0 = q0 - 1;
+ addi r3, r3, -1
+# rhat = rhat + vn1;
+ add r11, r11, r7
+# if (rhat < b) goto again2;}
+ cmplwi r11, 0xFFFF
+ ble 4b
+6:
+# remainder = (un21*b + un0 - q0*v) >> s;
+ slwi r0, r9, 16
+ add r4, r0, r4 # un0 dies, remainder in r4
+ mullw r0, r3, r5
+ subf r4, r0, r4
+ srw r4, r4, r6
+# quotient = q1*b + q0;
+ slwi r0, r10, 16
+ add r3, r0, r3
+ blr
+
+ .type __compcert_i64_udiv6432, @function
+ .size __compcert_i64_udiv6432,.-__compcert_i64_udiv6432
diff --git a/runtime/powerpc/i64_umod.s b/runtime/powerpc/i64_umod.s
new file mode 100644
index 00000000..bf8d6121
--- /dev/null
+++ b/runtime/powerpc/i64_umod.s
@@ -0,0 +1,47 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Unsigned modulus
+
+ .balign 16
+ .globl __compcert_i64_umod
+__compcert_i64_umod:
+ b __compcert_i64_udivmod
+ .type __compcert_i64_umod, @function
+ .size __compcert_i64_umod, .-__compcert_i64_umod
+
diff --git a/runtime/powerpc/i64_umulh.s b/runtime/powerpc/i64_umulh.s
new file mode 100644
index 00000000..53b72948
--- /dev/null
+++ b/runtime/powerpc/i64_umulh.s
@@ -0,0 +1,65 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris
+#
+# Copyright (c) 2016 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Unsigned multiply-high
+
+# X * Y = 2^64 XH.YH + 2^32 (XH.YL + XL.YH) + XL.YL
+
+ .balign 16
+ .globl __compcert_i64_umulh
+__compcert_i64_umulh:
+# r7:r8:r9 accumulate bits 127:32 of the full product
+ mulhwu r9, r4, r6 # r9 = high half of XL.YL
+ mullw r0, r4, r5 # r0 = low half of XL.YH
+ addc r9, r9, r0
+ mulhwu r0, r4, r5 # r0 = high half of XL.YH
+ addze r8, r0
+ mullw r0, r3, r6 # r0 = low half of XH.YL
+ addc r9, r9, r0
+ mulhwu r0, r3, r6 # r0 = high half of XH.YL
+ adde r8, r8, r0
+ li r7, 0
+ addze r7, r7
+ mullw r0, r3, r5 # r0 = low half of XH.YH
+ addc r4, r8, r0
+ mulhwu r0, r3, r5 # r0 = high half of XH.YH
+ adde r3, r7, r0
+ blr
+ .type __compcert_i64_umulh, @function
+ .size __compcert_i64_umulh, .-__compcert_i64_umulh
+
diff --git a/runtime/powerpc/i64_utod.s b/runtime/powerpc/i64_utod.s
new file mode 100644
index 00000000..69de6fdb
--- /dev/null
+++ b/runtime/powerpc/i64_utod.s
@@ -0,0 +1,66 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from unsigned long to double float
+
+ .balign 16
+ .globl __compcert_i64_utod
+__compcert_i64_utod:
+ addi r1, r1, -16
+ lis r5, 0x4330
+ li r6, 0
+ stw r5, 0(r1)
+ stw r4, 4(r1) # 0(r1) = 2^52 + (double) XL
+ stw r5, 8(r1)
+ stw r6, 12(r1) # 8(r1) = 2^52
+ lfd f1, 0(r1)
+ lfd f2, 8(r1)
+ fsub f1, f1, f2 # f1 is (double) XL
+ lis r5, 0x4530
+ stw r5, 0(r1) # 0(r1) = 2^84 + (double) XH * 2^32
+ stw r3, 4(r1)
+ stw r5, 8(r1) # 8(r1) = 2^84
+ lfd f2, 0(r1)
+ lfd f3, 8(r1)
+ fsub f2, f2, f3 # f2 is XH * 2^32 as a double
+ fadd f1, f1, f2 # add both to get result
+ addi r1, r1, 16
+ blr
+ .type __compcert_i64_utod, @function
+ .size __compcert_i64_utod, .-__compcert_i64_utod
+
diff --git a/runtime/powerpc/i64_utof.s b/runtime/powerpc/i64_utof.s
new file mode 100644
index 00000000..4a2a172b
--- /dev/null
+++ b/runtime/powerpc/i64_utof.s
@@ -0,0 +1,64 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from unsigned long to single float
+
+ .balign 16
+ .globl __compcert_i64_utof
+__compcert_i64_utof:
+ mflr r9
+ # Check whether X < 2^53
+ andis. r0, r3, 0xFFE0 # test bits 53...63 of X
+ beq 1f
+ # X is large enough that double rounding can occur.
+ # Avoid it by nudging X away from the points where double rounding
+ # occurs (the "round to odd" technique)
+ rlwinm r5, r4, 0, 21, 31 # extract bits 0 to 11 of X
+ addi r5, r5, 0x7FF # r5 = (X & 0x7FF) + 0x7FF
+ # bit 12 of r5 is 0 if all low 12 bits of X are 0, 1 otherwise
+ # bits 13-31 of r5 are 0
+ or r4, r4, r5 # correct bit number 12 of X
+ rlwinm r4, r4, 0, 0, 20 # set to 0 bits 0 to 11 of X
+ # Convert to double, then round to single
+1: bl __compcert_i64_utod
+ mtlr r9
+ frsp f1, f1
+ blr
+ .type __compcert_i64_utof, @function
+ .size __compcert_i64_utof, .-__compcert_i64_utof
+
diff --git a/runtime/powerpc/vararg.s b/runtime/powerpc/vararg.s
new file mode 100644
index 00000000..8d7e62c8
--- /dev/null
+++ b/runtime/powerpc/vararg.s
@@ -0,0 +1,163 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for variadic functions <stdarg.h>. IA32 version
+
+# typedef struct {
+# unsigned char ireg; // index of next integer register
+# unsigned char freg; // index of next FP register
+# char * stk; // pointer to next argument in stack
+# struct {
+# int iregs[8];
+# double fregs[8];
+# } * regs; // pointer to saved register area
+# } va_list[1];
+#
+# unsigned int __compcert_va_int32(va_list ap);
+# unsigned long long __compcert_va_int64(va_list ap);
+# double __compcert_va_float64(va_list ap);
+
+ .text
+
+ .balign 16
+ .globl __compcert_va_int32
+__compcert_va_int32:
+ # r3 = ap = address of va_list structure
+ lbz r4, 0(r3) # r4 = ap->ireg = next integer register
+ cmplwi r4, 8
+ bge 1f
+ # Next argument was passed in an integer register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ rlwinm r6, r4, 2, 0, 29 # r6 = r4 * 4
+ addi r4, r4, 1 # increment ap->ireg
+ stb r4, 0(r3)
+ lwzx r3, r5, r6 # load argument in r3
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ addi r5, r5, 4 # advance ap->stk by 4
+ stw r5, 4(r3)
+ lwz r3, -4(r5) # load argument in r3
+ blr
+ .type __compcert_va_int32, @function
+ .size __compcert_va_int32, .-__compcert_va_int32
+
+ .balign 16
+ .globl __compcert_va_int64
+__compcert_va_int64:
+ # r3 = ap = address of va_list structure
+ lbz r4, 0(r3) # r4 = ap->ireg = next integer register
+ cmplwi r4, 7
+ bge 1f
+ # Next argument was passed in two consecutive integer register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ addi r4, r4, 3 # round r4 up to an even number and add 2
+ rlwinm r4, r4, 0, 0, 30
+ rlwinm r6, r4, 2, 0, 29 # r6 = r4 * 4
+ add r5, r5, r6 # r5 = address of argument + 8
+ stb r4, 0(r3) # update ap->ireg
+ lwz r3, -8(r5) # load argument in r3:r4
+ lwz r4, -4(r5)
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ li r4, 8
+ stb r4, 0(r3) # set ap->ireg = 8 so that no ireg is left
+ addi r5, r5, 15 # round r5 to a multiple of 8 and add 8
+ rlwinm r5, r5, 0, 0, 28
+ stw r5, 4(r3) # update ap->stk
+ lwz r3, -8(r5) # load argument in r3:r4
+ lwz r4, -4(r5)
+ blr
+ .type __compcert_va_int64, @function
+ .size __compcert_va_int64, .-__compcert_va_int64
+
+ .balign 16
+ .globl __compcert_va_float64
+__compcert_va_float64:
+ # r3 = ap = address of va_list structure
+ lbz r4, 1(r3) # r4 = ap->freg = next float register
+ cmplwi r4, 8
+ bge 1f
+ # Next argument was passed in a FP register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ rlwinm r6, r4, 3, 0, 28 # r6 = r4 * 8
+ add r5, r5, r6
+ lfd f1, 32(r5) # load argument in f1
+ addi r4, r4, 1 # increment ap->freg
+ stb r4, 1(r3)
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ addi r5, r5, 15 # round r5 to a multiple of 8 and add 8
+ rlwinm r5, r5, 0, 0, 28
+ lfd f1, -8(r5) # load argument in f1
+ stw r5, 4(r3) # update ap->stk
+ blr
+ .type __compcert_va_float64, @function
+ .size __compcert_va_float64, .-__compcert_va_int64
+
+ .balign 16
+ .globl __compcert_va_composite
+__compcert_va_composite:
+ b __compcert_va_int32
+ .type __compcert_va_composite, @function
+ .size __compcert_va_composite, .-__compcert_va_composite
+
+# Save integer and FP registers at beginning of vararg function
+
+ .balign 16
+ .globl __compcert_va_saveregs
+__compcert_va_saveregs:
+ lwz r11, 0(r1) # r11 point to top of our frame
+ stwu r3, -96(r11) # register save area is 96 bytes below
+ stw r4, 4(r11)
+ stw r5, 8(r11)
+ stw r6, 12(r11)
+ stw r7, 16(r11)
+ stw r8, 20(r11)
+ stw r9, 24(r11)
+ stw r10, 28(r11)
+ bf 6, 1f # don't save FP regs if CR6 bit is clear
+ stfd f1, 32(r11)
+ stfd f2, 40(r11)
+ stfd f3, 48(r11)
+ stfd f4, 56(r11)
+ stfd f5, 64(r11)
+ stfd f6, 72(r11)
+ stfd f7, 80(r11)
+ stfd f8, 88(r11)
+1: blr
+ .type __compcert_va_saveregs, @function
+ .size __compcert_va_saveregs, .-__compcert_va_saveregs
diff --git a/runtime/powerpc64/i64_dtou.s b/runtime/powerpc64/i64_dtou.s
new file mode 100644
index 00000000..e58bcfaf
--- /dev/null
+++ b/runtime/powerpc64/i64_dtou.s
@@ -0,0 +1,66 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC 64 version.
+
+ .text
+
+### Conversion from double float to unsigned long
+
+ .balign 16
+ .globl __compcert_i64_dtou
+__compcert_i64_dtou:
+ lis r0, 0x5f00 # 0x5f00_0000 = 2^63 in binary32 format
+ stwu r0, -16(r1)
+ lfs f2, 0(r1) # f2 = 2^63
+ fcmpu cr0, f1, f2 # crbit 0 is f1 < f2
+ bf 0, 1f # branch if f1 >= 2^63 (or f1 is NaN)
+ fctidz f1, f1 # convert as signed
+ stfd f1, 0(r1)
+ lwz r3, 0(r1)
+ lwz r4, 4(r1)
+ addi r1, r1, 16
+ blr
+1: fsub f1, f1, f2 # shift argument down by 2^63
+ fctidz f1, f1 # convert as signed
+ stfd f1, 0(r1)
+ lwz r3, 0(r1)
+ lwz r4, 4(r1)
+ addis r3, r3, 0x8000 # shift result up by 2^63
+ addi r1, r1, 16
+ blr
+ .type __compcert_i64_dtou, @function
+ .size __compcert_i64_dtou, .-__compcert_i64_dtou
+
+
diff --git a/runtime/powerpc64/i64_stof.s b/runtime/powerpc64/i64_stof.s
new file mode 100644
index 00000000..779cbc18
--- /dev/null
+++ b/runtime/powerpc64/i64_stof.s
@@ -0,0 +1,68 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC 64 version.
+
+ .text
+
+### Conversion from signed long to single float
+
+ .balign 16
+ .globl __compcert_i64_stof
+__compcert_i64_stof:
+ rldimi r4, r3, 32, 0 # reassemble (r3,r4) as a 64-bit integer in r4
+ # Check whether -2^53 <= X < 2^53
+ sradi r5, r4, 53
+ addi r5, r5, 1
+ cmpldi r5, 2
+ blt 1f
+ # X is large enough that double rounding can occur.
+ # Avoid it by nudging X away from the points where double rounding
+ # occurs (the "round to odd" technique)
+ rldicl r5, r4, 0, 53 # extract bits 0 to 11 of X
+ addi r5, r5, 0x7FF # r5 = (X & 0x7FF) + 0x7FF
+ # bit 12 of r5 is 0 if all low 12 bits of X are 0, 1 otherwise
+ # bits 13-63 of r5 are 0
+ or r4, r4, r5 # correct bit number 12 of X
+ rldicr r4, r4, 0, 52 # set to 0 bits 0 to 11 of X
+ # Convert to double, then round to single
+1: stdu r4, -16(r1)
+ lfd f1, 0(r1)
+ fcfid f1, f1
+ frsp f1, f1
+ addi r1, r1, 16
+ blr
+ .type __compcert_i64_stof, @function
+ .size __compcert_i64_stof, .-__compcert_i64_stof
+
diff --git a/runtime/powerpc64/i64_utod.s b/runtime/powerpc64/i64_utod.s
new file mode 100644
index 00000000..491ee26b
--- /dev/null
+++ b/runtime/powerpc64/i64_utod.s
@@ -0,0 +1,79 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC 64 version.
+
+ .text
+
+### Conversion from unsigned long to double float
+
+ .balign 16
+ .globl __compcert_i64_utod
+__compcert_i64_utod:
+ rldicl r3, r3, 0, 32 # clear top 32 bits
+ rldicl r4, r4, 0, 32 # clear top 32 bits
+ lis r5, 0x4f80 # 0x4f80_0000 = 2^32 in binary32 format
+ stdu r3, -32(r1)
+ std r4, 8(r1)
+ stw r5, 16(r1)
+ lfd f1, 0(r1) # high 32 bits of argument
+ lfd f2, 8(r1) # low 32 bits of argument
+ lfs f3, 16(r1) # 2^32
+ fcfid f1, f1 # convert both 32-bit halves to FP (exactly)
+ fcfid f2, f2
+ fmadd f1, f1, f3, f2 # compute hi * 2^32 + lo
+ addi r1, r1, 32
+ blr
+ .type __compcert_i64_utod, @function
+ .size __compcert_i64_utod, .-__compcert_i64_utod
+
+# Alternate implementation using round-to-odd:
+# rldimi r4, r3, 32, 0 # reassemble (r3,r4) as a 64-bit integer in r4
+# cmpdi r4, 0 # is r4 >= 2^63 ?
+# blt 1f
+# stdu r4, -16(r1) # r4 < 2^63: convert as signed
+# lfd f1, 0(r1)
+# fcfid f1, f1
+# addi r1, r1, 16
+# blr
+#1: rldicl r0, r4, 0, 63 # extract low bit of r4
+# srdi r4, r4, 1
+# or r4, r4, r0 # round r4 to 63 bits, using round-to-odd
+# stdu r4, -16(r1) # convert to binary64
+# lfd f1, 0(r1)
+# fcfid f1, f1
+# fadd f1, f1, f1 # multiply result by 2
+# addi r1, r1, 16
+# blr
+ \ No newline at end of file
diff --git a/runtime/powerpc64/i64_utof.s b/runtime/powerpc64/i64_utof.s
new file mode 100644
index 00000000..4a2a172b
--- /dev/null
+++ b/runtime/powerpc64/i64_utof.s
@@ -0,0 +1,64 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for 64-bit integer arithmetic. PowerPC version.
+
+ .text
+
+### Conversion from unsigned long to single float
+
+ .balign 16
+ .globl __compcert_i64_utof
+__compcert_i64_utof:
+ mflr r9
+ # Check whether X < 2^53
+ andis. r0, r3, 0xFFE0 # test bits 53...63 of X
+ beq 1f
+ # X is large enough that double rounding can occur.
+ # Avoid it by nudging X away from the points where double rounding
+ # occurs (the "round to odd" technique)
+ rlwinm r5, r4, 0, 21, 31 # extract bits 0 to 11 of X
+ addi r5, r5, 0x7FF # r5 = (X & 0x7FF) + 0x7FF
+ # bit 12 of r5 is 0 if all low 12 bits of X are 0, 1 otherwise
+ # bits 13-31 of r5 are 0
+ or r4, r4, r5 # correct bit number 12 of X
+ rlwinm r4, r4, 0, 0, 20 # set to 0 bits 0 to 11 of X
+ # Convert to double, then round to single
+1: bl __compcert_i64_utod
+ mtlr r9
+ frsp f1, f1
+ blr
+ .type __compcert_i64_utof, @function
+ .size __compcert_i64_utof, .-__compcert_i64_utof
+
diff --git a/runtime/powerpc64/vararg.s b/runtime/powerpc64/vararg.s
new file mode 100644
index 00000000..8d7e62c8
--- /dev/null
+++ b/runtime/powerpc64/vararg.s
@@ -0,0 +1,163 @@
+# *****************************************************************
+#
+# The Compcert verified compiler
+#
+# Xavier Leroy, INRIA Paris-Rocquencourt
+#
+# Copyright (c) 2013 Institut National de Recherche en Informatique et
+# en Automatique.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the <organization> nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
+# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# *********************************************************************
+
+# Helper functions for variadic functions <stdarg.h>. IA32 version
+
+# typedef struct {
+# unsigned char ireg; // index of next integer register
+# unsigned char freg; // index of next FP register
+# char * stk; // pointer to next argument in stack
+# struct {
+# int iregs[8];
+# double fregs[8];
+# } * regs; // pointer to saved register area
+# } va_list[1];
+#
+# unsigned int __compcert_va_int32(va_list ap);
+# unsigned long long __compcert_va_int64(va_list ap);
+# double __compcert_va_float64(va_list ap);
+
+ .text
+
+ .balign 16
+ .globl __compcert_va_int32
+__compcert_va_int32:
+ # r3 = ap = address of va_list structure
+ lbz r4, 0(r3) # r4 = ap->ireg = next integer register
+ cmplwi r4, 8
+ bge 1f
+ # Next argument was passed in an integer register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ rlwinm r6, r4, 2, 0, 29 # r6 = r4 * 4
+ addi r4, r4, 1 # increment ap->ireg
+ stb r4, 0(r3)
+ lwzx r3, r5, r6 # load argument in r3
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ addi r5, r5, 4 # advance ap->stk by 4
+ stw r5, 4(r3)
+ lwz r3, -4(r5) # load argument in r3
+ blr
+ .type __compcert_va_int32, @function
+ .size __compcert_va_int32, .-__compcert_va_int32
+
+ .balign 16
+ .globl __compcert_va_int64
+__compcert_va_int64:
+ # r3 = ap = address of va_list structure
+ lbz r4, 0(r3) # r4 = ap->ireg = next integer register
+ cmplwi r4, 7
+ bge 1f
+ # Next argument was passed in two consecutive integer register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ addi r4, r4, 3 # round r4 up to an even number and add 2
+ rlwinm r4, r4, 0, 0, 30
+ rlwinm r6, r4, 2, 0, 29 # r6 = r4 * 4
+ add r5, r5, r6 # r5 = address of argument + 8
+ stb r4, 0(r3) # update ap->ireg
+ lwz r3, -8(r5) # load argument in r3:r4
+ lwz r4, -4(r5)
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ li r4, 8
+ stb r4, 0(r3) # set ap->ireg = 8 so that no ireg is left
+ addi r5, r5, 15 # round r5 to a multiple of 8 and add 8
+ rlwinm r5, r5, 0, 0, 28
+ stw r5, 4(r3) # update ap->stk
+ lwz r3, -8(r5) # load argument in r3:r4
+ lwz r4, -4(r5)
+ blr
+ .type __compcert_va_int64, @function
+ .size __compcert_va_int64, .-__compcert_va_int64
+
+ .balign 16
+ .globl __compcert_va_float64
+__compcert_va_float64:
+ # r3 = ap = address of va_list structure
+ lbz r4, 1(r3) # r4 = ap->freg = next float register
+ cmplwi r4, 8
+ bge 1f
+ # Next argument was passed in a FP register
+ lwz r5, 8(r3) # r5 = ap->regs = base of saved register area
+ rlwinm r6, r4, 3, 0, 28 # r6 = r4 * 8
+ add r5, r5, r6
+ lfd f1, 32(r5) # load argument in f1
+ addi r4, r4, 1 # increment ap->freg
+ stb r4, 1(r3)
+ blr
+ # Next argument was passed on stack
+1: lwz r5, 4(r3) # r5 = ap->stk = next argument passed on stack
+ addi r5, r5, 15 # round r5 to a multiple of 8 and add 8
+ rlwinm r5, r5, 0, 0, 28
+ lfd f1, -8(r5) # load argument in f1
+ stw r5, 4(r3) # update ap->stk
+ blr
+ .type __compcert_va_float64, @function
+ .size __compcert_va_float64, .-__compcert_va_int64
+
+ .balign 16
+ .globl __compcert_va_composite
+__compcert_va_composite:
+ b __compcert_va_int32
+ .type __compcert_va_composite, @function
+ .size __compcert_va_composite, .-__compcert_va_composite
+
+# Save integer and FP registers at beginning of vararg function
+
+ .balign 16
+ .globl __compcert_va_saveregs
+__compcert_va_saveregs:
+ lwz r11, 0(r1) # r11 point to top of our frame
+ stwu r3, -96(r11) # register save area is 96 bytes below
+ stw r4, 4(r11)
+ stw r5, 8(r11)
+ stw r6, 12(r11)
+ stw r7, 16(r11)
+ stw r8, 20(r11)
+ stw r9, 24(r11)
+ stw r10, 28(r11)
+ bf 6, 1f # don't save FP regs if CR6 bit is clear
+ stfd f1, 32(r11)
+ stfd f2, 40(r11)
+ stfd f3, 48(r11)
+ stfd f4, 56(r11)
+ stfd f5, 64(r11)
+ stfd f6, 72(r11)
+ stfd f7, 80(r11)
+ stfd f8, 88(r11)
+1: blr
+ .type __compcert_va_saveregs, @function
+ .size __compcert_va_saveregs, .-__compcert_va_saveregs
diff --git a/test/Makefile b/test/Makefile
index 7efcd8f1..e9c5d6a1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -4,7 +4,9 @@ include ../Makefile.config
# Kalray note - removing compression, raytracer and spass that cannot be executed by the simulator in reasonable time
ifeq ($(ARCH),mppa_k1c)
- DIRS:=c regression
+ DIRS=c regression
+else
+ DIRS=c compression raytracer spass regression
endif
ifeq ($(CLIGHTGEN),true)
diff --git a/test/c/mandelbrot.c b/test/c/mandelbrot.c
index fb8b929c..548c3ffa 100644
--- a/test/c/mandelbrot.c
+++ b/test/c/mandelbrot.c
@@ -59,7 +59,6 @@ int main (int argc, char **argv)
if(bit_num == 8)
{
- printf("%c", byte_acc);
putc(byte_acc,stdout);
#ifdef __K1C__ // stdout isn't flushed enough when --syscall=libstd_scalls.so is passed to the simulator k1-cluster
fflush(stdout);
@@ -70,7 +69,6 @@ int main (int argc, char **argv)
else if(x == w-1)
{
byte_acc <<= (8-w%8);
- printf("%c", byte_acc);
putc(byte_acc,stdout);
#ifdef __K1C__ // stdout isn't flushed enough when --syscall=libstd_scalls.so is passed to the simulator k1-cluster
fflush(stdout);
diff --git a/test/clightgen/issue319.c b/test/clightgen/issue319.c
new file mode 100644
index 00000000..be9f3f7e
--- /dev/null
+++ b/test/clightgen/issue319.c
@@ -0,0 +1,12 @@
+/* Dollar signs in identifiers */
+
+int c$d = 42;
+
+int a$b(int x$$) {
+ return c$d + x$$;
+}
+
+int main(int argc, const char *argv[])
+{
+ return a$b(6);
+}
diff --git a/test/cse2/globals.c b/test/cse2/globals.c
new file mode 100644
index 00000000..c6dd59cd
--- /dev/null
+++ b/test/cse2/globals.c
@@ -0,0 +1,8 @@
+int glob1, glob2;
+
+void toto() {
+ if (glob1 > 4) {
+ glob2 ++;
+ glob1 --;
+ }
+}
diff --git a/test/cse2/indexed_addr.c b/test/cse2/indexed_addr.c
new file mode 100644
index 00000000..30a7c571
--- /dev/null
+++ b/test/cse2/indexed_addr.c
@@ -0,0 +1,6 @@
+void foo(int *t) {
+ if (t[0] > 4) {
+ t[1] ++;
+ t[0] --;
+ }
+}
diff --git a/test/monniaux/README.md b/test/monniaux/README.md
index f2af67fb..14b062da 100644
--- a/test/monniaux/README.md
+++ b/test/monniaux/README.md
@@ -1,13 +1,18 @@
-# Benchmarking CompCert and GCC
+# Benchmarking `CompCert` and GCC
-rules.mk contains generic rules to compile with gcc and ccomp, with different
-optimizations, and producing different binaries. It also produces a
-measures.csv file containing the different timings given by the bench.
+## Compiling `CompCert`
-Up to 5 different optimizations can be used.
+The first step to benchmark `CompCert` is to compile it - the `INSTALL.md` instructions of the project root folder should guide you on installing it.
-To use this rule.mk, create a folder, put inside all the .c/.h source files,
-and write a Makefile ressembling:
+For the benchmarks to work, the compiler `ccomp` should be on your `$PATH`, with the runtime libraries installed correctly (with a successful `make install` on the project root directory).
+
+## Using the harness
+
+`rules.mk` contains generic rules to compile with `gcc` and `ccomp`, with different optimizations, and producing different binaries. It also produces a `measures.csv` file containing the different timings given by the bench.
+
+Up to 5 different sets of optimizations per compiler can be used.
+
+To use this `rules.mk`, create a folder, put inside all the .c/.h source files, and write a Makefile resembling:
```make
TARGET=float_mat
MEASURES="c1 c2 c3 c4 c5 c6 c7 c8"
@@ -15,64 +20,88 @@ MEASURES="c1 c2 c3 c4 c5 c6 c7 c8"
include ../rules.mk
```
-This is all that is required to write, the rules.mk handles everything.
+This is all that is required to write, the `rules.mk` handles everything.
-There is the possibility to define some variables to finetune what you want.
-For instance, `ALL_CFILES` describes the .c source files whose objects are
-to be linked.
+There is the possibility to define some variables to fine tune what you want. For instance, `ALL_CFILES` describes the .c source files whose objects are to be linked.
Here is an exhaustive list of the variables:
- `TARGET`: name of the binary to produce
- `MEASURES`: list of the different timings. This supposes that the program
-prints something of the form "c3 cycles: 44131" for instance. In the above
-example, the Makefile would generate such a line:
-```
-float_mat c3, 1504675, 751514, 553235, 1929369, 1372441
-```
+prints something of the form `c3 cycles: 44131`.
- `ALL_CFILES`: list of .c files to compile. By default, `$(wildcard *.c)`
-- `CLOCK`: basename of the clock file to compile. Default `../clock`
-- `ALL_CFLAGS`: cflags that are to be included for all compilers
+- `CLOCK`: `basename` of the clock file to compile. Default `../clock`
+- `ALL_CFLAGS`: `cflags` that are to be included for all compilers
- `ALL_GCCFLAGS`: same, but GCC specific
-- `ALL_CCOMPFLAGS`: same, but ccomp specific
-- `K1C_CC`: GCC compiler (default k1-cos-gcc)
-- `K1C_CCOMP`: compcert compiler (default ccomp)
-- `EXECUTE_CYCLES`: running command (default `k1-cluster` with some options)
-- `EXECUTE_ARGS`: execution arguments
-- `GCCiFLAGS` with i from 0 to 4: the wanted optimizations. If one of these flags is empty, nothing is done. Same for `CCOMPiFLAGS`. For now, the default values:
-```
-# You can define up to GCC4FLAGS and CCOMP4FLAGS
-GCC0FLAGS?=
-GCC1FLAGS?=$(ALL_GCCFLAGS) -O1
-GCC2FLAGS?=$(ALL_GCCFLAGS) -O2
-GCC3FLAGS?=$(ALL_GCCFLAGS) -O3
-GCC4FLAGS?=
-CCOMP0FLAGS?=
-CCOMP1FLAGS?=$(ALL_CCOMPFLAGS) -fno-postpass
-CCOMP2FLAGS?=$(ALL_CCOMPFLAGS)
-CCOMP3FLAGS?=
-CCOMP4FLAGS?=
-
-# Prefix names
-GCC0PREFIX?=
-GCC1PREFIX?=.gcc.o1
-GCC2PREFIX?=.gcc.o2
-GCC3PREFIX?=.gcc.o3
-GCC4PREFIX?=
-CCOMP0PREFIX?=
-CCOMP1PREFIX?=.ccomp.o1
-CCOMP2PREFIX?=.ccomp.o2
-CCOMP3PREFIX?=
-CCOMP4PREFIX?=
-```
+- `ALL_CCOMPFLAGS`: same, but `ccomp` specific
+- `K1C_CC`: GCC compiler (default `k1-cos-gcc`)
+- `K1C_CCOMP`: `CompCert` compiler (default `ccomp`)
+- `EXECUTE_CYCLES`: running command (default is `k1-cluster --syscall=libstd_scalls.so --cycle-based --`)
+- `EXECUTE_ARGS`: execution arguments. You can use a macro `__BASE__` which expands to the name of the binary being executed.
+- `GCCiFLAGS` with `i` from 0 to 4: the wanted optimizations. If one of these flags is empty, nothing is done. Same for `CCOMPiFLAGS`. Look at `rules.mk` to see the default values. You might find something like this:
+
+ # You can define up to GCC4FLAGS and CCOMP4FLAGS
+ GCC0FLAGS?=
+ GCC1FLAGS?=$(ALL_GCCFLAGS) -O1
+ GCC2FLAGS?=$(ALL_GCCFLAGS) -O2
+ GCC3FLAGS?=$(ALL_GCCFLAGS) -O3
+ GCC4FLAGS?=
+ CCOMP0FLAGS?=
+ CCOMP1FLAGS?=$(ALL_CCOMPFLAGS) -fno-postpass
+ CCOMP2FLAGS?=$(ALL_CCOMPFLAGS)
+ CCOMP3FLAGS?=
+ CCOMP4FLAGS?=
-The `PREFIX` are the prefixes to add to the .s, .o, etc.. You should be careful that if a FLAGS is set, then the according PREFIX should be set as well.
+ # Prefix names
+ GCC0PREFIX?=
+ GCC1PREFIX?=.gcc.o1
+ GCC2PREFIX?=.gcc.o2
+ GCC3PREFIX?=.gcc.o3
+ GCC4PREFIX?=
+ CCOMP0PREFIX?=
+ CCOMP1PREFIX?=.ccomp.o1
+ CCOMP2PREFIX?=.ccomp.o2
+ CCOMP3PREFIX?=
+ CCOMP4PREFIX?=
-Assembly files will be generated in `asm/`, objects in `obj/`, binaries in `bin/` and outputs in `out/`.
+The `PREFIX` are the prefixes to add to the secondary produced files (assembly, object, executable, ..). You should be careful that if a `FLAGS` is set, then the according `PREFIX` should be set as well.
-To compile and execute all the benches : `make` while in the `monniaux` directory (without any `-j` flag).
+Assembly files are generated in `asm/`, objects in `obj/`, binaries in `bin/` and outputs in `out/`.
+
+To compile and execute all the benches : `make` while in the `monniaux` directory (without any `-j` flag). Doing so will compile CompCert, install it, and then proceed to execute each bench.
To compile and/or execute a single bench, `cd` to the bench directory, then:
- `make` for compiling the bench
- `make run` for running it
-You can use `-j` flag when in a single bench directory
+You can use `-j` flag when in a single bench directory.
+
+## Individual scripts
+
+If you want to run the building and running scripts individually without having to use the `Makefile` from `test/monniaux`, you can run the `build_benches.sh` script which builds each bench using all the available cores on your machine.
+
+Once the benches are built, you can then run `run_benches.sh file.csv` where `file.csv` is where you want to store the timings of the benchmarks. `run_benches.sh` also uses all the available cores of your machine.
+
+## Adding timings to a benchmark
+
+If you just add a benchmark without any timing function, the resulting `measures.csv` file will be empty for lack of timing output.
+
+To add a timing, you must use the functions whose prototypes are in `clock.h`
+
+ #include "../clock.h"
+ /* ... */
+ clock_prepare();
+ /* ... */
+ clock_start();
+ /* .. computations .. */
+ clock_stop();
+ /* ... */
+ print_total_clock(); // print to stdout
+ printerr_total_clock(); // print to stderr
+
+If the benchmark doesn't use `stdout` in a binary way you can use `print_total_clock()`. However, some benchmarks like `jpeg-6b` print their binary content to `stdout`, which then messes up the `grep` command when attempting to use it to extract the cycles from `stdout`.
+
+The solution is then to use `printerr_total_clock()` which will print the cycles to `stderr`, and use `EXECUTE_ARGS` ressembling this:
+
+ EXECUTE_ARGS=-dct int -outfile __BASE__.jpg testimg.ppm 2> __BASE__.out
+
+`__BASE__` is a macro that gets expanded to the base name - that is, the `TARGET` concatenated with one of the `GCCiPREFIX` or `CCOMPiPREFIX`. For instance, in `jpeg-6b`, `__BASE__` could be `jpeg-6b.ccomp.o2`.
diff --git a/test/monniaux/build_benches.sh b/test/monniaux/build_benches.sh
index a749779d..01abf55d 100755
--- a/test/monniaux/build_benches.sh
+++ b/test/monniaux/build_benches.sh
@@ -2,6 +2,7 @@
TMPFILE=/tmp/1513times.txt
+cores=$(grep -c ^processor /proc/cpuinfo)
source benches.sh
default="\e[39m"
@@ -13,9 +14,9 @@ rm -f $TMPFILE
for bench in $benches; do
echo -e "${magenta}Building $bench..${default}"
if [ "$1" == "" ]; then
- (cd $bench && make -s -j20 > /dev/null &> /dev/null) || { echo -e "${red}Build failed" && break; }
+ (cd $bench && make -s -j$cores > /dev/null &> /dev/null) || { echo -e "${red}Build failed" && break; }
else
- (cd $bench && make -j20) | grep -P "\d+: \d+\.\d+" >> $TMPFILE
+ (cd $bench && make -j$cores) | grep -P "\d+: \d+\.\d+" >> $TMPFILE
fi
done
diff --git a/test/monniaux/clock.c b/test/monniaux/clock.c
index fb636667..4ec679f6 100644
--- a/test/monniaux/clock.c
+++ b/test/monniaux/clock.c
@@ -24,9 +24,9 @@ cycle_t get_current_cycle(void) {
}
void print_total_clock(void) {
- printf("time cycles: %lu\n", total_clock);
+ printf("time cycles: %" PRcycle "\n", total_clock);
}
void printerr_total_clock(void) {
- fprintf(stderr, "time cycles: %lu\n", total_clock);
+ fprintf(stderr, "time cycles: %" PRcycle "\n", total_clock);
}
diff --git a/test/monniaux/cse2/loopaccess.c b/test/monniaux/cse2/loopaccess.c
new file mode 100644
index 00000000..5ddaeb66
--- /dev/null
+++ b/test/monniaux/cse2/loopaccess.c
@@ -0,0 +1,7 @@
+double toto(double x, int count) {
+ double r = 5*x + 3;
+ while (count > r) {
+ count --;
+ }
+ return 5*x + 3;
+}
diff --git a/test/monniaux/cse2/loopinvariant.c b/test/monniaux/cse2/loopinvariant.c
new file mode 100644
index 00000000..64caf80b
--- /dev/null
+++ b/test/monniaux/cse2/loopinvariant.c
@@ -0,0 +1,7 @@
+int toto(int *t, int n) {
+ int x = t[0];
+ for(int i=1; i<n; i++) {
+ if (t[i] > t[0]) return i;
+ }
+ return 0;
+}
diff --git a/test/monniaux/cse2/loopload.c b/test/monniaux/cse2/loopload.c
new file mode 100644
index 00000000..6e0925f7
--- /dev/null
+++ b/test/monniaux/cse2/loopload.c
@@ -0,0 +1,5 @@
+int find_index(int *t, int n) {
+ if (t[0] > 0) return 3;
+ while (n > 0) n--;
+ return t[0];
+}
diff --git a/test/monniaux/cycles.h b/test/monniaux/cycles.h
index 21541145..c7dc582b 100644
--- a/test/monniaux/cycles.h
+++ b/test/monniaux/cycles.h
@@ -1,13 +1,11 @@
+#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
-typedef unsigned long cycle_t;
-
-#ifdef MAX_MEASURES
- static cycle_t _last_stop[MAX_MEASURES] = {0};
- static cycle_t _total_cycles[MAX_MEASURES] = {0};
-#endif
#ifdef __K1C__
+typedef uint64_t cycle_t;
+#define PRcycle PRId64
+
#include <../../k1-cos/include/hal/cos_registers.h>
static inline void cycle_count_config(void)
@@ -27,18 +25,57 @@ static inline cycle_t get_cycle(void)
#else // not K1C
static inline void cycle_count_config(void) { }
-#ifdef __x86_64__
+#if defined(__i386__) || defined( __x86_64__)
+#define PRcycle PRId64
+typedef uint64_t cycle_t;
#include <x86intrin.h>
static inline cycle_t get_cycle(void) { return __rdtsc(); }
#elif __riscv
+#ifdef __riscv32
+#define PRcycle PRId32
+typedef uint32_t cycle_t;
+#else
+#define PRcycle PRId64
+typedef uint64_t cycle_t;
+#endif
static inline cycle_t get_cycle(void) {
cycle_t cycles;
asm volatile ("rdcycle %0" : "=r" (cycles));
return cycles;
}
+#elif defined (__ARM_ARCH) && (__ARM_ARCH >= 6)
+#if (__ARM_ARCH < 8)
+typedef uint32_t cycle_t;
+#define PRcycle PRId32
+
+/* need this kernel module
+https://github.com/zertyz/MTL/tree/master/cpp/time/kernel/arm */
+static inline cycle_t get_cycle(void) {
+ cycle_t cycles;
+ __asm__ volatile ("mrc p15, 0, %0, c9, c13, 0":"=r" (cycles));
+ return cycles;
+}
#else
+#define PRcycle PRId64
+typedef uint64_t cycle_t;
+/* need this kernel module:
+https://github.com/jerinjacobk/armv8_pmu_cycle_counter_el0
+
+on 5+ kernels, remove first argument of access_ok macro */
+
+static inline cycle_t get_cycle(void)
+{
+ uint64_t val;
+ __asm__ volatile("mrs %0, pmccntr_el0" : "=r"(val));
+ return val;
+}
+#endif
+
+#else
+#define PRcycle PRId32
+typedef uint32_t cycle_t;
static inline cycle_t get_cycle(void) { return 0; }
#endif
#endif
@@ -48,3 +85,9 @@ static inline cycle_t get_cycle(void) { return 0; }
#define TIMESTOP(i) {cycle_t cur = get_cycle(); _total_cycles[i] += cur - _last_stop[i]; _last_stop[i] = cur;}
#define TIMEPRINT(n) { for (int i = 0; i <= n; i++) printf("%d cycles: %" PRIu64 "\n", i, _total_cycles[i]); }
#endif
+
+
+#ifdef MAX_MEASURES
+ static cycle_t _last_stop[MAX_MEASURES] = {0};
+ static cycle_t _total_cycles[MAX_MEASURES] = {0};
+#endif
diff --git a/test/monniaux/moves/array.c b/test/monniaux/moves/array.c
new file mode 100644
index 00000000..faa1d96b
--- /dev/null
+++ b/test/monniaux/moves/array.c
@@ -0,0 +1,18 @@
+void incr_double_array(double *t) {
+ double x0 = 1.0;
+ double t0 = t[0];
+ double x1 = 1.0;
+ double t1 = t[1];
+ double x2 = 1.0;
+ double t2 = t[2];
+ double x3 = 1.0;
+ double t3 = t[3];
+ t0 = t0 + x0;
+ t1 = t1 + x1;
+ t2 = t2 + x2;
+ t3 = t3 + x3;
+ t[0] = t0;
+ t[1] = t1;
+ t[2] = t2;
+ t[3] = t3;
+}
diff --git a/test/monniaux/quicksort/quicksort_run.c b/test/monniaux/quicksort/quicksort_run.c
index c35d0752..3c640b24 100644
--- a/test/monniaux/quicksort/quicksort_run.c
+++ b/test/monniaux/quicksort/quicksort_run.c
@@ -13,7 +13,7 @@ int main (void) {
quicksort(vec, len);
quicksort_time = get_cycle() - quicksort_time;
printf("sorted=%s\n"
- "time cycles:%" PRIu64 "\n",
+ "time cycles:%" PRcycle "\n",
data_vec_is_sorted(vec, len)?"true":"false",
quicksort_time);
free(vec);
diff --git a/test/monniaux/run_benches.sh b/test/monniaux/run_benches.sh
index 60eec865..2b2e28d6 100755
--- a/test/monniaux/run_benches.sh
+++ b/test/monniaux/run_benches.sh
@@ -1,13 +1,16 @@
source benches.sh
+cores=$(grep -c ^processor /proc/cpuinfo)
+processes=$((cores/4))
+
rm -f commands.txt
for bench in $benches; do
echo "(cd $bench && echo \"Running $bench..\" &&\
make -j4 run > /dev/null && echo \"$bench DONE\")" >> commands.txt
done
-cat commands.txt | xargs -n1 -I{} -P6 bash -c '{}'
+cat commands.txt | xargs -n1 -I{} -P$processes bash -c '{}'
##
# Gather all the CSV files
diff --git a/test/monniaux/yarpgen/Makefile b/test/monniaux/yarpgen/Makefile
index 9da82deb..28bd5ae0 100644
--- a/test/monniaux/yarpgen/Makefile
+++ b/test/monniaux/yarpgen/Makefile
@@ -1,52 +1,98 @@
-YARPGEN=yarpgen
-MAX=300
+TARGET_CCOMP=../../../ccomp
+TARGET_CC=gcc
+
+all:
+
+.SECONDARY:
+
+ifndef YARPGEN
+YARPGEN=./yarpgen
+GENERATOR=yarpgen
+endif
+
+ifdef BITS
+YARPGEN+=-m $(BITS)
+CFLAGS+=-m$(BITS)
+endif
+
+MAX=129
PREFIX=ran%06.f
-include ../rules.mk
-
-K1C_CCOMPFLAGS += -funprototyped -fbitfields
-CCOMPFLAGS += -funprototyped -fbitfields
-
-TARGETS_C=$(shell seq --format $(PREFIX)/func.c 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/driver.c 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/init.h 0 $(MAX))
-TARGETS_CCOMP_K1C_S=$(shell seq --format $(PREFIX)/func.ccomp.k1c.s 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/driver.ccomp.k1c.s 0 $(MAX))
-TARGETS_GCC_K1C_S=$(shell seq --format $(PREFIX)/func.gcc.k1c.s 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/driver.gcc.k1c.s 0 $(MAX))
-TARGETS_CCOMP_HOST_S=$(shell seq --format $(PREFIX)/func.ccomp.host.s 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/driver.ccomp.host.s 0 $(MAX))
-TARGETS_GCC_HOST_S=$(shell seq --format $(PREFIX)/func.gcc.host.s 0 $(MAX)) \
- $(shell seq --format $(PREFIX)/driver.gcc.host.s 0 $(MAX))
-TARGETS_CCOMP_K1C_OUT=$(shell seq --format $(PREFIX)/example.ccomp.k1c.out 0 $(MAX))
-TARGETS_GCC_K1C_OUT=$(shell seq --format $(PREFIX)/example.gcc.k1c.out 0 $(MAX))
-TARGETS_GCC_HOST_OUT=$(shell seq --format $(PREFIX)/example.gcc.host.out 0 $(MAX))
-TARGETS_CCOMP_HOST_OUT=$(shell seq --format $(PREFIX)/example.ccomp.host.out 0 $(MAX))
-TARGETS_CMP=$(shell seq --format $(PREFIX)/example.k1c.cmp 0 $(MAX))
-
-all: $(TARGETS_CCOMP_K1C_OUT) $(TARGETS_GCC_K1C_OUT) $(TARGETS_GCC_HOST_OUT) $(TARGETS_CCOMP_HOST_OUT) $(TARGETS_CCOMP_K1C_S) $(TARGETS_GCC_K1C_S) $(TARGETS_GCC_HOST_S) $(TARGETS_CCOMP_HOST_S) $(TARGETS_CMP) $(TARGETS_C)
-
-ran%/func.ccomp.k1c.s ran%/func.gcc.k1c.s ran%/func.ccomp.host.s ran%/func.gcc.host.s : ran%/init.h
-
-ran%/example.ccomp.k1c: ran%/func.ccomp.k1c.o ran%/driver.ccomp.k1c.o
- $(K1C_CCOMP) $(K1C_CCOMPFLAGS) $+ -o $@
-
-ran%/example.gcc.k1c: ran%/func.gcc.k1c.o ran%/driver.gcc.k1c.o
- $(K1C_CC) $(K1C_CFLAGS) $+ -o $@
-
-ran%/example.gcc.host: ran%/func.gcc.host.o ran%/driver.gcc.host.o
- $(CC) $(CFLAGS) $+ -o $@
-ran%/example.ccomp.host: ran%/func.ccomp.host.o ran%/driver.ccomp.host.o
- $(CCOMP) $(CCOMPFLAGS) $+ -o $@
+CCOMPOPTS=-static
+CCOMPFLAGS+=-funprototyped -fbitfields -fno-cse2 -stdlib ../../../runtime # FIXME
+
+TESTS_C=$(shell seq --format $(PREFIX)/func.c 1 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.c 1 $(MAX)) \
+ $(shell seq --format $(PREFIX)/init.c 1 $(MAX)) \
+ $(shell seq --format $(PREFIX)/hash.c 1 $(MAX)) \
+ $(shell seq --format $(PREFIX)/check.c 1 $(MAX)) \
+ $(shell seq --format $(PREFIX)/init.h 1 $(MAX))
+
+$(TESTS_C): $(GENERATOR)
+
+TESTS_CCOMP_TARGET_S=$(TEST_C:.c=.ccomp.target.s)
+TESTS_GCC_TARGET_S=$(TEST_C:.c=.gcc.target.s)
+TESTS_GCC_HOST_S=$(TEST_C:.c=.gcc.host.s)
+TESTS_CCOMP_TARGET_OUT=$(shell seq --format $(PREFIX)/example.ccomp.target.out 1 $(MAX))
+TESTS_GCC_TARGET_OUT=$(shell seq --format $(PREFIX)/example.gcc.target.out 1 $(MAX))
+TESTS_GCC_HOST_OUT=$(shell seq --format $(PREFIX)/example.gcc.host.out 1 $(MAX))
+TESTS_CMP=$(shell seq --format $(PREFIX)/example.target.cmp 1 $(MAX)) # $(shell seq --format $(PREFIX)/example.host_target.cmp 1 $(MAX))
+
+all: $(TESTS_CCOMP_TARGET_OUT) $(TESTS_GCC_TARGET_OUT) $(TESTS_CCOMP_TARGET_S) $(TESTS_GCC_TARGET_S) $(TESTS_CMP) $(TESTS_C)
+
+tests_c: $(TESTS_C)
+
+tests_s: $(TESTS_CCOMP_TARGET_S)
+
+%.ccomp.target.s : %.c
+ $(TARGET_CCOMP) $(CCOMPOPTS) $(CCOMPFLAGS) -S -o $@ $<
+
+%.gcc.target.s : %.c
+ $(TARGET_CC) $(CCOMPOPTS) -S -o $@ $<
-ran%/driver.c ran%/func.c ran%/init.h:
- -mkdir ran$*
+%.gcc.host.s : %.c
+ $(CC) $(CFLAGS) -S -o $@ $<
+
+%.target.o : %.target.s
+ $(TARGET_CC) -c -o $@ $<
+
+%.host.o : %.host.s
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.target.out : %.target
+ $(EXECUTE) $< | tee $@
+
+%.host.out : %.host
+ ./$< | tee $@
+
+ran%/func.ccomp.target.s ran%/func.gcc.target.s ran%/func.ccomp.host.s ran%/func.gcc.host.s ran%/init.gcc.host.s : ran%/init.h
+
+ran%/example.ccomp.target: ran%/func.ccomp.target.o ran%/driver.ccomp.target.o ran%/init.ccomp.target.o ran%/check.ccomp.target.o ran%/hash.ccomp.target.o
+ $(TARGET_CCOMP) $(CCOMPOPTS) $(CCOMPFLAGS) $+ -o $@
+
+ran%/example.gcc.target: ran%/func.gcc.target.o ran%/driver.gcc.target.o ran%/init.gcc.target.o ran%/check.gcc.target.o ran%/hash.gcc.target.o
+ $(TARGET_CC) $(TARGET_CFLAGS) $+ -o $@
+
+ran%/example.gcc.host: ran%/func.gcc.host.o ran%/driver.gcc.host.o ran%/init.gcc.host.o ran%/check.gcc.host.o ran%/hash.gcc.host.o
+ $(CC) $(CFLAGS) $+ -o $@
+
+ran%/driver.c ran%/func.c ran%/init.c ran%/check.c ran%/hash.c ran%/init.h:
+ mkdir -p ran$*
$(YARPGEN) --seed=$* --out-dir=ran$*/ --std=c99
-ran%/example.k1c.cmp : ran%/example.gcc.k1c.out ran%/example.ccomp.k1c.out
+ran%/example.target.cmp : ran%/example.gcc.target.out ran%/example.ccomp.target.out
cmp $+ > $@
-.PHONY: all clean
+ran%/example.host_target.cmp : ran%/example.gcc.host.out ran%/example.ccomp.target.out
+ cmp $+ > $@
+
+yarpgen:
+ curl -L -o yarpgen_v1.1.tar.gz https://github.com/intel/yarpgen/archive/v1.1.tar.gz
+ tar xfz yarpgen_v1.1.tar.gz
+ $(MAKE) CXX=g++ -C yarpgen-1.1
+ cp yarpgen-1.1/yarpgen $@
+
+.PHONY: all clean tests_c tests_c
clean:
-rm -rf ran*
diff --git a/test/monniaux/yarpgen/Makefile.old b/test/monniaux/yarpgen/Makefile.old
new file mode 100644
index 00000000..9da82deb
--- /dev/null
+++ b/test/monniaux/yarpgen/Makefile.old
@@ -0,0 +1,52 @@
+YARPGEN=yarpgen
+MAX=300
+PREFIX=ran%06.f
+include ../rules.mk
+
+K1C_CCOMPFLAGS += -funprototyped -fbitfields
+CCOMPFLAGS += -funprototyped -fbitfields
+
+TARGETS_C=$(shell seq --format $(PREFIX)/func.c 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.c 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/init.h 0 $(MAX))
+TARGETS_CCOMP_K1C_S=$(shell seq --format $(PREFIX)/func.ccomp.k1c.s 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.ccomp.k1c.s 0 $(MAX))
+TARGETS_GCC_K1C_S=$(shell seq --format $(PREFIX)/func.gcc.k1c.s 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.gcc.k1c.s 0 $(MAX))
+TARGETS_CCOMP_HOST_S=$(shell seq --format $(PREFIX)/func.ccomp.host.s 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.ccomp.host.s 0 $(MAX))
+TARGETS_GCC_HOST_S=$(shell seq --format $(PREFIX)/func.gcc.host.s 0 $(MAX)) \
+ $(shell seq --format $(PREFIX)/driver.gcc.host.s 0 $(MAX))
+TARGETS_CCOMP_K1C_OUT=$(shell seq --format $(PREFIX)/example.ccomp.k1c.out 0 $(MAX))
+TARGETS_GCC_K1C_OUT=$(shell seq --format $(PREFIX)/example.gcc.k1c.out 0 $(MAX))
+TARGETS_GCC_HOST_OUT=$(shell seq --format $(PREFIX)/example.gcc.host.out 0 $(MAX))
+TARGETS_CCOMP_HOST_OUT=$(shell seq --format $(PREFIX)/example.ccomp.host.out 0 $(MAX))
+TARGETS_CMP=$(shell seq --format $(PREFIX)/example.k1c.cmp 0 $(MAX))
+
+all: $(TARGETS_CCOMP_K1C_OUT) $(TARGETS_GCC_K1C_OUT) $(TARGETS_GCC_HOST_OUT) $(TARGETS_CCOMP_HOST_OUT) $(TARGETS_CCOMP_K1C_S) $(TARGETS_GCC_K1C_S) $(TARGETS_GCC_HOST_S) $(TARGETS_CCOMP_HOST_S) $(TARGETS_CMP) $(TARGETS_C)
+
+ran%/func.ccomp.k1c.s ran%/func.gcc.k1c.s ran%/func.ccomp.host.s ran%/func.gcc.host.s : ran%/init.h
+
+ran%/example.ccomp.k1c: ran%/func.ccomp.k1c.o ran%/driver.ccomp.k1c.o
+ $(K1C_CCOMP) $(K1C_CCOMPFLAGS) $+ -o $@
+
+ran%/example.gcc.k1c: ran%/func.gcc.k1c.o ran%/driver.gcc.k1c.o
+ $(K1C_CC) $(K1C_CFLAGS) $+ -o $@
+
+ran%/example.gcc.host: ran%/func.gcc.host.o ran%/driver.gcc.host.o
+ $(CC) $(CFLAGS) $+ -o $@
+
+ran%/example.ccomp.host: ran%/func.ccomp.host.o ran%/driver.ccomp.host.o
+ $(CCOMP) $(CCOMPFLAGS) $+ -o $@
+
+ran%/driver.c ran%/func.c ran%/init.h:
+ -mkdir ran$*
+ $(YARPGEN) --seed=$* --out-dir=ran$*/ --std=c99
+
+ran%/example.k1c.cmp : ran%/example.gcc.k1c.out ran%/example.ccomp.k1c.out
+ cmp $+ > $@
+
+.PHONY: all clean
+
+clean:
+ -rm -rf ran*
diff --git a/test/mppa/check.sh b/test/mppa/check.sh
deleted file mode 100755
index f25c3e31..00000000
--- a/test/mppa/check.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-# Tests the execution of the binaries produced by CompCert
-
-source do_test.sh
-
-do_test check $1
diff --git a/test/mppa/hardcheck.sh b/test/mppa/hardcheck.sh
new file mode 100755
index 00000000..82b63182
--- /dev/null
+++ b/test/mppa/hardcheck.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Tests the execution of the binaries produced by CompCert, in hardware
+
+source do_test.sh
+
+do_test hardcheck
diff --git a/test/mppa/hardtest.sh b/test/mppa/hardtest.sh
new file mode 100755
index 00000000..09511da6
--- /dev/null
+++ b/test/mppa/hardtest.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Tests the validity of the tests, in hardware
+
+source do_test.sh
+
+do_test hardtest
diff --git a/test/mppa/instr/Makefile b/test/mppa/instr/Makefile
index 69446796..37f7d0ab 100644
--- a/test/mppa/instr/Makefile
+++ b/test/mppa/instr/Makefile
@@ -5,10 +5,11 @@ CC ?= gcc
CCOMP ?= ccomp
OPTIM ?= -O2
CFLAGS ?= $(OPTIM)
-CCOMPFLAGS ?= $(CFLAGS) -faddx
+CCOMPFLAGS ?= $(CFLAGS)
SIMU ?= k1-mppa
TIMEOUT ?= --signal=SIGTERM 120s
DIFF ?= python2.7 floatcmp.py -reltol .00001
+HARDRUN ?= k1-jtag-runner
DIR=./
SRCDIR=$(DIR)
@@ -30,10 +31,11 @@ SIMUPATH=$(shell which $(SIMU))
TESTNAMES?=$(notdir $(subst .c,,$(wildcard $(DIR)/*.c)))
X86_GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .x86-gcc.out,$(TESTNAMES)))
-GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.out,$(TESTNAMES)))
-CCOMP_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.out,$(TESTNAMES)))
+GCC_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.simu.out,$(TESTNAMES)))
+CCOMP_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.simu.out,$(TESTNAMES)))
+GCC_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.hard.out,$(TESTNAMES)))
+CCOMP_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.hard.out,$(TESTNAMES)))
-OUT=$(X86_GCC_OUT) $(GCC_OUT) $(CCOMP_OUT)
BIN=$(addprefix $(BINDIR)/,$(addsuffix .x86-gcc.bin,$(TESTNAMES)))\
$(addprefix $(BINDIR)/,$(addsuffix .gcc.bin,$(TESTNAMES)))\
$(addprefix $(BINDIR)/,$(addsuffix .ccomp.bin,$(TESTNAMES)))
@@ -49,12 +51,18 @@ RED=\033[0;31m
YELLOW=\033[0;33m
NC=\033[0m
+.PHONY:
+test: simutest
+
+.PHONY:
+check: simucheck
+
.PHONY:
-test: $(X86_GCC_OUT) $(GCC_OUT)
+simutest: $(X86_GCC_OUT) $(GCC_SIMUOUT)
@echo "Comparing x86 gcc output to k1 gcc.."
for test in $(TESTNAMES); do\
x86out=$(OUTDIR)/$$test.x86-gcc.out;\
- gccout=$(OUTDIR)/$$test.gcc.out;\
+ gccout=$(OUTDIR)/$$test.gcc.simu.out;\
if grep "__K1C__" -q $$test.c; then\
printf "$(YELLOW)UNTESTED: $$test.c contains an \`#ifdef __K1C__\`\n";\
elif $(DIFF) $$x86out $$gccout > /dev/null; test $${PIPESTATUS[0]} -ne 0; then\
@@ -65,11 +73,39 @@ test: $(X86_GCC_OUT) $(GCC_OUT)
done
.PHONY:
-check: $(GCC_OUT) $(CCOMP_OUT)
+simucheck: $(GCC_SIMUOUT) $(CCOMP_SIMUOUT)
@echo "Comparing k1 gcc output to ccomp.."
@for test in $(TESTNAMES); do\
- gccout=$(OUTDIR)/$$test.gcc.out;\
- ccompout=$(OUTDIR)/$$test.ccomp.out;\
+ gccout=$(OUTDIR)/$$test.gcc.simu.out;\
+ ccompout=$(OUTDIR)/$$test.ccomp.simu.out;\
+ if $(DIFF) $$ccompout $$gccout > /dev/null; test $${PIPESTATUS[0]} -ne 0; then\
+ >&2 printf "$(RED)ERROR: $$ccompout and $$gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$ccompout and $$gccout concur$(NC)\n";\
+ fi;\
+ done
+
+.PHONY:
+hardtest: $(X86_GCC_OUT) $(GCC_HARDOUT)
+ @echo "Comparing x86 gcc output to k1 gcc.."
+ for test in $(TESTNAMES); do\
+ x86out=$(OUTDIR)/$$test.x86-gcc.out;\
+ gccout=$(OUTDIR)/$$test.gcc.hard.out;\
+ if grep "__K1C__" -q $$test.c; then\
+ printf "$(YELLOW)UNTESTED: $$test.c contains an \`#ifdef __K1C__\`\n";\
+ elif $(DIFF) $$x86out $$gccout > /dev/null; test $${PIPESTATUS[0]} -ne 0; then\
+ >&2 printf "$(RED)ERROR: $$x86out and $$gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$x86out and $$gccout concur$(NC)\n";\
+ fi;\
+ done
+
+.PHONY:
+hardcheck: $(GCC_HARDOUT) $(CCOMP_HARDOUT)
+ @echo "Comparing k1 gcc output to ccomp.."
+ @for test in $(TESTNAMES); do\
+ gccout=$(OUTDIR)/$$test.gcc.hard.out;\
+ ccompout=$(OUTDIR)/$$test.ccomp.hard.out;\
if $(DIFF) $$ccompout $$gccout > /dev/null; test $${PIPESTATUS[0]} -ne 0; then\
>&2 printf "$(RED)ERROR: $$ccompout and $$gccout differ$(NC)\n";\
else\
@@ -95,14 +131,22 @@ $(OUTDIR)/%.x86-gcc.out: $(BINDIR)/%.x86-gcc.bin
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) ./$< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.gcc.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
+$(OUTDIR)/%.gcc.simu.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.ccomp.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
+$(OUTDIR)/%.ccomp.simu.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
+$(OUTDIR)/%.gcc.hard.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+$(OUTDIR)/%.ccomp.hard.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
# Assembly to binary
$(BINDIR)/%.x86-gcc.bin: $(ASMDIR)/%.x86-gcc.s $(LIB) $(CCPATH)
diff --git a/test/mppa/interop/Makefile b/test/mppa/interop/Makefile
index e615e89a..3a83d51c 100644
--- a/test/mppa/interop/Makefile
+++ b/test/mppa/interop/Makefile
@@ -6,6 +6,7 @@ CCOMP ?= ccomp
CFLAGS ?= -O2 -Wno-varargs
SIMU ?= k1-mppa
TIMEOUT ?= --signal=SIGTERM 120s
+HARDRUN ?= k1-jtag-runner
DIR=./
SRCDIR=$(DIR)
@@ -33,17 +34,23 @@ SIMUPATH=$(shell which $(SIMU))
TESTNAMES ?= $(filter-out $(VAARG_COMMON),$(filter-out $(COMMON),$(notdir $(subst .c,,$(wildcard $(DIR)/*.c)))))
X86_GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .x86-gcc.out,$(TESTNAMES)))
-GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.out,$(TESTNAMES)))
-GCC_REV_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.out,$(TESTNAMES)))
-CCOMP_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.out,$(TESTNAMES)))
+GCC_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.simu.out,$(TESTNAMES)))
+GCC_REV_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.simu.out,$(TESTNAMES)))
+CCOMP_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.simu.out,$(TESTNAMES)))
+
+GCC_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.hard.out,$(TESTNAMES)))
+GCC_REV_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.hard.out,$(TESTNAMES)))
+CCOMP_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.hard.out,$(TESTNAMES)))
VAARG_X86_GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .x86-gcc.vaarg.out,$(TESTNAMES)))
-VAARG_GCC_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.vaarg.out,$(TESTNAMES)))
-VAARG_GCC_REV_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.vaarg.out,$(TESTNAMES)))
-VAARG_CCOMP_OUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.vaarg.out,$(TESTNAMES)))
+VAARG_GCC_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.vaarg.simu.out,$(TESTNAMES)))
+VAARG_GCC_REV_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.vaarg.simu.out,$(TESTNAMES)))
+VAARG_CCOMP_SIMUOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.vaarg.simu.out,$(TESTNAMES)))
+
+VAARG_GCC_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.vaarg.hard.out,$(TESTNAMES)))
+VAARG_GCC_REV_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .gcc.rev.vaarg.hard.out,$(TESTNAMES)))
+VAARG_CCOMP_HARDOUT=$(addprefix $(OUTDIR)/,$(addsuffix .ccomp.vaarg.hard.out,$(TESTNAMES)))
-OUT=$(X86_GCC_OUT) $(GCC_OUT) $(CCOMP_OUT) $(GCC_REV_OUT)\
- $(VAARG_GCC_OUT) $(VAARG_GCC_OUT) $(VAARG_CCOMP_OUT) $(VAARG_GCC_REV_OUT)
BIN=$(addprefix $(BINDIR)/,$(addsuffix .x86-gcc.bin,$(TESTNAMES)))\
$(addprefix $(BINDIR)/,$(addsuffix .gcc.bin,$(TESTNAMES)))\
$(addprefix $(BINDIR)/,$(addsuffix .ccomp.bin,$(TESTNAMES)))\
@@ -63,14 +70,72 @@ GREEN=\033[0;32m
RED=\033[0;31m
NC=\033[0m
+.PHONY:
+test: simutest
+
+.PHONY:
+simutest: $(X86_GCC_OUT) $(GCC_SIMUOUT) $(VAARG_X86_GCC_OUT) $(VAARG_GCC_SIMUOUT)
+ @echo "Comparing x86 gcc output to k1 gcc.."
+ @for test in $(TESTNAMES); do\
+ x86out=$(OUTDIR)/$$test.x86-gcc.out;\
+ gccout=$(OUTDIR)/$$test.gcc.simu.out;\
+ vaarg_x86out=$(OUTDIR)/$$test.x86-gcc.vaarg.out;\
+ vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.simu.out;\
+ if ! diff $$x86out $$gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$x86out and $$gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$x86out and $$gccout concur$(NC)\n";\
+ fi;\
+ if ! diff $$vaarg_x86out $$vaarg_gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$vaarg_x86out and $$vaarg_gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$vaarg_x86out and $$vaarg_gccout concur$(NC)\n";\
+ fi;\
+ done
+
+.PHONY:
+check: simucheck
+
+.PHONY:
+simucheck: $(GCC_SIMUOUT) $(CCOMP_SIMUOUT) $(GCC_REV_SIMUOUT) $(VAARG_GCC_SIMUOUT) $(VAARG_CCOMP_SIMUOUT) $(VAARG_GCC_REV_SIMUOUT)
+ @echo "Comparing k1 gcc output to ccomp.."
+ @for test in $(TESTNAMES); do\
+ gccout=$(OUTDIR)/$$test.gcc.simu.out;\
+ ccompout=$(OUTDIR)/$$test.ccomp.simu.out;\
+ gccrevout=$(OUTDIR)/$$test.gcc.rev.simu.out;\
+ vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.simu.out;\
+ vaarg_ccompout=$(OUTDIR)/$$test.ccomp.vaarg.simu.out;\
+ vaarg_gccrevout=$(OUTDIR)/$$test.gcc.rev.vaarg.simu.out;\
+ if ! diff $$ccompout $$gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$ccompout and $$gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$ccompout and $$gccout concur$(NC)\n";\
+ fi;\
+ if ! diff $$gccrevout $$gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$gccrevout and $$gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$gccrevout and $$gccout concur$(NC)\n";\
+ fi;\
+ if ! diff $$vaarg_ccompout $$vaarg_gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$vaarg_ccompout and $$vaarg_gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$vaarg_ccompout and $$vaarg_gccout concur$(NC)\n";\
+ fi;\
+ if ! diff $$vaarg_gccrevout $$vaarg_gccout > /dev/null; then\
+ >&2 printf "$(RED)ERROR: $$vaarg_gccrevout and $$vaarg_gccout differ$(NC)\n";\
+ else\
+ printf "$(GREEN)GOOD: $$vaarg_gccrevout and $$vaarg_gccout concur$(NC)\n";\
+ fi;\
+ done
+
.PHONY:
-test: $(X86_GCC_OUT) $(GCC_OUT) $(VAARG_X86_GCC_OUT) $(VAARG_GCC_OUT)
+hardtest: $(X86_GCC_OUT) $(GCC_HARDOUT) $(VAARG_X86_GCC_OUT) $(VAARG_GCC_HARDOUT)
@echo "Comparing x86 gcc output to k1 gcc.."
@for test in $(TESTNAMES); do\
x86out=$(OUTDIR)/$$test.x86-gcc.out;\
- gccout=$(OUTDIR)/$$test.gcc.out;\
+ gccout=$(OUTDIR)/$$test.gcc.hard.out;\
vaarg_x86out=$(OUTDIR)/$$test.x86-gcc.vaarg.out;\
- vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.out;\
+ vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.hard.out;\
if ! diff $$x86out $$gccout > /dev/null; then\
>&2 printf "$(RED)ERROR: $$x86out and $$gccout differ$(NC)\n";\
else\
@@ -84,15 +149,15 @@ test: $(X86_GCC_OUT) $(GCC_OUT) $(VAARG_X86_GCC_OUT) $(VAARG_GCC_OUT)
done
.PHONY:
-check: $(GCC_OUT) $(CCOMP_OUT) $(GCC_REV_OUT) $(VAARG_GCC_OUT) $(VAARG_CCOMP_OUT) $(VAARG_GCC_REV_OUT)
+hardcheck: $(GCC_HARDOUT) $(CCOMP_HARDOUT) $(GCC_REV_HARDOUT) $(VAARG_GCC_HARDOUT) $(VAARG_CCOMP_HARDOUT) $(VAARG_GCC_REV_HARDOUT)
@echo "Comparing k1 gcc output to ccomp.."
@for test in $(TESTNAMES); do\
- gccout=$(OUTDIR)/$$test.gcc.out;\
- ccompout=$(OUTDIR)/$$test.ccomp.out;\
- gccrevout=$(OUTDIR)/$$test.gcc.rev.out;\
- vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.out;\
- vaarg_ccompout=$(OUTDIR)/$$test.ccomp.vaarg.out;\
- vaarg_gccrevout=$(OUTDIR)/$$test.gcc.rev.vaarg.out;\
+ gccout=$(OUTDIR)/$$test.gcc.hard.out;\
+ ccompout=$(OUTDIR)/$$test.ccomp.hard.out;\
+ gccrevout=$(OUTDIR)/$$test.gcc.rev.hard.out;\
+ vaarg_gccout=$(OUTDIR)/$$test.gcc.vaarg.hard.out;\
+ vaarg_ccompout=$(OUTDIR)/$$test.ccomp.vaarg.hard.out;\
+ vaarg_gccrevout=$(OUTDIR)/$$test.gcc.rev.vaarg.hard.out;\
if ! diff $$ccompout $$gccout > /dev/null; then\
>&2 printf "$(RED)ERROR: $$ccompout and $$gccout differ$(NC)\n";\
else\
@@ -144,36 +209,60 @@ $(OUTDIR)/%.x86-gcc.out: $(BINDIR)/%.x86-gcc.bin
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) ./$< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.gcc.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
+$(OUTDIR)/%.gcc.simu.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.gcc.rev.out: $(BINDIR)/%.gcc.rev.bin $(SIMUPATH)
+$(OUTDIR)/%.gcc.rev.simu.out: $(BINDIR)/%.gcc.rev.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.ccomp.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
+$(OUTDIR)/%.ccomp.simu.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
+$(OUTDIR)/%.gcc.hard.out: $(BINDIR)/%.gcc.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+$(OUTDIR)/%.gcc.rev.hard.out: $(BINDIR)/%.gcc.rev.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+$(OUTDIR)/%.ccomp.hard.out: $(BINDIR)/%.ccomp.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
## With vaarg
$(OUTDIR)/%.x86-gcc.vaarg.out: $(BINDIR)/%.x86-gcc.vaarg.bin
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) ./$< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.gcc.vaarg.out: $(BINDIR)/%.gcc.vaarg.bin $(SIMUPATH)
+$(OUTDIR)/%.gcc.vaarg.simu.out: $(BINDIR)/%.gcc.vaarg.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.gcc.rev.vaarg.out: $(BINDIR)/%.gcc.rev.vaarg.bin $(SIMUPATH)
+$(OUTDIR)/%.gcc.rev.vaarg.simu.out: $(BINDIR)/%.gcc.rev.vaarg.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
-$(OUTDIR)/%.ccomp.vaarg.out: $(BINDIR)/%.ccomp.vaarg.bin $(SIMUPATH)
+$(OUTDIR)/%.ccomp.vaarg.simu.out: $(BINDIR)/%.ccomp.vaarg.bin $(SIMUPATH)
@mkdir -p $(@D)
ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
+$(OUTDIR)/%.gcc.vaarg.hard.out: $(BINDIR)/%.gcc.vaarg.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+$(OUTDIR)/%.gcc.rev.vaarg.hard.out: $(BINDIR)/%.gcc.rev.vaarg.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+$(OUTDIR)/%.ccomp.vaarg.hard.out: $(BINDIR)/%.ccomp.vaarg.bin $(SIMUPATH)
+ @mkdir -p $(@D)
+ ret=0; timeout $(TIMEOUT) $(HARDRUN) --exec-file=Cluster0:$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
##
# Object to binary
##
diff --git a/test/mppa/simucheck.sh b/test/mppa/simucheck.sh
new file mode 100755
index 00000000..25fb9947
--- /dev/null
+++ b/test/mppa/simucheck.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Tests the execution of the binaries produced by CompCert, by simulation
+
+source do_test.sh
+
+do_test check $1
diff --git a/test/mppa/test.sh b/test/mppa/simutest.sh
index 30806a6b..3b1021e6 100755
--- a/test/mppa/test.sh
+++ b/test/mppa/simutest.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Tests the validity of the tests
+# Tests the validity of the tests, in simulator
source do_test.sh
diff --git a/test/regression/Makefile b/test/regression/Makefile
index 3447d6a5..97c25f6c 100644
--- a/test/regression/Makefile
+++ b/test/regression/Makefile
@@ -35,9 +35,9 @@ endif
# but produce processor-dependent results, so no reference output in Results
TESTS_DIFF=NaNs
-ifeq ($(ARCH),mppa_k1c)
+# FIXME ifeq ($(ARCH),mppa_k1c)
TESTS_DIFF:=$(filter-out NaNs,$(TESTS_DIFF))
-endif
+# endif
# Other tests: should compile to .s without errors (but expect warnings)
diff --git a/test/regression/Results/int64 b/test/regression/Results/int64
index af444cf6..ae8a3cc1 100644
--- a/test/regression/Results/int64
+++ b/test/regression/Results/int64
@@ -335,6 +335,48 @@ utof x = 0
stof x = 0
x = 0
+y = 52ce6b4000000063
+-x = 0
+x + y = 52ce6b4000000063
+x - y = ad3194bfffffff9d
+x * y = 0
+x /u y = 0
+x %u y = 0
+x /s y = 0
+x %s y = 0
+x /u y2 = 0
+x %u y2 = 0
+x /s y3 = 0
+x %s y3 = 0
+x /u 3 = 0
+x %u 3 = 0
+x /s 3 = 0
+x %s 3 = 0
+x /u 5 = 0
+x %u 5 = 0
+x /s 5 = 0
+x %s 5 = 0
+x /u 11 = 0
+x %u 11 = 0
+x /s 11 = 0
+x %s 11 = 0
+~x = ffffffffffffffff
+x & y = 0
+x | y = 52ce6b4000000063
+x ^ y = 52ce6b4000000063
+x << i = 0
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = lt
+utod x = 0
+dtou f = 0
+stod x = 0
+dtos f = 0
+utof x = 0
+stof x = 0
+
+x = 0
y = 14057b7ef767814f
-x = 0
x + y = 14057b7ef767814f
@@ -755,6 +797,48 @@ utof x = 3f800000
stof x = 3f800000
x = 1
+y = 52ce6b4000000063
+-x = ffffffffffffffff
+x + y = 52ce6b4000000064
+x - y = ad3194bfffffff9e
+x * y = 52ce6b4000000063
+x /u y = 0
+x %u y = 1
+x /s y = 0
+x %s y = 1
+x /u y2 = 0
+x %u y2 = 1
+x /s y3 = 0
+x %s y3 = 1
+x /u 3 = 0
+x %u 3 = 1
+x /s 3 = 0
+x %s 3 = 1
+x /u 5 = 0
+x %u 5 = 1
+x /s 5 = 0
+x %s 5 = 1
+x /u 11 = 0
+x %u 11 = 1
+x /s 11 = 0
+x %s 11 = 1
+~x = fffffffffffffffe
+x & y = 1
+x | y = 52ce6b4000000063
+x ^ y = 52ce6b4000000062
+x << i = 800000000
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = lt
+utod x = 3ff0000000000000
+dtou f = 0
+stod x = 3ff0000000000000
+dtos f = 0
+utof x = 3f800000
+stof x = 3f800000
+
+x = 1
y = 9af678222e728119
-x = ffffffffffffffff
x + y = 9af678222e72811a
@@ -1175,6 +1259,48 @@ utof x = 5f800000
stof x = bf800000
x = ffffffffffffffff
+y = 52ce6b4000000063
+-x = 1
+x + y = 52ce6b4000000062
+x - y = ad3194bfffffff9c
+x * y = ad3194bfffffff9d
+x /u y = 3
+x %u y = 794be3ffffffed6
+x /s y = 0
+x %s y = ffffffffffffffff
+x /u y2 = 3176fe836
+x %u y2 = 3683607f
+x /s y3 = 0
+x %s y3 = ffffffffffffffff
+x /u 3 = 5555555555555555
+x %u 3 = 0
+x /s 3 = 0
+x %s 3 = ffffffffffffffff
+x /u 5 = 3333333333333333
+x %u 5 = 0
+x /s 5 = 0
+x %s 5 = ffffffffffffffff
+x /u 11 = 1745d1745d1745d1
+x %u 11 = 4
+x /s 11 = 0
+x %s 11 = ffffffffffffffff
+~x = 0
+x & y = 52ce6b4000000063
+x | y = ffffffffffffffff
+x ^ y = ad3194bfffffff9c
+x << i = fffffff800000000
+x >>u i = 1fffffff
+x >>s i = ffffffffffffffff
+x cmpu y = gt
+x cmps y = lt
+utod x = 43f0000000000000
+dtou f = 68db8bac710cb
+stod x = bff0000000000000
+dtos f = 0
+utof x = 5f800000
+stof x = bf800000
+
+x = ffffffffffffffff
y = 62354cda6226d1f3
-x = 1
x + y = 62354cda6226d1f2
@@ -1595,6 +1721,48 @@ utof x = 4f000000
stof x = 4f000000
x = 7fffffff
+y = 52ce6b4000000063
+-x = ffffffff80000001
+x + y = 52ce6b4080000062
+x - y = ad3194c07fffff9c
+x * y = ad3194f17fffff9d
+x /u y = 0
+x %u y = 7fffffff
+x /s y = 0
+x %s y = 7fffffff
+x /u y2 = 1
+x %u y2 = 2d3194bf
+x /s y3 = 1
+x %s y3 = 2d3194bf
+x /u 3 = 2aaaaaaa
+x %u 3 = 1
+x /s 3 = 2aaaaaaa
+x %s 3 = 1
+x /u 5 = 19999999
+x %u 5 = 2
+x /s 5 = 19999999
+x %s 5 = 2
+x /u 11 = ba2e8ba
+x %u 11 = 1
+x /s 11 = ba2e8ba
+x %s 11 = 1
+~x = ffffffff80000000
+x & y = 63
+x | y = 52ce6b407fffffff
+x ^ y = 52ce6b407fffff9c
+x << i = fffffff800000000
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = lt
+utod x = 41dfffffffc00000
+dtou f = 346dc
+stod x = 41dfffffffc00000
+dtos f = 346dc
+utof x = 4f000000
+stof x = 4f000000
+
+x = 7fffffff
y = 144093704fadba5d
-x = ffffffff80000001
x + y = 14409370cfadba5c
@@ -2015,6 +2183,48 @@ utof x = 4f000000
stof x = 4f000000
x = 80000000
+y = 52ce6b4000000063
+-x = ffffffff80000000
+x + y = 52ce6b4080000063
+x - y = ad3194c07fffff9d
+x * y = 3180000000
+x /u y = 0
+x %u y = 80000000
+x /s y = 0
+x %s y = 80000000
+x /u y2 = 1
+x %u y2 = 2d3194c0
+x /s y3 = 1
+x %s y3 = 2d3194c0
+x /u 3 = 2aaaaaaa
+x %u 3 = 2
+x /s 3 = 2aaaaaaa
+x %s 3 = 2
+x /u 5 = 19999999
+x %u 5 = 3
+x /s 5 = 19999999
+x %s 5 = 3
+x /u 11 = ba2e8ba
+x %u 11 = 2
+x /s 11 = ba2e8ba
+x %s 11 = 2
+~x = ffffffff7fffffff
+x & y = 0
+x | y = 52ce6b4080000063
+x ^ y = 52ce6b4080000063
+x << i = 0
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = lt
+utod x = 41e0000000000000
+dtou f = 346dc
+stod x = 41e0000000000000
+dtos f = 346dc
+utof x = 4f000000
+stof x = 4f000000
+
+x = 80000000
y = 7b985bc1e7bce4d7
-x = ffffffff80000000
x + y = 7b985bc267bce4d7
@@ -2435,6 +2645,48 @@ utof x = 5f000000
stof x = 5f000000
x = 7fffffffffffffff
+y = 52ce6b4000000063
+-x = 8000000000000001
+x + y = d2ce6b4000000062
+x - y = 2d3194bfffffff9c
+x * y = 2d3194bfffffff9d
+x /u y = 1
+x %u y = 2d3194bfffffff9c
+x /s y = 1
+x %s y = 2d3194bfffffff9c
+x /u y2 = 18bb7f41b
+x %u y2 = 1b41b03f
+x /s y3 = 18bb7f41b
+x %s y3 = 1b41b03f
+x /u 3 = 2aaaaaaaaaaaaaaa
+x %u 3 = 1
+x /s 3 = 2aaaaaaaaaaaaaaa
+x %s 3 = 1
+x /u 5 = 1999999999999999
+x %u 5 = 2
+x /s 5 = 1999999999999999
+x %s 5 = 2
+x /u 11 = ba2e8ba2e8ba2e8
+x %u 11 = 7
+x /s 11 = ba2e8ba2e8ba2e8
+x %s 11 = 7
+~x = 8000000000000000
+x & y = 52ce6b4000000063
+x | y = 7fffffffffffffff
+x ^ y = 2d3194bfffffff9c
+x << i = fffffff800000000
+x >>u i = fffffff
+x >>s i = fffffff
+x cmpu y = gt
+x cmps y = gt
+utod x = 43e0000000000000
+dtou f = 346dc5d638865
+stod x = 43e0000000000000
+dtos f = 346dc5d638865
+utof x = 5f000000
+stof x = 5f000000
+
+x = 7fffffffffffffff
y = a220229ec164ffe1
-x = 8000000000000001
x + y = 2220229ec164ffe0
@@ -2855,6 +3107,48 @@ utof x = 5f000000
stof x = df000000
x = 8000000000000000
+y = 52ce6b4000000063
+-x = 8000000000000000
+x + y = d2ce6b4000000063
+x - y = 2d3194bfffffff9d
+x * y = 8000000000000000
+x /u y = 1
+x %u y = 2d3194bfffffff9d
+x /s y = ffffffffffffffff
+x %s y = d2ce6b4000000063
+x /u y2 = 18bb7f41b
+x %u y2 = 1b41b040
+x /s y3 = fffffffe74480be5
+x %s y3 = ffffffffe4be4fc0
+x /u 3 = 2aaaaaaaaaaaaaaa
+x %u 3 = 2
+x /s 3 = d555555555555556
+x %s 3 = fffffffffffffffe
+x /u 5 = 1999999999999999
+x %u 5 = 3
+x /s 5 = e666666666666667
+x %s 5 = fffffffffffffffd
+x /u 11 = ba2e8ba2e8ba2e8
+x %u 11 = 8
+x /s 11 = f45d1745d1745d18
+x %s 11 = fffffffffffffff8
+~x = 7fffffffffffffff
+x & y = 0
+x | y = d2ce6b4000000063
+x ^ y = d2ce6b4000000063
+x << i = 0
+x >>u i = 10000000
+x >>s i = fffffffff0000000
+x cmpu y = gt
+x cmps y = lt
+utod x = 43e0000000000000
+dtou f = 346dc5d638865
+stod x = c3e0000000000000
+dtos f = fffcb923a29c779b
+utof x = 5f000000
+stof x = df000000
+
+x = 8000000000000000
y = c73aa0d9a415dfb
-x = 8000000000000000
x + y = 8c73aa0d9a415dfb
@@ -3275,6 +3569,48 @@ utof x = 4f800000
stof x = 4f800000
x = 100000003
+y = 52ce6b4000000063
+-x = fffffffefffffffd
+x + y = 52ce6b4100000066
+x - y = ad3194c0ffffffa0
+x * y = f86b422300000129
+x /u y = 0
+x %u y = 100000003
+x /s y = 0
+x %s y = 100000003
+x /u y2 = 3
+x %u y2 = 794be43
+x /s y3 = 3
+x %s y3 = 794be43
+x /u 3 = 55555556
+x %u 3 = 1
+x /s 3 = 55555556
+x %s 3 = 1
+x /u 5 = 33333333
+x %u 5 = 4
+x /s 5 = 33333333
+x %s 5 = 4
+x /u 11 = 1745d174
+x %u 11 = 7
+x /s 11 = 1745d174
+x %s 11 = 7
+~x = fffffffefffffffc
+x & y = 3
+x | y = 52ce6b4100000063
+x ^ y = 52ce6b4100000060
+x << i = 1800000000
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = lt
+utod x = 41f0000000300000
+dtou f = 68db8
+stod x = 41f0000000300000
+dtos f = 68db8
+utof x = 4f800000
+stof x = 4f800000
+
+x = 100000003
y = e9bcd26890f095a5
-x = fffffffefffffffd
x + y = e9bcd26990f095a8
@@ -3358,47 +3694,467 @@ dtos f = 14bb101261e18
utof x = 5e4a72c9
stof x = 5e4a72c9
-x = 8362aa9340fe215f
-y = f986342416ec8002
--x = 7c9d556cbf01dea1
-x + y = 7ce8deb757eaa161
-x - y = 89dc766f2a11a15d
-x * y = e4a2b426803fc2be
+x = 52ce6b4000000063
+y = 0
+-x = ad3194bfffffff9d
+x + y = 52ce6b4000000063
+x - y = 52ce6b4000000063
+x * y = 0
x /u y = 0
-x %u y = 8362aa9340fe215f
-x /s y = 13
-x %s y = fe6ccbe58d70a139
-x /u y2 = 86cb918b
-x %u y2 = 910b6dd3
-x /s y3 = 133e437097
-x %s y3 = fffffffffe99a023
-x /u 3 = 2bcb8e3115aa0b1f
-x %u 3 = 2
-x /s 3 = d67638dbc054b5cb
-x %s 3 = fffffffffffffffe
-x /u 5 = 1a46eeea4032d379
-x %u 5 = 2
-x /s 5 = e713bbb70cffa047
-x %s 5 = fffffffffffffffc
-x /u 11 = bf1b26a7a45a5f1
-x %u 11 = 4
-x /s 11 = f4abe0f61d2e6020
-x %s 11 = ffffffffffffffff
-~x = 7c9d556cbf01dea0
-x & y = 8102200000ec0002
-x | y = fbe6beb756fea15f
-x ^ y = 7ae49eb75612a15d
-x << i = d8aaa4d03f8857c
-x >>u i = 20d8aaa4d03f8857
-x >>s i = e0d8aaa4d03f8857
+x %u y = 0
+x /s y = 0
+x %s y = 0
+x /u y2 = 0
+x %u y2 = 0
+x /s y3 = 0
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 0
+x | y = 52ce6b4000000063
+x ^ y = 52ce6b4000000063
+x << i = 52ce6b4000000063
+x >>u i = 52ce6b4000000063
+x >>s i = 52ce6b4000000063
+x cmpu y = gt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 1
+-x = ad3194bfffffff9d
+x + y = 52ce6b4000000064
+x - y = 52ce6b4000000062
+x * y = 52ce6b4000000063
+x /u y = 52ce6b4000000063
+x %u y = 0
+x /s y = 52ce6b4000000063
+x %s y = 0
+x /u y2 = 0
+x %u y2 = 0
+x /s y3 = 0
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 1
+x | y = 52ce6b4000000063
+x ^ y = 52ce6b4000000062
+x << i = a59cd680000000c6
+x >>u i = 296735a000000031
+x >>s i = 296735a000000031
+x cmpu y = gt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = ffffffffffffffff
+-x = ad3194bfffffff9d
+x + y = 52ce6b4000000062
+x - y = 52ce6b4000000064
+x * y = ad3194bfffffff9d
+x /u y = 0
+x %u y = 52ce6b4000000063
+x /s y = ad3194bfffffff9d
+x %s y = 0
+x /u y2 = 52ce6b40
+x %u y2 = 52ce6ba3
+x /s y3 = ad3194bfffffff9d
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 52ce6b4000000063
+x | y = ffffffffffffffff
+x ^ y = ad3194bfffffff9c
+x << i = 8000000000000000
+x >>u i = 0
+x >>s i = 0
+x cmpu y = lt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 7fffffff
+-x = ad3194bfffffff9d
+x + y = 52ce6b4080000062
+x - y = 52ce6b3f80000064
+x * y = ad3194f17fffff9d
+x /u y = a59cd681
+x %u y = 259cd6e4
+x /s y = a59cd681
+x %s y = 259cd6e4
+x /u y2 = 0
+x %u y2 = 0
+x /s y3 = 0
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 63
+x | y = 52ce6b407fffffff
+x ^ y = 52ce6b407fffff9c
+x << i = 8000000000000000
+x >>u i = 0
+x >>s i = 0
+x cmpu y = gt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 80000000
+-x = ad3194bfffffff9d
+x + y = 52ce6b4080000063
+x - y = 52ce6b3f80000063
+x * y = 3180000000
+x /u y = a59cd680
+x %u y = 63
+x /s y = a59cd680
+x %s y = 63
+x /u y2 = 0
+x %u y2 = 0
+x /s y3 = 0
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 0
+x | y = 52ce6b4080000063
+x ^ y = 52ce6b4080000063
+x << i = 52ce6b4000000063
+x >>u i = 52ce6b4000000063
+x >>s i = 52ce6b4000000063
+x cmpu y = gt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 7fffffffffffffff
+-x = ad3194bfffffff9d
+x + y = d2ce6b4000000062
+x - y = d2ce6b4000000064
+x * y = 2d3194bfffffff9d
+x /u y = 0
+x %u y = 52ce6b4000000063
+x /s y = 0
+x %s y = 52ce6b4000000063
+x /u y2 = a59cd681
+x %u y2 = 259cd6e4
+x /s y3 = a59cd681
+x %s y3 = 259cd6e4
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 52ce6b4000000063
+x | y = 7fffffffffffffff
+x ^ y = 2d3194bfffffff9c
+x << i = 8000000000000000
+x >>u i = 0
+x >>s i = 0
x cmpu y = lt
x cmps y = lt
-utod x = 43e06c5552681fc4
-dtou f = 35d0c262d14d7
-stod x = c3df27555b2fc078
-dtos f = fffccf536b66040d
-utof x = 5f0362ab
-stof x = def93aab
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 8000000000000000
+-x = ad3194bfffffff9d
+x + y = d2ce6b4000000063
+x - y = d2ce6b4000000063
+x * y = 8000000000000000
+x /u y = 0
+x %u y = 52ce6b4000000063
+x /s y = 0
+x %s y = 52ce6b4000000063
+x /u y2 = a59cd680
+x %u y2 = 63
+x /s y3 = ffffffff5a632980
+x %s y3 = 63
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 0
+x | y = d2ce6b4000000063
+x ^ y = d2ce6b4000000063
+x << i = 52ce6b4000000063
+x >>u i = 52ce6b4000000063
+x >>s i = 52ce6b4000000063
+x cmpu y = lt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 100000003
+-x = ad3194bfffffff9d
+x + y = 52ce6b4100000066
+x - y = 52ce6b3f00000060
+x * y = f86b422300000129
+x /u y = 52ce6b3f
+x %u y = 794bea6
+x /s y = 52ce6b3f
+x %s y = 794bea6
+x /u y2 = 52ce6b4000000063
+x %u y2 = 0
+x /s y3 = 52ce6b4000000063
+x %s y3 = 0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 3
+x | y = 52ce6b4100000063
+x ^ y = 52ce6b4100000060
+x << i = 96735a0000000318
+x >>u i = a59cd680000000c
+x >>s i = a59cd680000000c
+x cmpu y = gt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 52ce6b4000000063
+-x = ad3194bfffffff9d
+x + y = a59cd680000000c6
+x - y = 0
+x * y = ba6f38000002649
+x /u y = 1
+x %u y = 0
+x /s y = 1
+x %s y = 0
+x /u y2 = 100000000
+x %u y2 = 63
+x /s y3 = 100000000
+x %s y3 = 63
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 52ce6b4000000063
+x | y = 52ce6b4000000063
+x ^ y = 0
+x << i = 31800000000
+x >>u i = a59cd68
+x >>s i = a59cd68
+x cmpu y = eq
+x cmps y = eq
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = 52ce6b4000000063
+y = 8362aa9340fe215f
+-x = ad3194bfffffff9d
+x + y = d63115d340fe21c2
+x - y = cf6bc0acbf01df04
+x * y = 8f1503b22246e7bd
+x /u y = 0
+x %u y = 52ce6b4000000063
+x /s y = 0
+x %s y = 52ce6b4000000063
+x /u y2 = a158656f
+x %u y2 = 5640ba6
+x /s y3 = ffffffff55e35d11
+x %s y3 = 5f2245a0
+x /u 3 = 1b9a23c000000021
+x %u 3 = 0
+x /s 3 = 1b9a23c000000021
+x %s 3 = 0
+x /u 5 = 108faf0ccccccce0
+x %u 5 = 3
+x /s 5 = 108faf0ccccccce0
+x %s 5 = 3
+x /u 11 = 7872105d1745d20
+x %u 11 = 3
+x /s 11 = 7872105d1745d20
+x %s 11 = 3
+~x = ad3194bfffffff9c
+x & y = 2422a0000000043
+x | y = d3eeebd340fe217f
+x ^ y = d1acc1d340fe213c
+x << i = 3180000000
+x >>u i = a59cd680
+x >>s i = a59cd680
+x cmpu y = lt
+x cmps y = gt
+utod x = 43d4b39ad0000000
+dtou f = 21eadf559b3d0
+stod x = 43d4b39ad0000000
+dtos f = 21eadf559b3d0
+utof x = 5ea59cd7
+stof x = 5ea59cd7
+
+x = f986342416ec8002
+y = 52ce6b4000000063
+-x = 679cbdbe9137ffe
+x + y = 4c549f6416ec8065
+x - y = a6b7c8e416ec7f9f
+x * y = b9230074dd7580c6
+x /u y = 3
+x %u y = 11af26416ec7ed9
+x /s y = 0
+x %s y = f986342416ec8002
+x /u y2 = 3036abea3
+x %u y2 = 164b642
+x /s y3 = ffffffffebfad66d
+x %s y3 = ffffffffcae155c2
+x /u 3 = 532cbc0c07a42aab
+x %u 3 = 1
+x /s 3 = fdd766b6b24ed556
+x %s 3 = 0
+x /u 5 = 31e7a40737c8e666
+x %u 5 = 4
+x /s 5 = feb470d40495b334
+x %s 5 = fffffffffffffffe
+x /u 11 = 16af1c0347e6f45d
+x %u 11 = 3
+x /s 11 = ff694a8eeacfae8c
+x %s 11 = fffffffffffffffe
+~x = 679cbdbe9137ffd
+x & y = 5086200000000002
+x | y = fbce7f6416ec8063
+x ^ y = ab485f6416ec8061
+x << i = b764001000000000
+x >>u i = 1f30c684
+x >>s i = ffffffffff30c684
+x cmpu y = gt
+x cmps y = lt
+utod x = 43ef30c68482dd90
+dtou f = 6634832136daf
+stod x = c399e72f6fa44e00
+dtos f = ffffd58f774c5ce4
+utof x = 5f798634
+stof x = dccf397b
x = 368083376ba4ffa9
y = 6912b247b79a4904
@@ -7558,3 +8314,45 @@ dtos f = b3fdf698d581
utof x = 5ddbb784
stof x = 5ddbb784
+x = ca9a47c1649d27a7
+y = d56d650045e652aa
+-x = 3565b83e9b62d859
+x + y = a007acc1aa837a51
+x - y = f52ce2c11eb6d4fd
+x * y = 630e3c88ca19d2e6
+x /u y = 0
+x %u y = ca9a47c1649d27a7
+x /s y = 1
+x %s y = f52ce2c11eb6d4fd
+x /u y2 = f3042098
+x %u y2 = 6b092fa7
+x /s y3 = 141176486
+x %s y3 = ffffffffdee649a7
+x /u 3 = 4388c295cc34628d
+x %u 3 = 0
+x /s 3 = ee336d4076df0d38
+x %s 3 = ffffffffffffffff
+x /u 5 = 2885418d141f6e54
+x %u 5 = 3
+x /s 5 = f5520e59e0ec3b22
+x %s 5 = fffffffffffffffd
+x /u 11 = 126b1dcbc3541ae0
+x %u 11 = 7
+x /s 11 = fb254c57663cd510
+x %s 11 = fffffffffffffff7
+~x = 3565b83e9b62d858
+x & y = c0084500448402a2
+x | y = dfff67c165ff77af
+x ^ y = 1ff722c1217b750d
+x << i = 749e9c0000000000
+x >>u i = 32a691
+x >>s i = fffffffffff2a691
+x cmpu y = lt
+x cmps y = lt
+utod x = 43e95348f82c93a5
+dtou f = 52fc6dac31674
+stod x = c3cab2dc1f4db16c
+dtos f = fffea20e1ffc05aa
+utof x = 5f4a9a48
+stof x = de5596e1
+
diff --git a/test/regression/Results/interop1 b/test/regression/Results/interop1
index 990dfe9d..6e32c1cb 100644
--- a/test/regression/Results/interop1
+++ b/test/regression/Results/interop1
@@ -1,4 +1,8 @@
--- CompCert calling native:
+si8u: 177
+si8s: -79
+si16u: 64305
+si16s: -1231
s1: { a = 'a' }
s2: { a = 'a', b = 'b' }
s3: { a = 'a', b = 'b', c = ' c' }
@@ -44,6 +48,10 @@ ru6: { a = 55555, b = 666 }
ru7: { a = -10001, b = -789, c = 'z' }
ru8: { a = 'x', b = 12345 }
--- native calling CompCert:
+si8u: 177
+si8s: -79
+si16u: 64305
+si16s: -1231
s1: { a = 'a' }
s2: { a = 'a', b = 'b' }
s3: { a = 'a', b = 'b', c = ' c' }
diff --git a/test/regression/int64.c b/test/regression/int64.c
index d9785e95..0da9602d 100644
--- a/test/regression/int64.c
+++ b/test/regression/int64.c
@@ -103,7 +103,8 @@ u64 special_values[] = {
0x80000000LLU,
0x7FFFFFFFFFFFFFFFLLU,
0x8000000000000000LLU,
- 0x100000003LLU
+ 0x100000003LLU,
+ 0x52ce6b4000000063LLU
};
#define NUM_SPECIAL_VALUES (sizeof(special_values) / sizeof(u64))
diff --git a/test/regression/interop1.c b/test/regression/interop1.c
index a39f449c..6836b89e 100644
--- a/test/regression/interop1.c
+++ b/test/regression/interop1.c
@@ -195,6 +195,17 @@ RETURN(ru6,U6,init_U6)
RETURN(ru7,U7,init_U7)
RETURN(ru8,U8,init_U8)
+/* Returning small integers */
+
+#define SMALLINT(name,ty) \
+extern ty THEM(name)(int); \
+ty US(name)(int x) { return x * x; }
+
+SMALLINT(si8u, unsigned char)
+SMALLINT(si8s, signed char)
+SMALLINT(si16u, unsigned short)
+SMALLINT(si16s, signed short)
+
/* Test function, calling the functions compiled by the other compiler */
#define CALLPRINT(name,ty,init) \
@@ -207,6 +218,10 @@ RETURN(ru8,U8,init_U8)
extern void THEM(test) (void);
void US(test) (void)
{
+ printf("si8u: %d\n", THEM(si8u)(12345));
+ printf("si8s: %d\n", THEM(si8s)(12345));
+ printf("si16u: %d\n", THEM(si16u)(1234567));
+ printf("si16s: %d\n", THEM(si16s)(1234567));
CALLPRINT(s1,S1,init_S1)
CALLPRINT(s2,S2,init_S2)
CALLPRINT(s3,S3,init_S3)
diff --git a/test/regression/packedstruct1.c b/test/regression/packedstruct1.c
index ac68c698..b805c92a 100644
--- a/test/regression/packedstruct1.c
+++ b/test/regression/packedstruct1.c
@@ -23,9 +23,9 @@ void test1(void)
struct s1 s1;
printf("sizeof(struct s1) = %d\n", szof(s1));
printf("precomputed sizeof(struct s1) = %d\n", bszof(s1));
- printf("offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetOf(s1,x), offsetOf(s1,y), offsetOf(s1,z));
- printf("precomputed offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
boffsetof(s1,x), boffsetof(s1,y), boffsetof(s1,z));
s1.x = 123; s1.y = -456; s1.z = 3.14159;
printf("s1 = {x = %d, y = %d, z = %.5f}\n\n", s1.x, s1.y, s1.z);
@@ -44,9 +44,9 @@ void test2(void)
printf("sizeof(struct s2) = %d\n", szof(s2));
printf("precomputed sizeof(struct s2) = %d\n", bszof(s2));
printf("&s2 mod 16 = %d\n", ((int) &s2) & 0xF);
- printf("offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetOf(s2,x), offsetOf(s2,y), offsetOf(s2,z));
- printf("precomputed offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
boffsetof(s2,x), boffsetof(s2,y), boffsetof(s2,z));
s2.x = 12345; s2.y = -456; s2.z = 3.14159;
printf("s2 = {x = %d, y = %d, z = %.5f}\n\n", s2.x, s2.y, s2.z);
@@ -73,8 +73,8 @@ void test3(void)
printf("sizeof(struct s3) = %d\n", szof(s3));
printf("precomputed sizeof(struct s3) = %d\n", bszof(s3));
- printf("offsetOf(s) = %d\n", offsetOf(s3,s));
- printf("precomputed offsetOf(s) = %d\n", boffsetof(s3,s));
+ printf("offsetof(s) = %d\n", offsetOf(s3,s));
+ printf("precomputed offsetof(s) = %d\n", boffsetof(s3,s));
s3.x = 123;
s3.y = 45678;
s3.z = 0x80000001U;
@@ -103,9 +103,9 @@ void test4(void)
printf("sizeof(struct s4) = %d\n", szof(s4));
printf("precomputed sizeof(struct s4) = %d\n", bszof(s4));
- printf("offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetOf(s4,x), offsetOf(s4,y), offsetOf(s4,z));
- printf("precomputed offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
boffsetof(s4,x), boffsetof(s4,y), boffsetof(s4,z));
s4.x = 123; s4.y = -456; s4.z = 3.14159;
printf("s4 = {x = %d, y = %d, z = %.5f}\n\n", s4.x, s4.y, s4.z);
@@ -121,9 +121,9 @@ void test5(void)
printf("sizeof(struct s5) = %d\n", szof(s5));
printf("precomputed sizeof(struct s5) = %d\n", bszof(s5));
- printf("offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetOf(s5,x), offsetOf(s5,y), offsetOf(s5,z));
- printf("precomputed offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
boffsetof(s5,x), boffsetof(s5,y), boffsetof(s5,z));
s5.x = 123; s5.y = -456; s5.z = 3.14159;
printf("s5 = {x = %d, y = %d, z = %.5f}\n\n", s5.x, s5.y, s5.z);
@@ -139,9 +139,9 @@ void test6(void)
printf("sizeof(struct s6) = %d\n", szof(s6));
printf("precomputed sizeof(struct s6) = %d\n", bszof(s6));
- printf("offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetOf(s6,x), offsetOf(s6,y), offsetOf(s6,z));
- printf("precomputed offsetOf(x) = %d, offsetOf(y) = %d, offsetOf(z) = %d\n",
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
boffsetof(s6,x), boffsetof(s6,y), boffsetof(s6,z));
s62.x = 123; s62.y = -456; s62.z = 3.14159;
printf("s62 = {x = %d, y = %d, z = %.5f}\n\n", s62.x, s62.y, s62.z);
diff --git a/x86/Asmexpand.ml b/x86/Asmexpand.ml
index 16426ce3..b8353046 100644
--- a/x86/Asmexpand.ml
+++ b/x86/Asmexpand.ml
@@ -251,7 +251,7 @@ let expand_builtin_va_start_32 r =
invalid_arg "Fatal error: va_start used in non-vararg function";
let ofs =
Int32.(add (add !PrintAsmaux.current_function_stacksize 4l)
- (mul 4l (Z.to_int32 (Conventions1.size_arguments
+ (mul 4l (Z.to_int32 (Conventions.size_arguments
(get_current_function_sig ()))))) in
emit (Pleal (RAX, linear_addr RSP (Z.of_uint32 ofs)));
emit (Pmovl_mr (linear_addr r _0z, RAX))
@@ -506,7 +506,7 @@ let expand_instruction instr =
(* Save the registers *)
emit (Pleaq (R10, linear_addr RSP (Z.of_uint save_regs)));
emit (Pcall_s (intern_string "__compcert_va_saveregs",
- {sig_args = []; sig_res = None; sig_cc = cc_default}))
+ {sig_args = []; sig_res = Tvoid; sig_cc = cc_default}))
end;
(* Stack chaining *)
let fullsz = sz + 8 in
diff --git a/x86/Asmgen.v b/x86/Asmgen.v
index 73e3263e..99e9fc2b 100644
--- a/x86/Asmgen.v
+++ b/x86/Asmgen.v
@@ -636,9 +636,14 @@ Definition transl_op
(** Translation of memory loads and stores *)
-Definition transl_load (chunk: memory_chunk)
+Definition transl_load
+ (trap : trapping_mode)
+ (chunk: memory_chunk)
(addr: addressing) (args: list mreg) (dest: mreg)
(k: code) : res code :=
+ match trap with
+ | NOTRAP => Error (msg "Asmgen.transl_load x86 does not support non trapping loads")
+ | TRAP =>
do am <- transl_addressing addr args;
match chunk with
| Mint8unsigned =>
@@ -659,6 +664,7 @@ Definition transl_load (chunk: memory_chunk)
do r <- freg_of dest; OK(Pmovsd_fm r am :: k)
| _ =>
Error (msg "Asmgen.transl_load")
+ end
end.
Definition transl_store (chunk: memory_chunk)
@@ -699,8 +705,8 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
loadind RSP f.(fn_link_ofs) Tptr AX k1)
| Mop op args res =>
transl_op op args res k
- | Mload chunk addr args dst =>
- transl_load chunk addr args dst k
+ | Mload trap chunk addr args dst =>
+ transl_load trap chunk addr args dst k
| Mstore chunk addr args src =>
transl_store chunk addr args src k
| Mcall sig (inl reg) =>
diff --git a/x86/Asmgenproof.v b/x86/Asmgenproof.v
index f1fd41e3..6886b2fd 100644
--- a/x86/Asmgenproof.v
+++ b/x86/Asmgenproof.v
@@ -235,11 +235,11 @@ Proof.
Qed.
Remark transl_load_label:
- forall chunk addr args dest k c,
- transl_load chunk addr args dest k = OK c ->
+ forall trap chunk addr args dest k c,
+ transl_load trap chunk addr args dest k = OK c ->
tail_nolabel k c.
Proof.
- intros. monadInv H. destruct chunk; TailNoLabel.
+ intros. destruct trap; try discriminate. monadInv H. destruct chunk; TailNoLabel.
Qed.
Remark transl_store_label:
@@ -567,6 +567,12 @@ Opaque loadind.
split. eapply agree_set_undef_mreg; eauto. congruence.
simpl; congruence.
+- (* Mload notrap *) (* isn't there a nicer way? *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
- (* Mstore *)
assert (eval_addressing tge sp addr rs##args = Some a).
rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
diff --git a/x86/Asmgenproof1.v b/x86/Asmgenproof1.v
index fd88954e..7cff1047 100644
--- a/x86/Asmgenproof1.v
+++ b/x86/Asmgenproof1.v
@@ -1464,8 +1464,8 @@ Qed.
(** Translation of memory loads. *)
Lemma transl_load_correct:
- forall chunk addr args dest k c (rs: regset) m a v,
- transl_load chunk addr args dest k = OK c ->
+ forall trap chunk addr args dest k c (rs: regset) m a v,
+ transl_load trap chunk addr args dest k = OK c ->
eval_addressing ge (rs#RSP) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
@@ -1473,7 +1473,9 @@ Lemma transl_load_correct:
/\ rs'#(preg_of dest) = v
/\ forall r, data_preg r = true -> r <> preg_of dest -> rs'#r = rs#r.
Proof.
- unfold transl_load; intros. monadInv H.
+ unfold transl_load; intros.
+ destruct trap; simpl; try discriminate.
+ monadInv H.
exploit transl_addressing_mode_correct; eauto. intro EA.
assert (EA': eval_addrmode ge x rs = a). destruct a; simpl in H1; try discriminate; inv EA; auto.
set (rs2 := nextinstr_nf (rs#(preg_of dest) <- v)).
diff --git a/x86/Builtins1.v b/x86/Builtins1.v
index 6103cc4c..f1d60961 100644
--- a/x86/Builtins1.v
+++ b/x86/Builtins1.v
@@ -33,10 +33,10 @@ Definition platform_builtin_table : list (string * platform_builtin) :=
Definition platform_builtin_sig (b: platform_builtin) : signature :=
match b with
| BI_fmin | BI_fmax =>
- mksignature (Tfloat :: Tfloat :: nil) (Some Tfloat) cc_default
+ mksignature (Tfloat :: Tfloat :: nil) Tfloat cc_default
end.
-Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (proj_sig_res (platform_builtin_sig b)) :=
+Definition platform_builtin_sem (b: platform_builtin) : builtin_sem (sig_res (platform_builtin_sig b)) :=
match b with
| BI_fmin =>
mkbuiltin_n2t Tfloat Tfloat Tfloat
diff --git a/x86/CBuiltins.ml b/x86/CBuiltins.ml
index f4f40a31..e7f714c7 100644
--- a/x86/CBuiltins.ml
+++ b/x86/CBuiltins.ml
@@ -73,9 +73,6 @@ let builtins = {
(TVoid [], [TPtr(TInt(IUShort, []), []); TInt(IUShort, [])], false);
"__builtin_write32_reversed",
(TVoid [], [TPtr(TInt(IUInt, []), []); TInt(IUInt, [])], false);
- (* no operation *)
- "__builtin_nop",
- (TVoid [], [], false);
]
}
diff --git a/x86/CSE2deps.v b/x86/CSE2deps.v
new file mode 100644
index 00000000..f4d9e254
--- /dev/null
+++ b/x86/CSE2deps.v
@@ -0,0 +1,24 @@
+Require Import BoolEqual Coqlib.
+Require Import AST Integers Floats.
+Require Import Values Memory Globalenvs Events.
+Require Import Op.
+
+Definition can_swap_accesses_ofs ofsr chunkr ofsw chunkw :=
+ (0 <=? ofsw) && (ofsw <=? (Ptrofs.modulus - largest_size_chunk))
+ && (0 <=? ofsr) && (ofsr <=? (Ptrofs.modulus - largest_size_chunk))
+ && ((ofsw + size_chunk chunkw <=? ofsr) ||
+ (ofsr + size_chunk chunkr <=? ofsw)).
+
+Definition may_overlap chunk addr args chunk' addr' args' :=
+ match addr, addr', args, args' with
+ | (Aindexed ofs), (Aindexed ofs'),
+ (base :: nil), (base' :: nil) =>
+ if peq base base'
+ then negb (can_swap_accesses_ofs ofs' chunk' ofs chunk)
+ else true
+ | (Aglobal symb ofs), (Aglobal symb' ofs'), nil, nil =>
+ if peq symb symb'
+ then negb (can_swap_accesses_ofs (Ptrofs.unsigned ofs') chunk' (Ptrofs.unsigned ofs) chunk)
+ else false
+ | _, _, _, _ => true
+ end.
diff --git a/x86/CSE2depsproof.v b/x86/CSE2depsproof.v
new file mode 100644
index 00000000..1e913254
--- /dev/null
+++ b/x86/CSE2depsproof.v
@@ -0,0 +1,253 @@
+Require Import Coqlib Maps Errors Integers Floats Lattice Kildall.
+Require Import AST Linking.
+Require Import Memory Registers Op RTL Maps.
+
+Require Import Globalenvs Values.
+Require Import Linking Values Memory Globalenvs Events Smallstep.
+Require Import Registers Op RTL.
+Require Import CSE2 CSE2deps.
+Require Import Lia.
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Section MEMORY_WRITE.
+ Variable m m2 : mem.
+ Variable chunkw chunkr : memory_chunk.
+ Variable base : val.
+
+ Variable addrw addrr valw : val.
+ Hypothesis STORE : Mem.storev chunkw m addrw valw = Some m2.
+
+ Section INDEXED_AWAY.
+ Variable ofsw ofsr : Z.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aindexed ofsw) (base :: nil) = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aindexed ofsr) (base :: nil) = Some addrr.
+
+ Lemma load_store_away1 :
+ forall RANGEW : 0 <= ofsw <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= ofsr <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : ofsw + size_chunk chunkw <= ofsr
+ \/ ofsr + size_chunk chunkr <= ofsw,
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ try change (Ptrofs.modulus - largest_size_chunk) with 4294967288 in *.
+ try change (Ptrofs.modulus - largest_size_chunk) with 18446744073709551608 in *.
+ destruct addrr ; simpl in * ; trivial.
+ unfold eval_addressing, eval_addressing32, eval_addressing64 in *.
+ destruct Archi.ptr64 eqn:PTR64; destruct base; simpl in *; try discriminate.
+ rewrite PTR64 in *.
+
+ inv ADDRR.
+ inv ADDRW.
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+
+ all: try (destruct (Ptrofs.unsigned_add_either i0
+ (Ptrofs.of_int (Int.repr ofsr))) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i0
+ (Ptrofs.of_int64 (Int64.repr ofsr))) as [OFSR | OFSR];
+ rewrite OFSR).
+ all: try (destruct (Ptrofs.unsigned_add_either i0
+ (Ptrofs.of_int (Int.repr ofsw))) as [OFSW | OFSW];
+ rewrite OFSW).
+ all: try (destruct (Ptrofs.unsigned_add_either i0
+ (Ptrofs.of_int64 (Int64.repr ofsw))) as [OFSW | OFSW];
+ rewrite OFSW).
+
+ all: unfold Ptrofs.of_int64.
+ all: unfold Ptrofs.of_int.
+
+
+ all: repeat rewrite Int.unsigned_repr by (change Int.max_unsigned with 4294967295; lia).
+ all: repeat rewrite Ptrofs.unsigned_repr by (change Ptrofs.max_unsigned with 4294967295; lia).
+ all: repeat rewrite Int64.unsigned_repr by (change Int64.max_unsigned with 18446744073709551615; lia).
+ all: repeat rewrite Ptrofs.unsigned_repr by (change Ptrofs.max_unsigned with 18446744073709551615; lia).
+
+ all: try change Ptrofs.modulus with 4294967296.
+ all: try change Ptrofs.modulus with 18446744073709551616.
+
+ all: intuition lia.
+ Qed.
+
+ Theorem load_store_away :
+ can_swap_accesses_ofs ofsr chunkr ofsw chunkw = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_away1.
+ all: tauto.
+ Qed.
+ End INDEXED_AWAY.
+
+ Section DIFFERENT_GLOBALS.
+ Variable ofsw ofsr : ptrofs.
+ Hypothesis symw symr : ident.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aglobal symw ofsw) nil = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aglobal symr ofsr) nil = Some addrr.
+
+ Lemma ptr64_cases:
+ forall {T : Type},
+ forall b : bool,
+ forall x y : T,
+ (if b then (if b then x else y) else (if b then y else x)) = x.
+ Proof.
+ destruct b; reflexivity.
+ Qed.
+
+ (* not needed
+ Lemma bool_cases_same:
+ forall {T : Type},
+ forall b : bool,
+ forall x : T,
+ (if b then x else x) = x.
+ Proof.
+ destruct b; reflexivity.
+ Qed.
+ *)
+
+ Lemma load_store_diff_globals :
+ symw <> symr ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+ unfold eval_addressing in *.
+ simpl in *.
+ rewrite ptr64_cases in ADDRR.
+ rewrite ptr64_cases in ADDRW.
+ unfold Genv.symbol_address in *.
+ unfold Genv.find_symbol in *.
+ destruct ((Genv.genv_symb genv) ! symw) as [bw |] eqn:SYMW; inv ADDRW.
+ 2: simpl in STORE; discriminate.
+ destruct ((Genv.genv_symb genv) ! symr) as [br |] eqn:SYMR; inv ADDRR.
+ 2: reflexivity.
+ assert (br <> bw).
+ {
+ intro EQ.
+ subst br.
+ assert (symr = symw).
+ {
+ eapply Genv.genv_vars_inj; eauto.
+ }
+ congruence.
+ }
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := bw).
+ - exact STORE.
+ - left. assumption.
+ Qed.
+ End DIFFERENT_GLOBALS.
+
+ Section SAME_GLOBALS.
+ Variable ofsw ofsr : ptrofs.
+ Hypothesis sym : ident.
+ Hypothesis ADDRW : eval_addressing genv sp
+ (Aglobal sym ofsw) nil = Some addrw.
+ Hypothesis ADDRR : eval_addressing genv sp
+ (Aglobal sym ofsr) nil = Some addrr.
+
+ Lemma load_store_glob_away1 :
+ forall RANGEW : 0 <= (Ptrofs.unsigned ofsw) <= Ptrofs.modulus - largest_size_chunk,
+ forall RANGER : 0 <= (Ptrofs.unsigned ofsr) <= Ptrofs.modulus - largest_size_chunk,
+ forall SWAPPABLE : (Ptrofs.unsigned ofsw) + size_chunk chunkw <= (Ptrofs.unsigned ofsr)
+ \/ (Ptrofs.unsigned ofsr) + size_chunk chunkr <= (Ptrofs.unsigned ofsw),
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intros.
+
+ pose proof (max_size_chunk chunkr) as size_chunkr_bounded.
+ pose proof (max_size_chunk chunkw) as size_chunkw_bounded.
+ unfold largest_size_chunk in size_chunkr_bounded, size_chunkw_bounded.
+ try change (Ptrofs.modulus - largest_size_chunk) with 4294967288 in *.
+ try change (Ptrofs.modulus - largest_size_chunk) with 18446744073709551608 in *.
+ unfold eval_addressing, eval_addressing32, eval_addressing64 in *.
+
+ rewrite ptr64_cases in ADDRR.
+ rewrite ptr64_cases in ADDRW.
+ unfold Genv.symbol_address in *.
+ inv ADDRR.
+ inv ADDRW.
+ destruct (Genv.find_symbol genv sym).
+ 2: discriminate.
+
+ eapply Mem.load_store_other with (chunk := chunkw) (v := valw) (b := b).
+ exact STORE.
+ right.
+ tauto.
+ Qed.
+
+ Lemma load_store_glob_away :
+ (can_swap_accesses_ofs (Ptrofs.unsigned ofsr) chunkr (Ptrofs.unsigned ofsw) chunkw) = true ->
+ Mem.loadv chunkr m2 addrr = Mem.loadv chunkr m addrr.
+ Proof.
+ intro SWAP.
+ unfold can_swap_accesses_ofs in SWAP.
+ repeat rewrite andb_true_iff in SWAP.
+ repeat rewrite orb_true_iff in SWAP.
+ repeat rewrite Z.leb_le in SWAP.
+ apply load_store_glob_away1.
+ all: tauto.
+ Qed.
+ End SAME_GLOBALS.
+End MEMORY_WRITE.
+End SOUNDNESS.
+
+
+Section SOUNDNESS.
+ Variable F V : Type.
+ Variable genv: Genv.t F V.
+ Variable sp : val.
+
+Lemma may_overlap_sound:
+ forall m m' : mem,
+ forall chunk addr args chunk' addr' args' v a a' rs,
+ (eval_addressing genv sp addr (rs ## args)) = Some a ->
+ (eval_addressing genv sp addr' (rs ## args')) = Some a' ->
+ (may_overlap chunk addr args chunk' addr' args') = false ->
+ (Mem.storev chunk m a v) = Some m' ->
+ (Mem.loadv chunk' m' a') = (Mem.loadv chunk' m a').
+Proof.
+ intros until rs.
+ intros ADDR ADDR' OVERLAP STORE.
+ destruct addr; destruct addr'; try discriminate.
+ { (* Aindexed / Aindexed *)
+ destruct args as [ | base [ | ]]. 1,3: discriminate.
+ destruct args' as [ | base' [ | ]]. 1,3: discriminate.
+ simpl in OVERLAP.
+ destruct (peq base base'). 2: discriminate.
+ subst base'.
+ destruct (can_swap_accesses_ofs z0 chunk' z chunk) eqn:SWAP.
+ 2: discriminate.
+ simpl in *.
+ eapply load_store_away; eassumption.
+ }
+ { (* Aglobal / Aglobal *)
+ destruct args. 2: discriminate.
+ destruct args'. 2: discriminate.
+ simpl in *.
+ destruct (peq i i1).
+ {
+ subst i1.
+ rewrite negb_false_iff in OVERLAP.
+ eapply load_store_glob_away; eassumption.
+ }
+ eapply load_store_diff_globals; eassumption.
+ }
+Qed.
+
+End SOUNDNESS.
diff --git a/x86/Conventions1.v b/x86/Conventions1.v
index 35d555f9..d9f5b8fa 100644
--- a/x86/Conventions1.v
+++ b/x86/Conventions1.v
@@ -100,22 +100,20 @@ Definition is_float_reg (r: mreg) :=
function with one integer result. *)
Definition loc_result_32 (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One AX
- | Some (Tint | Tany32) => One AX
- | Some (Tfloat | Tsingle) => One FP0
- | Some Tany64 => One X0
- | Some Tlong => Twolong DX AX
+ match proj_sig_res s with
+ | Tint | Tany32 => One AX
+ | Tfloat | Tsingle => One FP0
+ | Tany64 => One X0
+ | Tlong => Twolong DX AX
end.
(** In 64 bit mode, he result value of a function is passed back to
the caller in registers [AX] or [X0]. *)
Definition loc_result_64 (s: signature) : rpair mreg :=
- match s.(sig_res) with
- | None => One AX
- | Some (Tint | Tlong | Tany32 | Tany64) => One AX
- | Some (Tfloat | Tsingle) => One X0
+ match proj_sig_res s with
+ | Tint | Tlong | Tany32 | Tany64 => One AX
+ | Tfloat | Tsingle => One X0
end.
Definition loc_result :=
@@ -127,8 +125,8 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
- intros. unfold proj_sig_res, loc_result, loc_result_32, loc_result_64, mreg_type;
- destruct Archi.ptr64; destruct (sig_res sig) as [[]|]; auto.
+ intros. unfold loc_result, loc_result_32, loc_result_64, mreg_type;
+ destruct Archi.ptr64; destruct (proj_sig_res sig); auto.
Qed.
(** The result locations are caller-save registers *)
@@ -138,7 +136,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros. unfold loc_result, loc_result_32, loc_result_64, is_callee_save;
- destruct Archi.ptr64; destruct (sig_res s) as [[]|]; simpl; auto.
+ destruct Archi.ptr64; destruct (proj_sig_res s); simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
@@ -148,14 +146,14 @@ Lemma loc_result_pair:
match loc_result sg with
| One _ => True
| Twolong r1 r2 =>
- r1 <> r2 /\ sg.(sig_res) = Some Tlong
+ r1 <> r2 /\ proj_sig_res sg = Tlong
/\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
/\ Archi.ptr64 = false
end.
Proof.
intros.
unfold loc_result, loc_result_32, loc_result_64, mreg_type;
- destruct Archi.ptr64; destruct (sig_res sg) as [[]|]; auto.
+ destruct Archi.ptr64; destruct (proj_sig_res sg); auto.
split; auto. congruence.
Qed.
@@ -164,7 +162,7 @@ Qed.
Lemma loc_result_exten:
forall s1 s2, s1.(sig_res) = s2.(sig_res) -> loc_result s1 = loc_result s2.
Proof.
- intros. unfold loc_result, loc_result_32, loc_result_64.
+ intros. unfold loc_result, loc_result_32, loc_result_64, proj_sig_res.
destruct Archi.ptr64; rewrite H; auto.
Qed.
@@ -223,36 +221,6 @@ Definition loc_arguments (s: signature) : list (rpair loc) :=
then loc_arguments_64 s.(sig_args) 0 0 0
else loc_arguments_32 s.(sig_args) 0.
-(** [size_arguments s] returns the number of [Outgoing] slots used
- to call a function with signature [s]. *)
-
-Fixpoint size_arguments_32
- (tyl: list typ) (ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => ofs
- | ty :: tys => size_arguments_32 tys (ofs + typesize ty)
- end.
-
-Fixpoint size_arguments_64 (tyl: list typ) (ir fr ofs: Z) {struct tyl} : Z :=
- match tyl with
- | nil => ofs
- | (Tint | Tlong | Tany32 | Tany64) :: tys =>
- match list_nth_z int_param_regs ir with
- | None => size_arguments_64 tys ir fr (ofs + 2)
- | Some ireg => size_arguments_64 tys (ir + 1) fr ofs
- end
- | (Tfloat | Tsingle) :: tys =>
- match list_nth_z float_param_regs fr with
- | None => size_arguments_64 tys ir fr (ofs + 2)
- | Some freg => size_arguments_64 tys ir (fr + 1) ofs
- end
- end.
-
-Definition size_arguments (s: signature) : Z :=
- if Archi.ptr64
- then size_arguments_64 s.(sig_args) 0 0 0
- else size_arguments_32 s.(sig_args) 0.
-
(** Argument locations are either caller-save registers or [Outgoing]
stack slots at nonnegative offsets. *)
@@ -354,123 +322,22 @@ Qed.
Hint Resolve loc_arguments_acceptable: locs.
-(** The offsets of [Outgoing] arguments are below [size_arguments s]. *)
-
-Remark size_arguments_32_above:
- forall tyl ofs0, ofs0 <= size_arguments_32 tyl ofs0.
+Lemma loc_arguments_main:
+ loc_arguments signature_main = nil.
Proof.
- induction tyl; simpl; intros.
- omega.
- apply Z.le_trans with (ofs0 + typesize a); auto.
- generalize (typesize_pos a); omega.
+ unfold loc_arguments; destruct Archi.ptr64; reflexivity.
Qed.
-Remark size_arguments_64_above:
- forall tyl ir fr ofs0,
- ofs0 <= size_arguments_64 tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- omega.
- assert (A: ofs0 <=
- match list_nth_z int_param_regs ir with
- | Some _ => size_arguments_64 tyl (ir + 1) fr ofs0
- | None => size_arguments_64 tyl ir fr (ofs0 + 2)
- end).
- { destruct (list_nth_z int_param_regs ir); eauto.
- apply Z.le_trans with (ofs0 + 2); auto. omega. }
- assert (B: ofs0 <=
- match list_nth_z float_param_regs fr with
- | Some _ => size_arguments_64 tyl ir (fr + 1) ofs0
- | None => size_arguments_64 tyl ir fr (ofs0 + 2)
- end).
- { destruct (list_nth_z float_param_regs fr); eauto.
- apply Z.le_trans with (ofs0 + 2); auto. omega. }
- destruct a; auto.
-Qed.
+(** ** Normalization of function results *)
-Lemma size_arguments_above:
- forall s, size_arguments s >= 0.
-Proof.
- intros; unfold size_arguments. apply Z.le_ge.
- destruct Archi.ptr64; [apply size_arguments_64_above|apply size_arguments_32_above].
-Qed.
+(** In the x86 ABI, a return value of type "char" is returned in
+ register AL, leaving the top 24 bits of EAX unspecified.
+ Likewise, a return value of type "short" is returned in register
+ AH, leaving the top 16 bits of EAX unspecified. Hence, return
+ values of small integer types need re-normalization after calls. *)
-Lemma loc_arguments_32_bounded:
- forall ofs ty tyl ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_32 tyl ofs0)) ->
- ofs + typesize ty <= size_arguments_32 tyl ofs0.
-Proof.
- induction tyl as [ | t l]; simpl; intros x IN.
-- contradiction.
-- rewrite in_app_iff in IN; destruct IN as [IN|IN].
-+ apply Z.le_trans with (x + typesize t); [|apply size_arguments_32_above].
- Ltac decomp :=
- match goal with
- | [ H: _ \/ _ |- _ ] => destruct H; decomp
- | [ H: S _ _ _ = S _ _ _ |- _ ] => inv H
- | [ H: False |- _ ] => contradiction
+Definition return_value_needs_normalization (t: rettype) : bool :=
+ match t with
+ | Tint8signed | Tint8unsigned | Tint16signed | Tint16unsigned => true
+ | _ => false
end.
- destruct t; simpl in IN; decomp; simpl; omega.
-+ apply IHl; auto.
-Qed.
-
-Lemma loc_arguments_64_bounded:
- forall ofs ty tyl ir fr ofs0,
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments_64 tyl ir fr ofs0)) ->
- ofs + typesize ty <= size_arguments_64 tyl ir fr ofs0.
-Proof.
- induction tyl; simpl; intros.
- contradiction.
- assert (T: forall ty0, typesize ty0 <= 2).
- { destruct ty0; simpl; omega. }
- assert (A: forall ty0,
- In (S Outgoing ofs ty) (regs_of_rpairs
- match list_nth_z int_param_regs ir with
- | Some ireg =>
- One (R ireg) :: loc_arguments_64 tyl (ir + 1) fr ofs0
- | None => One (S Outgoing ofs0 ty0) :: loc_arguments_64 tyl ir fr (ofs0 + 2)
- end) ->
- ofs + typesize ty <=
- match list_nth_z int_param_regs ir with
- | Some _ => size_arguments_64 tyl (ir + 1) fr ofs0
- | None => size_arguments_64 tyl ir fr (ofs0 + 2)
- end).
- { intros. destruct (list_nth_z int_param_regs ir); simpl in H0; destruct H0.
- - discriminate.
- - eapply IHtyl; eauto.
- - inv H0. apply Z.le_trans with (ofs + 2). specialize (T ty). omega. apply size_arguments_64_above.
- - eapply IHtyl; eauto. }
- assert (B: forall ty0,
- In (S Outgoing ofs ty) (regs_of_rpairs
- match list_nth_z float_param_regs fr with
- | Some ireg =>
- One (R ireg) :: loc_arguments_64 tyl ir (fr + 1) ofs0
- | None => One (S Outgoing ofs0 ty0) :: loc_arguments_64 tyl ir fr (ofs0 + 2)
- end) ->
- ofs + typesize ty <=
- match list_nth_z float_param_regs fr with
- | Some _ => size_arguments_64 tyl ir (fr + 1) ofs0
- | None => size_arguments_64 tyl ir fr (ofs0 + 2)
- end).
- { intros. destruct (list_nth_z float_param_regs fr); simpl in H0; destruct H0.
- - discriminate.
- - eapply IHtyl; eauto.
- - inv H0. apply Z.le_trans with (ofs + 2). specialize (T ty). omega. apply size_arguments_64_above.
- - eapply IHtyl; eauto. }
- destruct a; eauto.
-Qed.
-
-Lemma loc_arguments_bounded:
- forall (s: signature) (ofs: Z) (ty: typ),
- In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments s)) ->
- ofs + typesize ty <= size_arguments s.
-Proof.
- unfold loc_arguments, size_arguments; intros.
- destruct Archi.ptr64; eauto using loc_arguments_32_bounded, loc_arguments_64_bounded.
-Qed.
-
-Lemma loc_arguments_main:
- loc_arguments signature_main = nil.
-Proof.
- unfold loc_arguments; destruct Archi.ptr64; reflexivity.
-Qed.
diff --git a/x86/DuplicateOpcodeHeuristic.ml b/x86/DuplicateOpcodeHeuristic.ml
new file mode 100644
index 00000000..2ec314c1
--- /dev/null
+++ b/x86/DuplicateOpcodeHeuristic.ml
@@ -0,0 +1,27 @@
+(* open Camlcoq *)
+open Op
+open Integers
+
+let opcode_heuristic code cond ifso ifnot is_loop_header =
+ match cond with
+ | Ccompimm (c, n) | Ccompuimm (c, n) -> if n == Integers.Int.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccomplimm (c, n) | Ccompluimm (c, n) -> if n == Integers.Int64.zero then (match c with
+ | Clt | Cle -> Some false
+ | Cgt | Cge -> Some true
+ | _ -> None
+ ) else None
+ | Ccompf c | Ccompfs c -> (match c with
+ | Ceq -> Some false
+ | Cne -> Some true
+ | _ -> None
+ )
+ | Cnotcompf c | Cnotcompfs c -> (match c with
+ | Ceq -> Some true
+ | Cne -> Some false
+ | _ -> None
+ )
+ | _ -> None
diff --git a/x86/Op.v b/x86/Op.v
index 16d75426..15672bbe 100644
--- a/x86/Op.v
+++ b/x86/Op.v
@@ -742,6 +742,37 @@ Proof with (try exact I; try reflexivity).
unfold Val.select. destruct (eval_condition c vl m). apply Val.normalize_type. exact I.
Qed.
+
+Definition is_trapping_op (op : operation) :=
+ match op with
+ | Odiv | Odivl | Odivu | Odivlu
+ | Omod | Omodl | Omodu | Omodlu
+ | Oshrximm _ | Oshrxlimm _
+ | Ointoffloat
+ | Ointofsingle
+ | Olongoffloat
+ | Olongofsingle
+ | Osingleofint
+ | Osingleoflong
+ | Ofloatofint
+ | Ofloatoflong
+ | Olea _ | Oleal _ (* TODO this is suboptimal *) => true
+ | _ => false
+ end.
+
+Lemma is_trapping_op_sound:
+ forall op vl sp m,
+ op <> Omove ->
+ is_trapping_op op = false ->
+ (List.length vl) = (List.length (fst (type_of_operation op))) ->
+ eval_operation genv sp op vl m <> None.
+Proof.
+ destruct op; intros; simpl in *; try congruence.
+ all: try (destruct vl as [ | vh1 vl1]; try discriminate).
+ all: try (destruct vl1 as [ | vh2 vl2]; try discriminate).
+ all: try (destruct vl2 as [ | vh3 vl3]; try discriminate).
+ all: try (destruct vl3 as [ | vh4 vl4]; try discriminate).
+Qed.
End SOUNDNESS.
(** * Manipulating and transforming operations *)
@@ -1199,6 +1230,21 @@ Proof.
unfold eval_addressing; intros. destruct Archi.ptr64; eauto using eval_addressing32_inj, eval_addressing64_inj.
Qed.
+Lemma eval_addressing_inj_none:
+ forall addr sp1 vl1 sp2 vl2,
+ (forall id ofs,
+ In id (globals_addressing addr) ->
+ Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
+ Val.inject f sp1 sp2 ->
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing ge1 sp1 addr vl1 = None ->
+ eval_addressing ge2 sp2 addr vl2 = None.
+Proof.
+ intros until vl2. intros Hglobal Hinjsp Hinjvl.
+ destruct addr; simpl in *;
+ inv Hinjvl; trivial; try discriminate; inv H0; trivial; try discriminate; inv H2; trivial; try discriminate.
+Qed.
+
Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
@@ -1425,6 +1471,19 @@ Proof.
destruct H1 as [v2 [A B]]. exists v2; split; auto. rewrite val_inject_lessdef; auto.
Qed.
+Lemma eval_addressing_lessdef_none:
+ forall sp addr vl1 vl2,
+ Val.lessdef_list vl1 vl2 ->
+ eval_addressing genv sp addr vl1 = None ->
+ eval_addressing genv sp addr vl2 = None.
+Proof.
+ intros until vl2. intros Hlessdef Heval1.
+ destruct addr; simpl in *;
+ inv Hlessdef; trivial; try discriminate;
+ inv H0; trivial; try discriminate;
+ inv H2; trivial; try discriminate.
+Qed.
+
End EVAL_LESSDEF.
(** Compatibility of the evaluation functions with memory injections. *)
@@ -1477,6 +1536,19 @@ Proof.
econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
Qed.
+Lemma eval_addressing_inject_none:
+ forall addr vl1 vl2,
+ Val.inject_list f vl1 vl2 ->
+ eval_addressing genv (Vptr sp1 Ptrofs.zero) addr vl1 = None ->
+ eval_addressing genv (Vptr sp2 Ptrofs.zero) (shift_stack_addressing delta addr) vl2 = None.
+Proof.
+ intros.
+ rewrite eval_shift_stack_addressing.
+ eapply eval_addressing_inj_none with (sp1 := Vptr sp1 Ptrofs.zero); eauto.
+ intros. apply symbol_address_inject.
+ econstructor; eauto. rewrite Ptrofs.add_zero_l; auto.
+Qed.
+
Lemma eval_operation_inject:
forall op vl1 vl2 v1 m1 m2,
Val.inject_list f vl1 vl2 ->
diff --git a/x86/ValueAOp.v b/x86/ValueAOp.v
index d0b8427a..e5584b6a 100644
--- a/x86/ValueAOp.v
+++ b/x86/ValueAOp.v
@@ -261,6 +261,25 @@ Proof.
apply of_optbool_sound. eapply eval_static_condition_sound; eauto.
apply select_sound; auto. eapply eval_static_condition_sound; eauto.
Qed.
-
+(*
+Theorem eval_static_addressing_sound_none:
+ forall addr vargs aargs,
+ eval_addressing ge (Vptr sp Ptrofs.zero) addr vargs = None ->
+ list_forall2 (vmatch bc) vargs aargs ->
+ (eval_static_addressing addr aargs) = Vbot.
+Proof.
+ unfold eval_addressing, eval_static_addressing.
+ intros until aargs. intros Heval_none Hlist.
+ destruct (Archi.ptr64).
+ inv Hlist.
+ destruct addr; trivial; discriminate.
+ inv H0.
+ destruct addr; trivial; try discriminate. simpl in *.
+ inv H2.
+ destruct addr; trivial; discriminate.
+ inv H3;
+ destruct addr; trivial; discriminate.
+Qed.
+*)
End SOUNDNESS.