mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 09:23:52 -05:00
Merge branch 'main' into armcom11and12
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
set -eo pipefail
|
||||
|
||||
# when in a VS Code or GitHub Codespaces devcontainer
|
||||
if [ -n "${REMOTE_CONTAINERS}" ]; then
|
||||
if [ -n "${REMOTE_CONTAINERS}" ] || [ -n "${CODESPACES}" ]; then
|
||||
this_dir=$(cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P)
|
||||
workspace_root=$(realpath ${this_dir}/..)
|
||||
|
||||
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -174,6 +174,10 @@ lang-swift:
|
||||
lang-snowball:
|
||||
- lib/compilers/snowball.ts
|
||||
- etc/config/snowball.*.properties
|
||||
lang-tablegen:
|
||||
- lib/compilers/tablegen.ts
|
||||
- etc/config/tablegen.*.properties
|
||||
- static/modes/tablegen-mode.ts
|
||||
lang-toit:
|
||||
- lib/compilers/toit.ts
|
||||
- etc/config/toit.*.properties
|
||||
|
||||
21
README.md
21
README.md
@@ -5,15 +5,26 @@
|
||||
|
||||
# Compiler Explorer
|
||||
|
||||
Is an interactive compiler exploration website. Edit code in C, C++, C#, F#, Rust, Go, D, Haskell,
|
||||
Swift, Pascal, [ispc](https://ispc.github.io/), Python, Java, or any of the other [30+ supported languages](https://godbolt.org/api/languages) components, and see how that code looks after being compiled in real
|
||||
time.
|
||||
Is an interactive compiler exploration website. Edit code in C, C++, C#, F#, Rust, Go, D, Haskell, Swift, Pascal,
|
||||
[ispc](https://ispc.github.io/), Python, Java, or any of the other
|
||||
[30+ supported languages](https://godbolt.org/api/languages) components, and see how that code looks after being
|
||||
compiled in real time.
|
||||
|
||||
[Bug Report](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=%5BBUG%5D%3A+) · [Compiler Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-compilers&projects=&template=compiler_request.yml&title=%5BCOMPILER+REQUEST%5D%3A+) · [Feature Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request&projects=&template=feature_request.yml&title=%5BREQUEST%5D%3A+) · [Language Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-language&projects=&template=language_request.yml&title=%5BLANGUAGE+REQUEST%5D%3A+) · [Library Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-libs&projects=&template=library_request.yml&title=%5BLIB+REQUEST%5D%3A+) · [Report Vulnerability](https://github.com/compiler-explorer/compiler-explorer/security/advisories/new)
|
||||
[Bug Report](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=%5BBUG%5D%3A+)
|
||||
·
|
||||
[Compiler Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-compilers&projects=&template=compiler_request.yml&title=%5BCOMPILER+REQUEST%5D%3A+)
|
||||
·
|
||||
[Feature Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request&projects=&template=feature_request.yml&title=%5BREQUEST%5D%3A+)
|
||||
·
|
||||
[Language Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-language&projects=&template=language_request.yml&title=%5BLANGUAGE+REQUEST%5D%3A+)
|
||||
·
|
||||
[Library Request](https://github.com/compiler-explorer/compiler-explorer/issues/new?assignees=&labels=request%2Cnew-libs&projects=&template=library_request.yml&title=%5BLIB+REQUEST%5D%3A+)
|
||||
· [Report Vulnerability](https://github.com/compiler-explorer/compiler-explorer/security/advisories/new)
|
||||
|
||||
# Overview
|
||||
|
||||
Multiple compilers are supported for each language, many different tools and visualizations are available, and the UI layout is configurable (thanks to [GoldenLayout](https://www.golden-layout.com/)).
|
||||
Multiple compilers are supported for each language, many different tools and visualizations are available, and the UI
|
||||
layout is configurable (thanks to [GoldenLayout](https://www.golden-layout.com/)).
|
||||
|
||||
Try out at [godbolt.org](https://godbolt.org), or [run your own local instance](#running-a-local-instance). An overview
|
||||
of what the site lets you achieve, why it's useful, and how to use it is
|
||||
|
||||
13
docs/API.md
13
docs/API.md
@@ -99,7 +99,18 @@ Execution Only request example:
|
||||
"userArguments": "-O3",
|
||||
"executeParameters": {
|
||||
"args": ["arg1", "arg2"],
|
||||
"stdin": "hello, world!"
|
||||
"stdin": "hello, world!",
|
||||
"runtimeTools": [
|
||||
{
|
||||
"name": "env",
|
||||
"options": [
|
||||
{
|
||||
"name": "MYENV",
|
||||
"value": "123"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"compilerOptions": {
|
||||
"executorRequest": true
|
||||
|
||||
@@ -137,20 +137,20 @@ group.gnuasriscv32.compilers=gnuasriscv32g820:gnuasriscv32g1020:gnuasriscv32g114
|
||||
group.gnuasriscv32.groupName=RISC-V (32-bits) binutils
|
||||
group.gnuasriscv32.baseName=RISC-V (32-bits) binutils
|
||||
|
||||
compiler.gnuasriscv32g820.exe=/opt/compiler-explorer/riscv32/gcc-8.2.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-as
|
||||
compiler.gnuasriscv32g820.exe=/opt/compiler-explorer/riscv32/gcc-8.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-as
|
||||
compiler.gnuasriscv32g820.name=RISC-V binutils 2.31.1
|
||||
compiler.gnuasriscv32g820.semver=2.31.1
|
||||
compiler.gnuasriscv32g820.objdumper=/opt/compiler-explorer/riscv32/gcc-8.2.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-objdump
|
||||
compiler.gnuasriscv32g820.objdumper=/opt/compiler-explorer/riscv32/gcc-8.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump
|
||||
|
||||
compiler.gnuasriscv32g1020.exe=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-as
|
||||
compiler.gnuasriscv32g1020.exe=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-as
|
||||
compiler.gnuasriscv32g1020.name=RISC-V binutils 2.35.1
|
||||
compiler.gnuasriscv32g1020.semver=2.35.1
|
||||
compiler.gnuasriscv32g1020.objdumper=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-objdump
|
||||
compiler.gnuasriscv32g1020.objdumper=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump
|
||||
|
||||
compiler.gnuasriscv32g1140.exe=/opt/compiler-explorer/riscv32/gcc-11.4.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-as
|
||||
compiler.gnuasriscv32g1140.exe=/opt/compiler-explorer/riscv32/gcc-11.4.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-as
|
||||
compiler.gnuasriscv32g1140.name=RISC-V binutils 2.37.0
|
||||
compiler.gnuasriscv32g1140.semver=2.37.0
|
||||
compiler.gnuasriscv32g1140.objdumper=/opt/compiler-explorer/riscv32/gcc-11.4.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-objdump
|
||||
compiler.gnuasriscv32g1140.objdumper=/opt/compiler-explorer/riscv32/gcc-11.4.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump
|
||||
|
||||
compiler.gnuasriscv32g1320.exe=/opt/compiler-explorer/riscv32/gcc-13.2.0/riscv32-unknown-linux-gnu/bin/riscv32-unknown-linux-gnu-as
|
||||
compiler.gnuasriscv32g1320.name=RISC-V binutils 2.38.0
|
||||
|
||||
@@ -17,7 +17,7 @@ llvmDisassembler=/opt/compiler-explorer/clang-14.0.0/bin/llvm-dis
|
||||
|
||||
###############################
|
||||
# GCC for x86
|
||||
group.gcc86.compilers=g412:g447:g453:g464:g471:g472:g473:g474:g481:g482:g483:g484:g485:g490:g491:g492:g493:g494:g510:g520:g530:g540:g550:g6:g62:g63:g64:g71:g72:g73:g74:g75:g81:g82:g83:g84:g85:g91:g92:g93:g94:g95:g101:g102:g103:g104:g105:g111:g112:g113:g114:g121:g122:g123:g131:g132:gsnapshot:gcontracts-trunk:gcontract-labels-trunk:gcxx-modules-trunk:gcxx-coroutines-trunk:gcc-embed-trunk:gcc-static-analysis-trunk
|
||||
group.gcc86.compilers=g412:g447:g453:g464:g471:g472:g473:g474:g481:g482:g483:g484:g485:g490:g491:g492:g493:g494:g510:g520:g530:g540:g550:g6:g62:g63:g64:g71:g72:g73:g74:g75:g81:g82:g83:g84:g85:g91:g92:g93:g94:g95:g101:g102:g103:g104:g105:g111:g112:g113:g114:g121:g122:g123:g131:g132:gsnapshot:gcontracts-trunk:gcontract-labels-trunk:gcontracts-nonattr-trunk:gcxx-modules-trunk:gcxx-coroutines-trunk:gcc-embed-trunk:gcc-static-analysis-trunk
|
||||
group.gcc86.groupName=GCC x86-64
|
||||
group.gcc86.instructionSet=amd64
|
||||
group.gcc86.baseName=x86-64 gcc
|
||||
@@ -174,6 +174,12 @@ compiler.gcontract-labels-trunk.objdumper=/opt/compiler-explorer/gcc-snapshot/bi
|
||||
compiler.gcontract-labels-trunk.semver=(contract labels)
|
||||
compiler.gcontract-labels-trunk.isNightly=true
|
||||
compiler.gcontract-labels-trunk.notification=Experimental Contract Label Support; see <a href="https://github.com/lock3/gcc/wiki" target="_blank" rel="noopener noreferrer">Lock3's repository wiki<sup><small class="fas fa-external-link-alt opens-new-window" title="Opens in a new window"></small></sup></a>
|
||||
compiler.gcontracts-nonattr-trunk.exe=/opt/compiler-explorer/gcc-contracts-nonattr-trunk/bin/g++
|
||||
compiler.gcontracts-nonattr-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.gcontracts-nonattr-trunk.objdumper=/opt/compiler-explorer/gcc-snapshot/bin/objdump
|
||||
compiler.gcontracts-nonattr-trunk.semver=(contracts natural syntax)
|
||||
compiler.gcontracts-nonattr-trunk.isNightly=true
|
||||
compiler.gcontracts-nonattr-trunk.notification=Experimental Contract Natural Syntax Support; see <a href="https://open-std.org/JTC1/SC22/WG21/docs/papers/2023/p2961r0.pdf" target="_blank" rel="noopener noreferrer">P2961R0<sup><small class="fas fa-external-link-alt opens-new-window" title="Opens in a new window"></small></sup></a>
|
||||
compiler.gcxx-modules-trunk.exe=/opt/compiler-explorer/gcc-cxx-modules-trunk/bin/g++
|
||||
compiler.gcxx-modules-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.gcxx-modules-trunk.objdumper=/opt/compiler-explorer/gcc-snapshot/bin/objdump
|
||||
@@ -720,7 +726,7 @@ compiler.armv8-clang-trunk.options=-target aarch64-linux-gnu --gcc-toolchain=/op
|
||||
compiler.armv8-full-clang-trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
|
||||
compiler.armv8-full-clang-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.armv8-full-clang-trunk.objdumper=/opt/compiler-explorer/arm64/gcc-10.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/bin/objdump
|
||||
compiler.armv8-full-clang-trunk.semver=(trunk, all architectural features)
|
||||
compiler.armv8-full-clang-trunk.semver=(all architectural features, trunk)
|
||||
compiler.armv8-full-clang-trunk.isNightly=true
|
||||
# Arm v8-a with all supported architectural features
|
||||
compiler.armv8-full-clang-trunk.options=-target aarch64-linux-gnu --gcc-toolchain=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot -march=armv8.8-a+crypto+profile+rng+memtag+sve2+sve2-bitperm+sve2-sm4+sve2-aes+sve2-sha3+tme+brbe+f32mm+f64mm+fp16fml+ls64+sme+sme-f64f64+sme-i16i64+sme2
|
||||
@@ -3698,9 +3704,9 @@ libs.libbpf.liblink=bpf:dl:m
|
||||
libs.libbpf.description=Libbpf supports building BPF CO-RE-enabled applications
|
||||
libs.libbpf.url=https://github.com/libbpf/libbpf
|
||||
libs.libbpf.versions.100.version=1.0.0
|
||||
libs.libbpf.versions.100.path=/opt/compiler-explorer/libs/libbpf/v1.0.0/include
|
||||
libs.libbpf.versions.100.path=/opt/compiler-explorer/libs/libbpf/v1.0.0/include:/opt/compiler-explorer/libs/libbpf/v1.0.0/src
|
||||
libs.libbpf.versions.122.version=1.2.2
|
||||
libs.libbpf.versions.122.path=/opt/compiler-explorer/libs/libbpf/v1.2.2/include
|
||||
libs.libbpf.versions.122.path=/opt/compiler-explorer/libs/libbpf/v1.2.2/include:/opt/compiler-explorer/libs/libbpf/v1.2.2/src
|
||||
|
||||
libs.libguarded.name=CsLibGuarded
|
||||
libs.libguarded.versions=trunk:110
|
||||
@@ -3990,11 +3996,13 @@ libs.qt.url=https://www.qt.io
|
||||
libs.qt.packagedheaders=true
|
||||
libs.qt.liblink=Qt6Core
|
||||
libs.qt.options=-DQT_NO_VERSION_TAGGING
|
||||
libs.qt.versions=642:652
|
||||
libs.qt.versions=642:652:660
|
||||
libs.qt.versions.642.version=6.4.2
|
||||
libs.qt.versions.642.path=/app/qt/include/QtCore
|
||||
libs.qt.versions.652.version=6.5.2
|
||||
libs.qt.versions.652.path=/app/qt/include/QtCore
|
||||
libs.qt.versions.660.version=6.6.0
|
||||
libs.qt.versions.660.path=/app/qt/include/QtCore
|
||||
|
||||
libs.rangesv3.name=range-v3
|
||||
libs.rangesv3.versions=trunk:030:035:036:091:0100:0110:0120
|
||||
@@ -4049,10 +4057,14 @@ libs.scnlib.versions.04.path=/opt/compiler-explorer/libs/scnlib/refs/tags/v0.4/i
|
||||
|
||||
libs.seastar.name=Seastar
|
||||
libs.seastar.description=SeaStar is an event-driven framework allowing you to write non-blocking, asynchronous code in a relatively straightforward manner.
|
||||
libs.seastar.versions=180
|
||||
libs.seastar.versions=trunk:180:2211
|
||||
libs.seastar.url=http://seastar.io
|
||||
libs.seastar.versions.180.version=18.08.0
|
||||
libs.seastar.versions.180.path=/opt/compiler-explorer/libs/seastar/seastar-18.08.0
|
||||
libs.seastar.versions.2211.version=22.11.0
|
||||
libs.seastar.versions.2211.path=/opt/compiler-explorer/libs/seastar/seastar-22.11.0/include
|
||||
libs.seastar.versions.trunk.version=trunk
|
||||
libs.seastar.versions.trunk.path=/opt/compiler-explorer/libs/seastar/trunk/include
|
||||
|
||||
libs.seqan3.name=SeqAn3
|
||||
libs.seqan3.description=A modern C++ library for sequence analysis.
|
||||
@@ -4223,8 +4235,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
|
||||
libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
|
||||
|
||||
libs.trompeloeil.name=trompeloeil
|
||||
libs.trompeloeil.versions=45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.versions=46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
|
||||
libs.trompeloeil.versions.46.path=/opt/compiler-explorer/libs/trompeloeil/v46/include
|
||||
libs.trompeloeil.versions.46.version=v46
|
||||
libs.trompeloeil.versions.45.path=/opt/compiler-explorer/libs/trompeloeil/v45/include
|
||||
libs.trompeloeil.versions.45.version=v45
|
||||
libs.trompeloeil.versions.44.path=/opt/compiler-explorer/libs/trompeloeil/v44/include
|
||||
@@ -4520,7 +4534,7 @@ tools.llvm-mcatrunk.name=llvm-mca (trunk)
|
||||
tools.llvm-mcatrunk.exe=/opt/compiler-explorer/clang-trunk/bin/llvm-mca
|
||||
tools.llvm-mcatrunk.type=postcompilation
|
||||
tools.llvm-mcatrunk.class=llvm-mca-tool
|
||||
tools.llvm-mcatrunk.exclude=avr:rv32:arm:aarch:mips:msp:ppc:cl19:cl_new:djggp
|
||||
tools.llvm-mcatrunk.exclude=avr:rv32:arm:mips:msp:ppc:cl19:cl_new:djggp
|
||||
tools.llvm-mcatrunk.stdinHint=disabled
|
||||
|
||||
tools.osacatrunk.name=OSACA (0.5.2)
|
||||
|
||||
@@ -545,7 +545,7 @@ compiler.armv8-cclang-trunk.isNightly=true
|
||||
# Arm v8-a
|
||||
compiler.armv8-cclang-trunk.options=-target aarch64-linux-gnu --gcc-toolchain=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot
|
||||
|
||||
compiler.armv8-full-cclang-trunk.name=armv8-a clang (trunk, all architectural features)
|
||||
compiler.armv8-full-cclang-trunk.name=armv8-a clang (all architectural features, trunk)
|
||||
compiler.armv8-full-cclang-trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang
|
||||
compiler.armv8-full-cclang-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.armv8-full-cclang-trunk.objdumper=/opt/compiler-explorer/arm64/gcc-10.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/bin/objdump
|
||||
@@ -2736,9 +2736,9 @@ libs.libbpf.liblink=bpf:dl:m
|
||||
libs.libbpf.description=Libbpf supports building BPF CO-RE-enabled applications
|
||||
libs.libbpf.url=https://github.com/libbpf/libbpf
|
||||
libs.libbpf.versions.100.version=1.0.0
|
||||
libs.libbpf.versions.100.path=/opt/compiler-explorer/libs/libbpf/v1.0.0/include
|
||||
libs.libbpf.versions.100.path=/opt/compiler-explorer/libs/libbpf/v1.0.0/include:/opt/compiler-explorer/libs/libbpf/v1.0.0/src
|
||||
libs.libbpf.versions.122.version=1.2.2
|
||||
libs.libbpf.versions.122.path=/opt/compiler-explorer/libs/libbpf/v1.2.2/include
|
||||
libs.libbpf.versions.122.path=/opt/compiler-explorer/libs/libbpf/v1.2.2/include:/opt/compiler-explorer/libs/libbpf/v1.2.2/src
|
||||
|
||||
libs.lua.name=Lua
|
||||
libs.lua.versions=535:540
|
||||
|
||||
@@ -1003,8 +1003,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
|
||||
libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
|
||||
|
||||
libs.trompeloeil.name=trompeloeil
|
||||
libs.trompeloeil.versions=45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.versions=46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
|
||||
libs.trompeloeil.versions.46.path=/opt/compiler-explorer/libs/trompeloeil/v46/include
|
||||
libs.trompeloeil.versions.46.version=v46
|
||||
libs.trompeloeil.versions.45.path=/opt/compiler-explorer/libs/trompeloeil/v45/include
|
||||
libs.trompeloeil.versions.45.version=v45
|
||||
libs.trompeloeil.versions.44.path=/opt/compiler-explorer/libs/trompeloeil/v44/include
|
||||
|
||||
@@ -40,6 +40,8 @@ cmake=/opt/compiler-explorer/cmake/bin/cmake
|
||||
useninja=false
|
||||
ld=/usr/bin/ld
|
||||
readelf=/usr/bin/readelf
|
||||
mkfifo=/usr/bin/mkfifo
|
||||
heaptrackPath=/opt/compiler-explorer/heaptrack-v1.3.0
|
||||
|
||||
formatters=clangformat:rustfmt:gofmt:dartformat:vfmt
|
||||
formatter.clangformat.name=clang-format
|
||||
|
||||
@@ -50,6 +50,8 @@ cmake=cmake
|
||||
useninja=false
|
||||
ld=ld
|
||||
readelf=readelf
|
||||
mkfifo=/usr/bin/mkfifo
|
||||
heaptrackPath=
|
||||
|
||||
# set this true to keep temporary folders for a while for debugging purposes
|
||||
delayCleanupTemp=false
|
||||
|
||||
@@ -171,7 +171,7 @@ compiler.armv8-cpp4oclclang-trunk-assertions.isNightly=true
|
||||
# Arm v8-a
|
||||
compiler.armv8-cpp4oclclang-trunk-assertions.options=-target aarch64-linux-gnu --gcc-toolchain=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot
|
||||
|
||||
compiler.armv8-full-cpp4oclclang-trunk.name=armv8-a clang (trunk, all architectural features)
|
||||
compiler.armv8-full-cpp4oclclang-trunk.name=armv8-a clang (all architectural features, trunk)
|
||||
compiler.armv8-full-cpp4oclclang-trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang
|
||||
compiler.armv8-full-cpp4oclclang-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.armv8-full-cpp4oclclang-trunk.objdumper=/opt/compiler-explorer/gcc-snapshot/bin/objdump
|
||||
|
||||
@@ -3,6 +3,7 @@ compilers=&dxc:&rga:&clang
|
||||
defaultCompiler=dxc_default
|
||||
supportsBinary=false
|
||||
compilerType=hlsl
|
||||
instructionSet=llvm
|
||||
|
||||
group.dxc.compilers=dxc_default
|
||||
compiler.dxc_default.exe=/usr/dxc-artifacts/bin/dxc
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
compilers=&kotlin
|
||||
compilerType=kotlin
|
||||
versionFlag=-version
|
||||
objdumper=/opt/compiler-explorer/jdk-19.0.2/bin/javap
|
||||
objdumper=/opt/compiler-explorer/jdk-21.0.0/bin/javap
|
||||
instructionSet=java
|
||||
defaultCompiler=kotlinc1900
|
||||
defaultCompiler=kotlinc1920
|
||||
demangler=
|
||||
postProcess=
|
||||
options=
|
||||
@@ -12,7 +12,7 @@ needsMulti=false
|
||||
supportsExecute=true
|
||||
interpreted=true
|
||||
|
||||
group.kotlin.compilers=kotlinc1400:kotlinc1410:kotlinc1420:kotlinc1421:kotlinc1430:kotlinc1431:kotlinc1432:kotlinc1500:kotlinc1510:kotlinc1520:kotlinc1521:kotlinc1530:kotlinc1531:kotlinc1600:kotlinc1610:kotlinc1620:kotlinc1700:kotlinc1800:kotlinc1810:kotlinc1820:kotlinc1900
|
||||
group.kotlin.compilers=kotlinc1400:kotlinc1410:kotlinc1420:kotlinc1421:kotlinc1430:kotlinc1431:kotlinc1432:kotlinc1500:kotlinc1510:kotlinc1520:kotlinc1521:kotlinc1530:kotlinc1531:kotlinc1600:kotlinc1610:kotlinc1620:kotlinc1700:kotlinc1800:kotlinc1810:kotlinc1820:kotlinc1900:kotlinc1910:kotlinc1920
|
||||
group.kotlin.groupName=Kotlin
|
||||
group.kotlin.baseName=kotlinc
|
||||
group.kotlin.isSemVer=true
|
||||
@@ -103,3 +103,11 @@ compiler.kotlinc1900.exe=/opt/compiler-explorer/kotlin-jvm-1.9.0/bin/kotlinc-jvm
|
||||
compiler.kotlinc1900.semver=1.9.0
|
||||
compiler.kotlinc1900.java_home=/opt/compiler-explorer/jdk-20.0.0
|
||||
compiler.kotlinc1900.runtime=/opt/compiler-explorer/jdk-20.0.0/bin/java
|
||||
compiler.kotlinc1910.exe=/opt/compiler-explorer/kotlin-jvm-1.9.10/bin/kotlinc-jvm
|
||||
compiler.kotlinc1910.semver=1.9.10
|
||||
compiler.kotlinc1910.java_home=/opt/compiler-explorer/jdk-20.0.0
|
||||
compiler.kotlinc1910.runtime=/opt/compiler-explorer/jdk-20.0.0/bin/java
|
||||
compiler.kotlinc1920.exe=/opt/compiler-explorer/kotlin-jvm-1.9.20/bin/kotlinc-jvm
|
||||
compiler.kotlinc1920.semver=1.9.20
|
||||
compiler.kotlinc1920.java_home=/opt/compiler-explorer/jdk-21.0.0
|
||||
compiler.kotlinc1920.runtime=/opt/compiler-explorer/jdk-21.0.0/bin/java
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
compilers=&nim
|
||||
defaultCompiler=nim160
|
||||
demangler=/opt/compiler-explorer/gcc-9.2.0/bin/c++filt
|
||||
objdumper=/opt/compiler-explorer/gcc-9.2.0/bin/objdump
|
||||
defaultCompiler=nim200
|
||||
demangler=/opt/compiler-explorer/gcc-13.1.0/bin/c++filt
|
||||
objdumper=/opt/compiler-explorer/gcc-13.1.0/bin/objdump
|
||||
|
||||
supportsBinary=true
|
||||
supportsExecute=false
|
||||
compilerType=nim
|
||||
binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|.plt.*|.*@plt|_dl_relocate_static_pie)$
|
||||
|
||||
group.nim.compilers=nim160:nim148:nim146:nim144:nim142:nim120:nim106:nim104:nimtrunk
|
||||
group.nim.compilers=nim200:nim1616:nim160:nim148:nim146:nim144:nim142:nim120:nim106:nim104:nimtrunk
|
||||
group.nim.isSemVer=true
|
||||
group.nim.baseName=nim
|
||||
group.nim.licenseLink=https://github.com/nim-lang/Nim/blob/devel/copying.txt
|
||||
group.nim.licenseName=MIT License
|
||||
group.nim.licensePreamble=Copyright (C) 2006-2022 Andreas Rumpf. All rights reserved.
|
||||
group.nim.licensePreamble=Copyright (C) 2006-2023 Andreas Rumpf. All rights reserved.
|
||||
|
||||
compiler.nim200.semver=2.0.0
|
||||
compiler.nim200.exe=/opt/compiler-explorer/nim-2.0.0/bin/nim
|
||||
compiler.nim1616.semver=1.6.16
|
||||
compiler.nim1616.exe=/opt/compiler-explorer/nim-1.6.16/bin/nim
|
||||
compiler.nim160.semver=1.6.0
|
||||
compiler.nim160.exe=/opt/compiler-explorer/nim-1.6.0/bin/nim
|
||||
compiler.nim148.semver=1.4.8
|
||||
|
||||
@@ -1587,8 +1587,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
|
||||
libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
|
||||
|
||||
libs.trompeloeil.name=trompeloeil
|
||||
libs.trompeloeil.versions=45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.versions=46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
|
||||
libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
|
||||
libs.trompeloeil.versions.46.path=/opt/compiler-explorer/libs/trompeloeil/v46/include
|
||||
libs.trompeloeil.versions.46.version=v46
|
||||
libs.trompeloeil.versions.45.path=/opt/compiler-explorer/libs/trompeloeil/v45/include
|
||||
libs.trompeloeil.versions.45.version=v45
|
||||
libs.trompeloeil.versions.44.path=/opt/compiler-explorer/libs/trompeloeil/v44/include
|
||||
|
||||
@@ -192,7 +192,7 @@ compiler.armv8-oclcclang-trunk-assertions.semver=(assertions trunk)
|
||||
# Arm v8-a
|
||||
compiler.armv8-oclcclang-trunk-assertions.options=-target aarch64-linux-gnu --gcc-toolchain=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/arm64/gcc-12.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot
|
||||
|
||||
compiler.armv8-full-oclcclang-trunk.name=armv8-a clang (trunk, all architectural features)
|
||||
compiler.armv8-full-oclcclang-trunk.name=armv8-a clang (all architectural features, trunk)
|
||||
compiler.armv8-full-oclcclang-trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang
|
||||
compiler.armv8-full-oclcclang-trunk.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
compiler.armv8-full-oclcclang-trunk.objdumper=/opt/compiler-explorer/gcc-snapshot/bin/objdump
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
compilers=&solc
|
||||
defaultCompiler=solc0813
|
||||
defaultCompiler=solc0821
|
||||
|
||||
group.solc.compilers=solc036:solc0426:solc0517:solc0612:solc076:solc0813
|
||||
group.solc.compilers=solc036:solc0426:solc0517:solc0612:solc076:solc0821
|
||||
group.solc.compilerType=solidity
|
||||
group.solc.supportsBinary=false
|
||||
group.solc.instructionSet=evm
|
||||
@@ -20,9 +20,9 @@ compiler.solc0612.name=solc 0.6.12
|
||||
compiler.solc076.exe=/opt/compiler-explorer/solc-0.7.6/solc
|
||||
compiler.solc076.semver=0.7.6
|
||||
compiler.solc076.name=solc 0.7.6
|
||||
compiler.solc0813.exe=/opt/compiler-explorer/solc-0.8.13/solc
|
||||
compiler.solc0813.semver=0.8.13
|
||||
compiler.solc0813.name=solc 0.8.13
|
||||
compiler.solc0821.exe=/opt/compiler-explorer/solc-0.8.21/solc
|
||||
compiler.solc0821.semver=0.8.21
|
||||
compiler.solc0821.name=solc 0.8.21
|
||||
|
||||
#################################
|
||||
#################################
|
||||
|
||||
@@ -12,15 +12,6 @@ levels:
|
||||
priority: 100
|
||||
topIconShowEvery: 3
|
||||
statsId: solid_sands
|
||||
- name: Intel
|
||||
description: We engineer solutions for our customers’ greatest challenges with reliable, cloud to edge computing, inspired by Moore’s Law.
|
||||
icon: https://static.ce-cdn.net/intel/logo-classicblue-3000px-single-colour.png
|
||||
img: https://static.ce-cdn.net/intel/logo-classicblue-3000px.png
|
||||
url: https://intel.com/
|
||||
priority: 400
|
||||
topIconShowEvery: 1
|
||||
sideBySide: true
|
||||
statsId: intel
|
||||
- name: Sonar
|
||||
description: Analyze your C and C++ projects with just one click. Free for open-source projects
|
||||
img: https://static.ce-cdn.net/sonar/sonarcloud-2.png
|
||||
@@ -445,3 +436,10 @@ levels:
|
||||
- dvirtz
|
||||
- ezki
|
||||
- Patrick Eads
|
||||
- Ivan Pribec
|
||||
- Ben Sunshine-Hill
|
||||
- Sam Mish
|
||||
- Aleš Křivák
|
||||
- Elias Nodland
|
||||
- Andy Bell
|
||||
- lv426
|
||||
|
||||
26
etc/config/tablegen.amazon.properties
Normal file
26
etc/config/tablegen.amazon.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
compilers=&llvmtblgen
|
||||
defaultCompiler=llvmtblgen1701
|
||||
compilerType=tablegen
|
||||
supportsBinary=false
|
||||
supportsExecute=false
|
||||
|
||||
group.llvmtblgen.compilers=llvmtblgen_trunk:llvmtblgen1701
|
||||
group.llvmtblgen.groupName=LLVM TableGen
|
||||
group.llvmtblgen.baseName=LLVM TableGen
|
||||
group.llvmtblgen.isSemVer=true
|
||||
group.llvmtblgen.compilerType=tablegen
|
||||
group.llvmtblgen.licenseName=LLVM Apache 2
|
||||
group.llvmtblgen.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.llvmtblgen.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.llvmtblgen.supportsBinaryObject=false
|
||||
group.llvmtblgen.supportsBinary=false
|
||||
group.llvmtblgen.compilerCategories=tablegen
|
||||
|
||||
compiler.llvmtblgen_trunk.exe=/opt/compiler-explorer/clang-trunk/bin/llvm-tblgen
|
||||
compiler.llvmtblgen_trunk.semver=(trunk)
|
||||
compiler.llvmtblgen_trunk.isNightly=true
|
||||
compiler.llvmtblgen_trunk.includePath=/opt/compiler-explorer/clang-trunk/include/
|
||||
|
||||
compiler.llvmtblgen1701.exe=/opt/compiler-explorer/clang-17.0.1/bin/llvm-tblgen
|
||||
compiler.llvmtblgen1701.semver=17.0.1
|
||||
compiler.llvmtblgen1701.includePath=/opt/compiler-explorer/clang-17.0.1/include/
|
||||
8
etc/config/tablegen.defaults.properties
Normal file
8
etc/config/tablegen.defaults.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
compilerType=tablegen
|
||||
compilers=llvmtblgen
|
||||
defaultCompiler=llvmtblgen
|
||||
supportsBinary=false
|
||||
supportsExecute=false
|
||||
|
||||
compiler.llvmtblgen.exe=/usr/bin/llvm-tblgen
|
||||
compiler.llvmtblgen.name=llvm-tblgen
|
||||
@@ -8,6 +8,7 @@ all: \
|
||||
$(GEN_DIR)/asm-docs-evm.ts \
|
||||
$(GEN_DIR)/asm-docs-java.ts \
|
||||
$(GEN_DIR)/asm-docs-llvm.ts \
|
||||
$(GEN_DIR)/asm-docs-riscv64.ts
|
||||
$(GEN_DIR)/asm-docs-ptx.ts \
|
||||
$(GEN_DIR)/asm-docs-sass.ts \
|
||||
$(GEN_DIR)/asm-docs-python.ts
|
||||
@@ -34,3 +35,5 @@ $(GEN_DIR)/asm-docs-sass.ts: docenizer-ptx-sass.py
|
||||
python3 $< -o $@
|
||||
$(GEN_DIR)/asm-docs-python.ts: docenizer-python.py
|
||||
python3 $< -o $@
|
||||
$(GEN_DIR)/asm-docs-riscv64.ts: docenizer-riscv64.py
|
||||
python3 $< -o $@
|
||||
138
etc/scripts/docenizers/docenizer-riscv64.py
Executable file
138
etc/scripts/docenizers/docenizer-riscv64.py
Executable file
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from urllib import request
|
||||
from urllib import parse
|
||||
|
||||
import requests
|
||||
import yaml
|
||||
import sys
|
||||
import re
|
||||
|
||||
#opcodes_yaml = "https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml"
|
||||
opcodes_yaml = "https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml"
|
||||
htmlhost = "https://five-embeddev.github.io/riscv-docs-html/"
|
||||
|
||||
parser = argparse.ArgumentParser(description='Scrape the five-embeddev quick reference page and generate the riscv documentation')
|
||||
parser.add_argument('-i', '--opcode-data', type=str, help='Input opcode data in YAML format.',
|
||||
default=opcodes_yaml)
|
||||
parser.add_argument('-o', '--outputpath', type=str, help='Final path of the .ts file. Default is ./asm-docs-riscv64.ts',
|
||||
default='./asm-docs-riscv64.ts')
|
||||
|
||||
def bold_keyword(text, keyword):
|
||||
for keywordr in (keyword.upper(), keyword.lower()):
|
||||
rer = re.compile(f"\\b{keywordr}\\b")
|
||||
text,_ = re.subn(rer,f"<b>{keywordr}</b>",text)
|
||||
return text
|
||||
|
||||
class operation:
|
||||
def __init__(self, yaml_record, yaml_data):
|
||||
opcode = yaml_record['opcode'][0].upper()
|
||||
# Remove "@" and "c." from opcode
|
||||
# These are
|
||||
|
||||
self.opcode = opcode
|
||||
self.opcode_alias = None
|
||||
if 'opcode_alias' in yaml_record:
|
||||
self.opcode_alias = yaml_record['opcode_alias'].upper()
|
||||
|
||||
tool_opcode_args = opcode + " " + ', '.join(yaml_record['opcode_args']) + "\n"
|
||||
html_opcode_args = f"<span class=\"opcode\"><b>{opcode}</b> {', '.join(yaml_record['opcode_args'])}</span>"
|
||||
|
||||
# What ISA does this opcode belong to?
|
||||
# Is is a psuedo opcode?
|
||||
group=""
|
||||
|
||||
if 'main_desc' in yaml_record:
|
||||
group += yaml_record['main_desc']
|
||||
if 'psuedo' == yaml_record['opcode_group']:
|
||||
group += "(pseudo)"
|
||||
|
||||
html_code = ""
|
||||
text_code = ""
|
||||
html_group = f"<br><div><b>ISA</b>: {group}</div>"
|
||||
|
||||
if 'psuedo_to_base' in yaml_record:
|
||||
html_code += "<br><div><b>Equivalent ASM:</b><pre>"
|
||||
html_code += "\n".join(yaml_record['psuedo_to_base'])
|
||||
html_code += "</pre></div>"
|
||||
text_code += "Equivalent ASM:\n\n" + "\n".join(yaml_record['psuedo_to_base'])
|
||||
|
||||
if 'main_url_base' in yaml_record:
|
||||
main_url_base = yaml_record['main_url_base']
|
||||
main_desc = yaml_record['main_desc']
|
||||
main_id = yaml_record['main_id']
|
||||
|
||||
opcode_descs = yaml_record['desc'][main_desc][main_id]['text']
|
||||
tool_desc = "\n".join(opcode_descs) + "\n\n" + text_code + "\n\n(ISA: " + group + ")"
|
||||
html_desc = "<br><div>" + "<br>".join([bold_keyword(x,opcode) for x in opcode_descs]) + "</div>"
|
||||
|
||||
|
||||
self.url = htmlhost + main_url_base + main_id
|
||||
self.tooltip = tool_desc
|
||||
# extract all elements under the second column and the third column which are td
|
||||
# and put them into a new div tag
|
||||
self.html = "<div>" + html_opcode_args + html_desc + html_code + html_group + "</div>"
|
||||
elif 'psuedo_to_base' in yaml_record:
|
||||
self.url = htmlhost
|
||||
self.tooltip = "Psuedo Instruction.\n\n" + text_code + "\n\n"
|
||||
self.html = "<div>" + html_opcode_args + html_code + html_group + "</div>"
|
||||
else:
|
||||
self.url = htmlhost
|
||||
self.tooltip = "\n\n(ISA: " + group + ")"
|
||||
self.html = "<div>" + html_opcode_args + html_group + "</div>"
|
||||
|
||||
def __str__(self):
|
||||
dic = {
|
||||
# no opcode here
|
||||
"tooltip": self.tooltip,
|
||||
"url": self.url,
|
||||
"html": self.html
|
||||
}
|
||||
return json.dumps(dic, indent=16, separators=(',', ': '), sort_keys=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
yaml_text=None
|
||||
try:
|
||||
if args.opcode_data[:4] == "http":
|
||||
r = requests.get(args.opcode_data)
|
||||
r.encoding = 'utf-8'
|
||||
yaml_text = r.text
|
||||
else:
|
||||
with open(args.opcode_data, 'r') as fin :
|
||||
yaml_text=fin.read()
|
||||
except:
|
||||
print("ERROR: Loading YAML file or URL: " + args.opcode_data + ":")
|
||||
print(exc)
|
||||
sys.exit(-1)
|
||||
yaml_data=None
|
||||
try:
|
||||
yaml_data = yaml.safe_load(yaml_text)
|
||||
except yaml.YAMLError as exc:
|
||||
print("ERROR: Parsing YAML file: " + args.opcode_data + ":")
|
||||
print(exc)
|
||||
sys.exit(-1)
|
||||
|
||||
with open(args.outputpath, "w") as output:
|
||||
|
||||
output.write("""
|
||||
import {AssemblyInstructionInfo} from '../base.js';
|
||||
|
||||
export function getAsmOpcode(opcode: string | undefined): AssemblyInstructionInfo | undefined {
|
||||
if (!opcode) return;
|
||||
switch (opcode.toUpperCase()) {
|
||||
""".lstrip())
|
||||
|
||||
for record in [operation(o, yaml_data) for o in yaml_data['opcodes'].values()]:
|
||||
# for each opcode
|
||||
output.write(f' case "{record.opcode}":\n')
|
||||
if record.opcode_alias:
|
||||
output.write(f' case "{record.opcode_alias}":\n')
|
||||
output.write(f' return {str(record)[:-1]} }};\n\n')
|
||||
|
||||
output.write("""
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
8
examples/tablegen/default.td
Normal file
8
examples/tablegen/default.td
Normal file
@@ -0,0 +1,8 @@
|
||||
class Register<int _size, string _alias=""> {
|
||||
int size = _size;
|
||||
string alias = _alias;
|
||||
}
|
||||
|
||||
def X0: Register<8> {}
|
||||
|
||||
def X29: Register<8, "frame pointer"> {}
|
||||
20
examples/tablegen/searchable_tables.td
Normal file
20
examples/tablegen/searchable_tables.td
Normal file
@@ -0,0 +1,20 @@
|
||||
// This example uses the Searchable Tables backend, aka --gen-searchable-tables.
|
||||
// To choose the backend, select it as the "Action" in the "Overrides" menu,
|
||||
// or add "--gen-searchable-tables" to the compiler options.
|
||||
// For more details:
|
||||
// https://llvm.org/docs/TableGen/BackEnds.html#searchabletables-reference
|
||||
|
||||
include "llvm/TableGen/SearchableTable.td"
|
||||
|
||||
class Pair<string name, int value> : SearchableTable {
|
||||
let SearchableFields = ["Name", "Value"];
|
||||
let EnumValueField = "Value";
|
||||
|
||||
string Name = name;
|
||||
bits<2> Value = value;
|
||||
}
|
||||
|
||||
def : Pair<"Example 0", 0b00>;
|
||||
def : Pair<"Example 1", 0b01>;
|
||||
def : Pair<"Example 2", 0b10>;
|
||||
def : Pair<"Example 3", 0b11>;
|
||||
@@ -31,4 +31,5 @@ export {LLVMDocumentationProvider} from './llvm.js';
|
||||
export {Mos6502DocumentationProvider} from './mos6502.js';
|
||||
export {PTXDocumentationProvider} from './ptx.js';
|
||||
export {PythonDocumentationProvider} from './python.js';
|
||||
export {Riscv64DocumentationProvider} from './riscv64.js';
|
||||
export {SASSDocumentationProvider} from './sass.js';
|
||||
|
||||
6472
lib/asm-docs/generated/asm-docs-riscv64.ts
generated
Normal file
6472
lib/asm-docs/generated/asm-docs-riscv64.ts
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
lib/asm-docs/riscv64.ts
Normal file
35
lib/asm-docs/riscv64.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2022, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
import {AssemblyInstructionInfo, BaseAssemblyDocumentationProvider} from './base.js';
|
||||
import {getAsmOpcode} from './generated/asm-docs-riscv64.js';
|
||||
|
||||
export class Riscv64DocumentationProvider extends BaseAssemblyDocumentationProvider {
|
||||
public static get key() {
|
||||
return 'riscv64';
|
||||
}
|
||||
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
|
||||
return getAsmOpcode(instruction) || null;
|
||||
}
|
||||
}
|
||||
@@ -48,16 +48,19 @@ import type {
|
||||
LLVMOptPipelineOutput,
|
||||
} from '../types/compilation/llvm-opt-pipeline-output.interfaces.js';
|
||||
import type {CompilerInfo, ICompiler, PreliminaryCompilerInfo} from '../types/compiler.interfaces.js';
|
||||
import type {
|
||||
import {
|
||||
BasicExecutionResult,
|
||||
ConfiguredRuntimeTool,
|
||||
ConfiguredRuntimeTools,
|
||||
ExecutableExecutionOptions,
|
||||
RuntimeToolType,
|
||||
UnprocessedExecResult,
|
||||
} from '../types/execution/execution.interfaces.js';
|
||||
import type {CompilerOutputOptions, ParseFiltersAndOutputOptions} from '../types/features/filters.interfaces.js';
|
||||
import type {Language} from '../types/languages.interfaces.js';
|
||||
import type {Library, LibraryVersion, SelectedLibraryVersion} from '../types/libraries/libraries.interfaces.js';
|
||||
import type {ResultLine} from '../types/resultline/resultline.interfaces.js';
|
||||
import type {Artifact, ToolResult, ToolTypeKey} from '../types/tool.interfaces.js';
|
||||
import {ArtifactType, type Artifact, type ToolResult, type ToolTypeKey} from '../types/tool.interfaces.js';
|
||||
|
||||
import {BuildEnvSetupBase, getBuildEnvTypeByKey} from './buildenvsetup/index.js';
|
||||
import type {BuildEnvDownloadInfo} from './buildenvsetup/buildenv.interfaces.js';
|
||||
@@ -108,6 +111,10 @@ import {LLVMIrBackendOptions} from '../types/compilation/ir.interfaces.js';
|
||||
import {ParsedAsmResultLine} from '../types/asmresult/asmresult.interfaces.js';
|
||||
import {unique} from '../shared/common-utils.js';
|
||||
import {ClientOptionsType, OptionsHandlerLibrary, VersionInfo} from './options-handler.js';
|
||||
import {HeaptrackWrapper} from './runtime-tools/heaptrack-wrapper.js';
|
||||
import {propsFor} from './properties.js';
|
||||
import stream from 'node:stream';
|
||||
import {SentryCapture} from './sentry.js';
|
||||
|
||||
const compilationTimeHistogram = new PromClient.Histogram({
|
||||
name: 'ce_base_compiler_compilation_duration_seconds',
|
||||
@@ -172,6 +179,8 @@ export class BaseCompiler implements ICompiler {
|
||||
protected externalparser: null | ExternalParserBase;
|
||||
protected supportedLibraries?: Record<string, Library>;
|
||||
protected packager: Packager;
|
||||
protected executionType: string;
|
||||
protected sandboxType: string;
|
||||
protected defaultRpathFlag: string = '-Wl,-rpath,';
|
||||
private static objdumpAndParseCounter = new PromClient.Counter({
|
||||
name: 'ce_objdumpandparsetime_total',
|
||||
@@ -211,6 +220,10 @@ export class BaseCompiler implements ICompiler {
|
||||
this.compiler.disabledFilters = (this.compiler.disabledFilters as any).split(',');
|
||||
}
|
||||
|
||||
const execProps = propsFor('execution');
|
||||
this.executionType = execProps('executionType', 'none');
|
||||
this.sandboxType = execProps('sandboxType', 'none');
|
||||
|
||||
this.asm = new AsmParser(this.compilerProps);
|
||||
const irDemangler = new LLVMIRDemangler(this.compiler.demangler, this);
|
||||
this.llvmIr = new LlvmIrParser(this.compilerProps, irDemangler);
|
||||
@@ -563,6 +576,22 @@ export class BaseCompiler implements ICompiler {
|
||||
};
|
||||
}
|
||||
|
||||
processUserExecutableExecutionResult(
|
||||
input: UnprocessedExecResult,
|
||||
stdErrlineParseOptions: utils.LineParseOptions,
|
||||
): BasicExecutionResult {
|
||||
const start = performance.now();
|
||||
const stdout = utils.parseOutput(input.stdout, undefined, undefined, []);
|
||||
const stderr = utils.parseOutput(input.stderr, undefined, undefined, stdErrlineParseOptions);
|
||||
const end = performance.now();
|
||||
return {
|
||||
...input,
|
||||
stdout,
|
||||
stderr,
|
||||
processExecutionResultTime: end - start,
|
||||
};
|
||||
}
|
||||
|
||||
getEmptyExecutionResult(): BasicExecutionResult {
|
||||
return {
|
||||
code: -1,
|
||||
@@ -585,16 +614,69 @@ export class BaseCompiler implements ICompiler {
|
||||
};
|
||||
}
|
||||
|
||||
async execBinary(
|
||||
executable,
|
||||
maxSize,
|
||||
protected setEnvironmentVariablesFromRuntime(
|
||||
configuredTools: ConfiguredRuntimeTools,
|
||||
execOptions: ExecutionOptions,
|
||||
) {
|
||||
for (const runtime of configuredTools) {
|
||||
if (runtime.name === RuntimeToolType.env) {
|
||||
for (const env of runtime.options) {
|
||||
if (!execOptions.env) execOptions.env = {};
|
||||
|
||||
execOptions.env[env.name] = env.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async execBinaryMaybeWrapped(
|
||||
executable: string,
|
||||
args: string[],
|
||||
execOptions: ExecutionOptions,
|
||||
executeParameters: ExecutableExecutionOptions,
|
||||
homeDir,
|
||||
homeDir: string,
|
||||
): Promise<BasicExecutionResult> {
|
||||
let runWithHeaptrack: ConfiguredRuntimeTool | undefined = undefined;
|
||||
|
||||
if (!execOptions.env) execOptions.env = {};
|
||||
|
||||
if (executeParameters.runtimeTools) {
|
||||
this.setEnvironmentVariablesFromRuntime(executeParameters.runtimeTools, execOptions);
|
||||
|
||||
for (const runtime of executeParameters.runtimeTools) {
|
||||
if (runtime.name === RuntimeToolType.heaptrack) {
|
||||
runWithHeaptrack = runtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (runWithHeaptrack && HeaptrackWrapper.isSupported(this.env)) {
|
||||
const wrapper = new HeaptrackWrapper(
|
||||
homeDir,
|
||||
exec.sandbox,
|
||||
this.exec,
|
||||
runWithHeaptrack.options,
|
||||
this.env.ceProps,
|
||||
this.sandboxType,
|
||||
);
|
||||
const execResult: UnprocessedExecResult = await wrapper.exec(executable, args, execOptions);
|
||||
return this.processUserExecutableExecutionResult(execResult, [utils.LineParseOption.AtFileLine]);
|
||||
} else {
|
||||
const execResult: UnprocessedExecResult = await exec.sandbox(executable, args, execOptions);
|
||||
return this.processUserExecutableExecutionResult(execResult, []);
|
||||
}
|
||||
}
|
||||
|
||||
async execBinary(
|
||||
executable: string,
|
||||
maxSize: number,
|
||||
executeParameters: ExecutableExecutionOptions,
|
||||
homeDir: string,
|
||||
): Promise<BasicExecutionResult> {
|
||||
// We might want to save this in the compilation environment once execution is made available
|
||||
const timeoutMs = this.env.ceProps('binaryExecTimeoutMs', 2000);
|
||||
try {
|
||||
const execResult: UnprocessedExecResult = await exec.sandbox(executable, executeParameters.args, {
|
||||
const execOptions: ExecutionOptions = {
|
||||
maxOutput: maxSize,
|
||||
timeoutMs: timeoutMs,
|
||||
ldPath: _.union(this.compiler.ldPath, executeParameters.ldPath),
|
||||
@@ -602,9 +684,15 @@ export class BaseCompiler implements ICompiler {
|
||||
env: executeParameters.env,
|
||||
customCwd: homeDir,
|
||||
appHome: homeDir,
|
||||
});
|
||||
};
|
||||
|
||||
return this.processExecutionResult(execResult);
|
||||
return this.execBinaryMaybeWrapped(
|
||||
executable,
|
||||
executeParameters.args,
|
||||
execOptions,
|
||||
executeParameters,
|
||||
homeDir,
|
||||
);
|
||||
} catch (err: UnprocessedExecResult | any) {
|
||||
if (err.code && err.stderr) {
|
||||
return this.processExecutionResult(err);
|
||||
@@ -624,7 +712,7 @@ export class BaseCompiler implements ICompiler {
|
||||
}
|
||||
|
||||
getGccDumpFileName(outputFilename: string) {
|
||||
return outputFilename.replace(path.extname(outputFilename), '.dump');
|
||||
return utils.changeExtension(outputFilename, '.dump');
|
||||
}
|
||||
|
||||
getGccDumpOptions(gccDumpOptions, outputFilename: string) {
|
||||
@@ -840,7 +928,7 @@ export class BaseCompiler implements ICompiler {
|
||||
return sortedlinks;
|
||||
}
|
||||
|
||||
getStaticLibraryLinks(libraries: CompileChildLibraries[]) {
|
||||
getStaticLibraryLinks(libraries: CompileChildLibraries[]): string[] {
|
||||
const linkFlag = this.compiler.linkFlag || '-l';
|
||||
|
||||
return this.getSortedStaticLibraries(libraries)
|
||||
@@ -868,11 +956,11 @@ export class BaseCompiler implements ICompiler {
|
||||
.filter(link => link) as string[];
|
||||
}
|
||||
|
||||
getSharedLibraryPaths(libraries: CompileChildLibraries[]) {
|
||||
getSharedLibraryPaths(libraries: CompileChildLibraries[]): string[] {
|
||||
return libraries
|
||||
.map(selectedLib => {
|
||||
const foundVersion = this.findLibVersion(selectedLib);
|
||||
if (!foundVersion) return false;
|
||||
if (!foundVersion) return [];
|
||||
|
||||
const paths = [...foundVersion.libpath];
|
||||
if (this.buildenvsetup && !this.buildenvsetup.extractAllToRoot) {
|
||||
@@ -887,7 +975,7 @@ export class BaseCompiler implements ICompiler {
|
||||
libraries: CompileChildLibraries[],
|
||||
libDownloadPath?: string,
|
||||
toolchainPath?: string,
|
||||
) {
|
||||
): string[] {
|
||||
const pathFlag = this.compiler.rpathFlag || this.defaultRpathFlag;
|
||||
const libPathFlag = this.compiler.libpathFlag || '-L';
|
||||
|
||||
@@ -907,10 +995,10 @@ export class BaseCompiler implements ICompiler {
|
||||
toolchainLibraryPaths.map(path => pathFlag + path),
|
||||
this.getSharedLibraryPaths(libraries).map(path => pathFlag + path),
|
||||
this.getSharedLibraryPaths(libraries).map(path => libPathFlag + path),
|
||||
) as string[];
|
||||
);
|
||||
}
|
||||
|
||||
protected getSharedLibraryPathsAsLdLibraryPaths(libraries) {
|
||||
protected getSharedLibraryPathsAsLdLibraryPaths(libraries): string[] {
|
||||
let paths = '';
|
||||
if (!this.alwaysResetLdPath) {
|
||||
paths = process.env.LD_LIBRARY_PATH || '';
|
||||
@@ -919,10 +1007,10 @@ export class BaseCompiler implements ICompiler {
|
||||
paths.split(path.delimiter).filter(p => !!p),
|
||||
this.compiler.ldPath,
|
||||
this.getSharedLibraryPaths(libraries),
|
||||
) as string[];
|
||||
);
|
||||
}
|
||||
|
||||
getSharedLibraryPathsAsLdLibraryPathsForExecution(libraries) {
|
||||
getSharedLibraryPathsAsLdLibraryPathsForExecution(libraries): string[] {
|
||||
let paths = '';
|
||||
if (!this.alwaysResetLdPath) {
|
||||
paths = process.env.LD_LIBRARY_PATH || '';
|
||||
@@ -1393,27 +1481,27 @@ export class BaseCompiler implements ICompiler {
|
||||
}
|
||||
|
||||
getRustMacroExpansionOutputFilename(inputFilename) {
|
||||
return inputFilename.replace(path.extname(inputFilename), '.expanded.rs');
|
||||
return utils.changeExtension(inputFilename, '.expanded.rs');
|
||||
}
|
||||
|
||||
getRustHirOutputFilename(inputFilename) {
|
||||
return inputFilename.replace(path.extname(inputFilename), '.hir');
|
||||
return utils.changeExtension(inputFilename, '.hir');
|
||||
}
|
||||
|
||||
getRustMirOutputFilename(outputFilename) {
|
||||
return outputFilename.replace(path.extname(outputFilename), '.mir');
|
||||
return utils.changeExtension(outputFilename, '.mir');
|
||||
}
|
||||
|
||||
getHaskellCoreOutputFilename(inputFilename) {
|
||||
return inputFilename.replace(path.extname(inputFilename), '.dump-simpl');
|
||||
return utils.changeExtension(inputFilename, '.dump-simpl');
|
||||
}
|
||||
|
||||
getHaskellStgOutputFilename(inputFilename) {
|
||||
return inputFilename.replace(path.extname(inputFilename), '.dump-stg-final');
|
||||
return utils.changeExtension(inputFilename, '.dump-stg-final');
|
||||
}
|
||||
|
||||
getHaskellCmmOutputFilename(inputFilename) {
|
||||
return inputFilename.replace(path.extname(inputFilename), '.dump-cmm');
|
||||
return utils.changeExtension(inputFilename, '.dump-cmm');
|
||||
}
|
||||
|
||||
// Currently called for getting macro expansion and HIR.
|
||||
@@ -1486,7 +1574,7 @@ export class BaseCompiler implements ICompiler {
|
||||
|
||||
getIrOutputFilename(inputFilename: string, filters: ParseFiltersAndOutputOptions): string {
|
||||
// filters are passed because rust needs to know whether a binary is being produced or not
|
||||
return inputFilename.replace(path.extname(inputFilename), '.ll');
|
||||
return utils.changeExtension(inputFilename, '.ll');
|
||||
}
|
||||
|
||||
getOutputFilename(dirPath: string, outputFilebase: string, key?: any): string {
|
||||
@@ -1848,26 +1936,32 @@ export class BaseCompiler implements ICompiler {
|
||||
|
||||
runExecutable(executable: string, executeParameters: ExecutableExecutionOptions, homeDir) {
|
||||
const maxExecOutputSize = this.env.ceProps('max-executable-output-size', 32 * 1024);
|
||||
|
||||
const execOptionsCopy: ExecutableExecutionOptions = JSON.parse(
|
||||
JSON.stringify(executeParameters),
|
||||
) as ExecutableExecutionOptions;
|
||||
|
||||
// Hardcoded fix for #2339. Ideally I'd have a config option for this, but for now this is plenty good enough.
|
||||
executeParameters.env = {
|
||||
execOptionsCopy.env = {
|
||||
ASAN_OPTIONS: 'color=always',
|
||||
UBSAN_OPTIONS: 'color=always',
|
||||
MSAN_OPTIONS: 'color=always',
|
||||
LSAN_OPTIONS: 'color=always',
|
||||
...executeParameters.env,
|
||||
};
|
||||
|
||||
if (this.compiler.executionWrapper) {
|
||||
executeParameters.args = [...this.compiler.executionWrapperArgs, executable, ...executeParameters.args];
|
||||
execOptionsCopy.args = [...this.compiler.executionWrapperArgs, executable, ...execOptionsCopy.args];
|
||||
executable = this.compiler.executionWrapper;
|
||||
}
|
||||
return this.execBinary(executable, maxExecOutputSize, executeParameters, homeDir);
|
||||
return this.execBinary(executable, maxExecOutputSize, execOptionsCopy, homeDir);
|
||||
}
|
||||
|
||||
protected fixExecuteParametersForInterpreting(executeParameters, outputFilename, key) {
|
||||
executeParameters.args.unshift(outputFilename);
|
||||
}
|
||||
|
||||
async handleInterpreting(key, executeParameters): Promise<CompilationResult> {
|
||||
async handleInterpreting(key, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
|
||||
const source = key.source;
|
||||
const dirPath = await this.newTempDir();
|
||||
const outputFilename = this.getExecutableFilename(dirPath, this.outputFilebase);
|
||||
@@ -1898,7 +1992,11 @@ export class BaseCompiler implements ICompiler {
|
||||
};
|
||||
}
|
||||
|
||||
async doExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
|
||||
async doExecution(
|
||||
key,
|
||||
executeParameters: ExecutableExecutionOptions,
|
||||
bypassCache: BypassCache,
|
||||
): Promise<CompilationResult> {
|
||||
if (this.compiler.interpreted) {
|
||||
return this.handleInterpreting(key, executeParameters);
|
||||
}
|
||||
@@ -1949,7 +2047,27 @@ export class BaseCompiler implements ICompiler {
|
||||
};
|
||||
}
|
||||
|
||||
async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
|
||||
async addHeaptrackResults(result: CompilationResult, dirPath?: string) {
|
||||
let dirPathToUse: string = '';
|
||||
if (dirPath) {
|
||||
dirPathToUse = dirPath;
|
||||
} else if (result.buildResult && result.buildResult.dirPath) {
|
||||
dirPathToUse = result.buildResult.dirPath;
|
||||
}
|
||||
|
||||
if (dirPathToUse === '') return;
|
||||
|
||||
const flamegraphFilepath = path.join(dirPathToUse, HeaptrackWrapper.FlamegraphFilename);
|
||||
if (await utils.fileExists(flamegraphFilepath)) {
|
||||
await this.addArtifactToResult(result, flamegraphFilepath, ArtifactType.heaptracktxt, 'Heaptrack results');
|
||||
}
|
||||
}
|
||||
|
||||
async handleExecution(
|
||||
key,
|
||||
executeParameters: ExecutableExecutionOptions,
|
||||
bypassCache: BypassCache,
|
||||
): Promise<CompilationResult> {
|
||||
// stringify now so shallow copying isn't a problem, I think the executeParameters get modified
|
||||
const execKey = JSON.stringify({key, executeParameters});
|
||||
if (!bypassExecutionCache(bypassCache)) {
|
||||
@@ -1960,6 +2078,15 @@ export class BaseCompiler implements ICompiler {
|
||||
}
|
||||
|
||||
const result = await this.doExecution(key, executeParameters, bypassCache);
|
||||
|
||||
if (executeParameters.runtimeTools) {
|
||||
for (const runtime of executeParameters.runtimeTools) {
|
||||
if (runtime.name === RuntimeToolType.heaptrack) {
|
||||
await this.addHeaptrackResults(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bypassExecutionCache(bypassCache)) {
|
||||
await this.env.cachePut(execKey, result, undefined);
|
||||
}
|
||||
@@ -1977,7 +2104,7 @@ export class BaseCompiler implements ICompiler {
|
||||
cacheKey.api = 'cmake';
|
||||
|
||||
if (cacheKey.filters) delete cacheKey.filters.execute;
|
||||
delete cacheKey.executionParameters;
|
||||
delete cacheKey.executeParameters;
|
||||
delete cacheKey.tools;
|
||||
|
||||
return cacheKey;
|
||||
@@ -2366,7 +2493,7 @@ export class BaseCompiler implements ICompiler {
|
||||
}
|
||||
|
||||
async cmake(files, key, bypassCache: BypassCache) {
|
||||
// key = {source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries};
|
||||
// key = {source, options, backendOptions, filters, bypassCache, tools, executeParameters, libraries};
|
||||
|
||||
if (!this.compiler.supportsBinary) {
|
||||
const errorResult: CompilationResult = {
|
||||
@@ -2390,10 +2517,12 @@ export class BaseCompiler implements ICompiler {
|
||||
const toolchainPath = this.getDefaultOrOverridenToolchainPath(key.backendOptions.overrides || []);
|
||||
|
||||
const doExecute = key.filters.execute;
|
||||
const executeParameters: ExecutableExecutionOptions = {
|
||||
|
||||
const executeOptions: ExecutableExecutionOptions = {
|
||||
args: key.executeParameters.args || [],
|
||||
stdin: key.executeParameters.stdin || '',
|
||||
ldPath: this.getSharedLibraryPathsAsLdLibraryPaths(key.libraries),
|
||||
args: key.executionParameters.args || [],
|
||||
stdin: key.executionParameters.stdin || '',
|
||||
runtimeTools: key.executeParameters?.runtimeTools || [],
|
||||
env: {},
|
||||
};
|
||||
|
||||
@@ -2511,8 +2640,16 @@ export class BaseCompiler implements ICompiler {
|
||||
fullResult.result.dirPath = dirPath;
|
||||
|
||||
if (this.compiler.supportsExecute && doExecute) {
|
||||
fullResult.execResult = await this.runExecutable(outputFilename, executeParameters, dirPath);
|
||||
fullResult.execResult = await this.runExecutable(outputFilename, executeOptions, dirPath);
|
||||
fullResult.didExecute = true;
|
||||
|
||||
if (executeOptions.runtimeTools) {
|
||||
for (const runtime of executeOptions.runtimeTools) {
|
||||
if (runtime.name === RuntimeToolType.heaptrack) {
|
||||
await this.addHeaptrackResults(fullResult, dirPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const optOutput = undefined;
|
||||
@@ -2521,7 +2658,7 @@ export class BaseCompiler implements ICompiler {
|
||||
fullResult.result,
|
||||
false,
|
||||
cacheKey,
|
||||
[],
|
||||
executeOptions,
|
||||
key.tools,
|
||||
cacheKey.backendOptions,
|
||||
cacheKey.filters,
|
||||
@@ -2584,7 +2721,7 @@ export class BaseCompiler implements ICompiler {
|
||||
filters,
|
||||
bypassCache: BypassCache,
|
||||
tools,
|
||||
executionParameters,
|
||||
executeParameters,
|
||||
libraries: CompileChildLibraries[],
|
||||
files,
|
||||
) {
|
||||
@@ -2601,9 +2738,12 @@ export class BaseCompiler implements ICompiler {
|
||||
|
||||
this.fixFiltersBeforeCacheKey(filters, options, files);
|
||||
|
||||
const executeParameters = {
|
||||
args: executionParameters.args || [],
|
||||
stdin: executionParameters.stdin || '',
|
||||
const executeOptions: ExecutableExecutionOptions = {
|
||||
args: executeParameters.args || [],
|
||||
stdin: executeParameters.stdin || '',
|
||||
ldPath: [],
|
||||
env: {},
|
||||
runtimeTools: executeParameters.runtimeTools || [],
|
||||
};
|
||||
|
||||
const key = this.getCacheKey(source, options, backendOptions, filters, tools, libraries, files);
|
||||
@@ -2631,7 +2771,7 @@ export class BaseCompiler implements ICompiler {
|
||||
async () => {
|
||||
const start = performance.now();
|
||||
executionQueueTimeHistogram.observe((start - queueTime) / 1000);
|
||||
const res = await this.handleExecution(key, executeParameters, bypassCache);
|
||||
const res = await this.handleExecution(key, executeOptions, bypassCache);
|
||||
executionTimeHistogram.observe((performance.now() - start) / 1000);
|
||||
return res;
|
||||
},
|
||||
@@ -2654,7 +2794,7 @@ export class BaseCompiler implements ICompiler {
|
||||
source = this.preProcess(source, filters);
|
||||
|
||||
if (backendOptions.executorRequest) {
|
||||
const execResult = await this.handleExecution(key, executeParameters, bypassCache);
|
||||
const execResult = await this.handleExecution(key, executeOptions, bypassCache);
|
||||
if (execResult && execResult.buildResult) {
|
||||
this.doTempfolderCleanup(execResult.buildResult);
|
||||
}
|
||||
@@ -2686,7 +2826,7 @@ export class BaseCompiler implements ICompiler {
|
||||
result,
|
||||
doExecute,
|
||||
key,
|
||||
executeParameters,
|
||||
executeOptions,
|
||||
tools,
|
||||
backendOptions,
|
||||
filters,
|
||||
@@ -2707,7 +2847,7 @@ export class BaseCompiler implements ICompiler {
|
||||
result,
|
||||
doExecute,
|
||||
key,
|
||||
executeParameters,
|
||||
executeOptions: ExecutableExecutionOptions,
|
||||
tools,
|
||||
backendOptions,
|
||||
filters,
|
||||
@@ -2719,7 +2859,7 @@ export class BaseCompiler implements ICompiler {
|
||||
) {
|
||||
// Start the execution as soon as we can, but only await it at the end.
|
||||
const execPromise =
|
||||
doExecute && result.code === 0 ? this.handleExecution(key, executeParameters, bypassCache) : null;
|
||||
doExecute && result.code === 0 ? this.handleExecution(key, executeOptions, bypassCache) : null;
|
||||
|
||||
if (result.hasOptOutput) {
|
||||
delete result.optPath;
|
||||
@@ -2812,9 +2952,16 @@ export class BaseCompiler implements ICompiler {
|
||||
async processOptOutput(optPath: string) {
|
||||
const output: compilerOptInfo.LLVMOptInfo[] = [];
|
||||
|
||||
const optStream = fs
|
||||
.createReadStream(optPath, {encoding: 'utf8'})
|
||||
.pipe(new compilerOptInfo.LLVMOptTransformer());
|
||||
const optStream = stream.pipeline(
|
||||
fs.createReadStream(optPath, {encoding: 'utf8'}),
|
||||
new compilerOptInfo.LLVMOptTransformer(),
|
||||
async err => {
|
||||
if (err) {
|
||||
logger.error(`Error handling opt output: ${err}`);
|
||||
SentryCapture(err, `Error handling opt output: ${await fs.readFile(optPath, 'utf-8')}`);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
for await (const opt of optStream as AsyncIterable<compilerOptInfo.LLVMOptInfo>) {
|
||||
if (opt.DebugLoc && opt.DebugLoc.File && opt.DebugLoc.File.includes(this.compileFilename)) {
|
||||
@@ -3151,6 +3298,33 @@ but nothing was dumped. Possible causes are:
|
||||
return await parser.getPossibleStdvers(this);
|
||||
}
|
||||
|
||||
async populatePossibleRuntimeTools() {
|
||||
this.compiler.possibleRuntimeTools = [];
|
||||
|
||||
if (HeaptrackWrapper.isSupported(this.env)) {
|
||||
this.compiler.possibleRuntimeTools.push({
|
||||
name: RuntimeToolType.heaptrack,
|
||||
description:
|
||||
'Heaptrack gets loaded into your code and collects the heap allocations, ' +
|
||||
"we'll display them in a flamegraph.",
|
||||
possibleOptions: [
|
||||
{
|
||||
name: 'graph',
|
||||
possibleValues: ['yes'],
|
||||
},
|
||||
{
|
||||
name: 'summary',
|
||||
possibleValues: ['stderr'],
|
||||
},
|
||||
{
|
||||
name: 'details',
|
||||
possibleValues: ['stderr'],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async populatePossibleOverrides() {
|
||||
const targets = await this.getTargetsAsOverrideValues();
|
||||
if (targets.length > 0) {
|
||||
@@ -3269,6 +3443,7 @@ but nothing was dumped. Possible causes are:
|
||||
const initResult = await this.getArgumentParser().parse(this);
|
||||
|
||||
await this.populatePossibleOverrides();
|
||||
await this.populatePossibleRuntimeTools();
|
||||
|
||||
logger.info(`${compiler} ${version} is ready`);
|
||||
return initResult;
|
||||
|
||||
@@ -86,14 +86,14 @@ export class BaseCFGParser {
|
||||
while (first !== last) {
|
||||
if (this.isFunctionEnd(asmArr[first].text)) {
|
||||
fnRange.end = first;
|
||||
result.push(_.clone(fnRange));
|
||||
if (fnRange.end > fnRange.start + 1) result.push(_.clone(fnRange));
|
||||
fnRange.start = first;
|
||||
}
|
||||
++first;
|
||||
}
|
||||
|
||||
fnRange.end = last;
|
||||
result.push(_.clone(fnRange));
|
||||
if (fnRange.end > fnRange.start + 1) result.push(_.clone(fnRange));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ export class BaseCFGParser {
|
||||
}
|
||||
|
||||
protected isFunctionName(line: AssemblyLine) {
|
||||
return line.text.trim().indexOf('.') !== 0;
|
||||
return line.text.trim().indexOf('.') !== 0 || line.text.startsWith('.omp_');
|
||||
}
|
||||
|
||||
protected getAsmDirective(txt: string) {
|
||||
@@ -167,7 +167,7 @@ export class BaseCFGParser {
|
||||
}
|
||||
|
||||
protected isFunctionEnd(x: string) {
|
||||
return x[0] !== ' ' && x[0] !== '.' && x.includes(':');
|
||||
return x[0] !== ' ' && (x[0] !== '.' || x.startsWith('.omp_')) && x.includes(':');
|
||||
}
|
||||
|
||||
protected isBasicBlockEnd(inst: string, prevInst: string) {
|
||||
|
||||
@@ -136,27 +136,47 @@ export class LlvmIrCfgParser extends BaseCFGParser {
|
||||
while (lastInst >= bb.start && asmArr[lastInst].text === '') {
|
||||
lastInst--;
|
||||
}
|
||||
|
||||
// Ad-hoc handling of a few known cases where LLVM splits a single instruction over multiple lines.
|
||||
const terminatingInstruction = (() => {
|
||||
if (asmArr[lastInst].text.trim().startsWith(']')) {
|
||||
// Llvm likes to split switches over multiple lines
|
||||
// Llvm likes to split switches over multiple lines:
|
||||
// switch i32 %0, label %5 [
|
||||
// i32 14, label %7
|
||||
// i32 60, label %2
|
||||
// i32 12, label %3
|
||||
// i32 4, label %4
|
||||
// ], !dbg !60
|
||||
// This is somewhat hacky. I'm not sure if there are other cases where this can happen, but for
|
||||
// now just handling this.
|
||||
const end = lastInst--;
|
||||
while (!asmArr[lastInst].text.includes('[')) {
|
||||
lastInst--;
|
||||
}
|
||||
return this.concatInstructions(asmArr, lastInst, end + 1);
|
||||
} else if (
|
||||
lastInst >= 1 &&
|
||||
asmArr[lastInst].text.includes('unwind label') &&
|
||||
asmArr[lastInst - 1].text.trim().includes('invoke ')
|
||||
) {
|
||||
// Handle multi-line `invoke` like:
|
||||
// invoke void @__cxa_throw(ptr nonnull %exception, ptr nonnull @typeinfo for int, ptr null) #3
|
||||
// to label %unreachable unwind label %lpad
|
||||
return this.concatInstructions(asmArr, lastInst - 1, lastInst + 1);
|
||||
} else if (
|
||||
lastInst >= 1 &&
|
||||
asmArr[lastInst - 1].text.includes('landingpad') &&
|
||||
asmArr[lastInst].text.includes('catch')
|
||||
) {
|
||||
// Handle multi-line `landingpad` like:
|
||||
// %0 = landingpad { ptr, i32 }
|
||||
// catch ptr null
|
||||
return this.concatInstructions(asmArr, lastInst - 1, lastInst + 1);
|
||||
} else {
|
||||
return asmArr[lastInst].text;
|
||||
}
|
||||
})();
|
||||
const terminator = terminatingInstruction.trim().split(' ')[0];
|
||||
const terminator = terminatingInstruction.includes('invoke ')
|
||||
? 'invoke'
|
||||
: terminatingInstruction.trim().split(' ')[0];
|
||||
const labels = [...terminatingInstruction.matchAll(this.labelReference)].map(m => m[1]);
|
||||
switch (terminator) {
|
||||
case 'ret':
|
||||
|
||||
@@ -77,9 +77,9 @@ export class ArmInstructionSetInfo extends BaseInstructionSetInfo {
|
||||
static returnInstruction = new RegExp(
|
||||
'(?:' +
|
||||
[`bx`, `ret`].map(re => `(?:${re})`).join('|') +
|
||||
')\\b.+' +
|
||||
`|pop\\s*\\{(?:r(?:\\d{2,}|[4-9]),\\s*)*pc\\}.+` +
|
||||
`|mov\\s*pc\\s*,.+`,
|
||||
')\\b.*' +
|
||||
`|pop\\s*\\{(?:r(?:\\d{2,}|[4-9]),\\s*)*pc\\}.*` +
|
||||
`|mov\\s*pc\\s*,.*`,
|
||||
);
|
||||
|
||||
static override get key(): InstructionSet[] {
|
||||
@@ -96,8 +96,8 @@ export class ArmInstructionSetInfo extends BaseInstructionSetInfo {
|
||||
|
||||
override getInstructionType(instruction: string) {
|
||||
const opcode = instruction.trim().split(' ')[0].toLowerCase();
|
||||
if (opcode.match(ArmInstructionSetInfo.unconditionalJumps)) return InstructionType.jmp;
|
||||
else if (opcode.match(ArmInstructionSetInfo.conditionalJumps)) return InstructionType.conditionalJmpInst;
|
||||
if (opcode.match(ArmInstructionSetInfo.conditionalJumps)) return InstructionType.conditionalJmpInst;
|
||||
else if (opcode.match(ArmInstructionSetInfo.unconditionalJumps)) return InstructionType.jmp;
|
||||
else if (instruction.trim().toLocaleLowerCase().match(ArmInstructionSetInfo.returnInstruction)) {
|
||||
return InstructionType.retInst;
|
||||
} else {
|
||||
|
||||
@@ -37,9 +37,11 @@ export class BaseInstructionSetInfo {
|
||||
}
|
||||
|
||||
isJmpInstruction(x: string) {
|
||||
return x.trim()[0] === 'j'
|
||||
|| !!x.match(/\bb\.*(eq|ne|cs|hs|cc|lo|hi|ls|ge|lt|gt|le|rge|rlt)?\b/)
|
||||
|| !!x.match(/(?:tbnz|tbz|cbnz|cbz)/);
|
||||
return (
|
||||
x.trim()[0] === 'j' ||
|
||||
!!x.match(/\bb\.*(eq|ne|cs|hs|cc|lo|hi|ls|ge|lt|gt|le|rge|rlt)?\b/) ||
|
||||
!!x.match(/(?:tbnz|tbz|cbnz|cbz)/)
|
||||
);
|
||||
}
|
||||
|
||||
getInstructionType(inst: string) {
|
||||
|
||||
@@ -38,8 +38,10 @@ export class ClientStateNormalizer {
|
||||
|
||||
setFilterSettingsFromComponent(compiler, component) {
|
||||
compiler.filters.binary = component.componentState.filters.binary;
|
||||
compiler.filters.binaryObject = component.componentState.filters.binaryObject;
|
||||
compiler.filters.execute = component.componentState.filters.execute;
|
||||
compiler.filters.labels = component.componentState.filters.labels;
|
||||
compiler.filters.libraryCode = component.componentState.filters.libraryCode;
|
||||
compiler.filters.directives = component.componentState.filters.directives;
|
||||
compiler.filters.commentOnly = component.componentState.filters.commentOnly;
|
||||
compiler.filters.trim = component.componentState.filters.trim;
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
|
||||
export class ClientStateCompilerOptions {
|
||||
binary = false;
|
||||
binaryObject = false;
|
||||
commentOnly = true;
|
||||
demangle = true;
|
||||
directives = true;
|
||||
execute = false;
|
||||
intel = true;
|
||||
labels = true;
|
||||
libraryCode = false;
|
||||
trim = false;
|
||||
debugCalls = false;
|
||||
|
||||
@@ -39,12 +41,14 @@ export class ClientStateCompilerOptions {
|
||||
|
||||
fromJsonData(jsondata) {
|
||||
if (jsondata.binary !== undefined) this.binary = jsondata.binary;
|
||||
if (jsondata.binaryObject !== undefined) this.binaryObject = jsondata.binaryObject;
|
||||
if (jsondata.commentOnly !== undefined) this.commentOnly = jsondata.commentOnly;
|
||||
if (jsondata.demangle !== undefined) this.demangle = jsondata.demangle;
|
||||
if (jsondata.directives !== undefined) this.directives = jsondata.directives;
|
||||
if (jsondata.execute !== undefined) this.execute = jsondata.execute;
|
||||
if (jsondata.intel !== undefined) this.intel = jsondata.intel;
|
||||
if (jsondata.labels !== undefined) this.labels = jsondata.labels;
|
||||
if (jsondata.libraryCode !== undefined) this.libraryCode = jsondata.libraryCode;
|
||||
if (jsondata.trim !== undefined) this.trim = jsondata.trim;
|
||||
if (jsondata.debugCalls !== undefined) this.debugCalls = jsondata.debugCalls;
|
||||
}
|
||||
|
||||
@@ -347,6 +347,7 @@ export class CompilerFinder {
|
||||
preamble: props<string>('licensePreamble'),
|
||||
},
|
||||
possibleOverrides: [],
|
||||
possibleRuntimeTools: [],
|
||||
$order: undefined as unknown as number, // TODO(jeremy-rifkin): Very dirty
|
||||
};
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ export {SdccCompiler} from './sdcc.js';
|
||||
export {SolidityCompiler} from './solidity.js';
|
||||
export {SPIRVCompiler} from './spirv.js';
|
||||
export {SwiftCompiler} from './swift.js';
|
||||
export {TableGenCompiler} from './tablegen.js';
|
||||
export {TenDRACompiler} from './tendra.js';
|
||||
export {TIC2000} from './tic2000.js';
|
||||
export {TinyCCompiler} from './tinyc.js';
|
||||
|
||||
@@ -889,6 +889,41 @@ export class CrystalParser extends BaseParser {
|
||||
}
|
||||
}
|
||||
|
||||
export class TableGenParser extends BaseParser {
|
||||
static async getPossibleActions(compiler): Promise<CompilerOverrideOptions> {
|
||||
const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']);
|
||||
return this.extractPossibleActions(utils.splitLines(result.stdout));
|
||||
}
|
||||
|
||||
static extractPossibleActions(lines: string[]): CompilerOverrideOptions {
|
||||
const actions: CompilerOverrideOptions = [];
|
||||
let found_actions = false;
|
||||
|
||||
for (const line of lines) {
|
||||
// Action options are in a section with this header.
|
||||
if (line.indexOf('Action to perform:') !== -1) {
|
||||
found_actions = true;
|
||||
} else if (found_actions) {
|
||||
// Actions are indented 6 spaces. The description follows after
|
||||
// a dash, for example:
|
||||
// <6 spaces>--do-thing - Description of thing.
|
||||
const action_match = line.match(/^ {6}(--[^\s]+)\s+-\s+(.+)$/);
|
||||
// The end of the option section is an option indented only 2 spaces.
|
||||
if (action_match == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
actions.push({
|
||||
name: action_match[1].substr(2) + ': ' + action_match[2],
|
||||
value: action_match[1],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
export class TypeScriptNativeParser extends BaseParser {
|
||||
static override async parse(compiler) {
|
||||
await this.getOptions(compiler, '--help');
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import {changeExtension} from '../utils.js';
|
||||
|
||||
export class CL430Compiler extends BaseCompiler {
|
||||
static get key() {
|
||||
@@ -52,7 +53,7 @@ export class CL430Compiler extends BaseCompiler {
|
||||
'--keep_asm',
|
||||
'--asm_extension=.s',
|
||||
'--output_file',
|
||||
this.filename(outputFilename.replace('.s', '')),
|
||||
this.filename(changeExtension(outputFilename, '')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,12 +77,7 @@ export class ClangCompiler extends BaseCompiler {
|
||||
|
||||
async addTimeTraceToResult(result: CompilationResult, dirPath: string, outputFilename: string) {
|
||||
let timeTraceJson = '';
|
||||
const outputExt = path.extname(outputFilename);
|
||||
if (outputExt) {
|
||||
timeTraceJson = outputFilename.replace(outputExt, '.json');
|
||||
} else {
|
||||
timeTraceJson += '.json';
|
||||
}
|
||||
timeTraceJson = utils.changeExtension(outputFilename, '.json');
|
||||
const jsonFilepath = path.join(dirPath, timeTraceJson);
|
||||
if (await utils.fileExists(jsonFilepath)) {
|
||||
this.addArtifactToResult(
|
||||
|
||||
@@ -27,10 +27,8 @@ import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import type {ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
|
||||
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import {propsFor} from '../properties.js';
|
||||
import * as utils from '../utils.js';
|
||||
|
||||
export class CleanCompiler extends BaseCompiler {
|
||||
@@ -38,14 +36,6 @@ export class CleanCompiler extends BaseCompiler {
|
||||
return 'clean';
|
||||
}
|
||||
|
||||
executionType: string;
|
||||
|
||||
constructor(compiler: PreliminaryCompilerInfo, env) {
|
||||
super(compiler, env);
|
||||
const execProps = propsFor('execution');
|
||||
this.executionType = execProps('executionType', 'none');
|
||||
}
|
||||
|
||||
override optionsForFilter(filters: ParseFiltersAndOutputOptions) {
|
||||
if (filters.binary) {
|
||||
return [];
|
||||
|
||||
@@ -29,14 +29,12 @@ import _ from 'underscore';
|
||||
|
||||
import type {CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
|
||||
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import type {
|
||||
BasicExecutionResult,
|
||||
ExecutableExecutionOptions,
|
||||
UnprocessedExecResult,
|
||||
import {
|
||||
type BasicExecutionResult,
|
||||
type ExecutableExecutionOptions,
|
||||
} from '../../types/execution/execution.interfaces.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import * as exec from '../exec.js';
|
||||
import {DotNetAsmParser} from '../parsers/asm-parser-dotnet.js';
|
||||
import * as utils from '../utils.js';
|
||||
|
||||
@@ -54,8 +52,6 @@ class DotNetCompiler extends BaseCompiler {
|
||||
private readonly crossgen2Path: string;
|
||||
private readonly sdkMajorVersion: number;
|
||||
|
||||
private versionString: string;
|
||||
|
||||
constructor(compilerInfo: PreliminaryCompilerInfo, env) {
|
||||
super(compilerInfo, env);
|
||||
|
||||
@@ -71,9 +67,8 @@ class DotNetCompiler extends BaseCompiler {
|
||||
this.langVersion = this.compilerProps<string>(`compiler.${this.compiler.id}.langVersion`);
|
||||
|
||||
this.corerunPath = path.join(this.clrBuildDir, 'corerun');
|
||||
this.crossgen2Path = path.join(this.clrBuildDir, 'crossgen2', 'crossgen2');
|
||||
this.crossgen2Path = path.join(this.clrBuildDir, 'crossgen2', 'crossgen2.dll');
|
||||
this.asm = new DotNetAsmParser();
|
||||
this.versionString = '';
|
||||
this.disassemblyLoaderPath = path.join(this.clrBuildDir, 'DisassemblyLoader', 'DisassemblyLoader.dll');
|
||||
}
|
||||
|
||||
@@ -301,8 +296,6 @@ class DotNetCompiler extends BaseCompiler {
|
||||
const toolOptions: string[] = [
|
||||
'--codegenopt',
|
||||
this.sdkMajorVersion === 6 ? 'NgenDisasm=*' : 'JitDisasm=*',
|
||||
'--codegenopt',
|
||||
this.sdkMajorVersion < 8 ? 'JitDiffableDasm=1' : 'JitDisasmDiffable=1',
|
||||
'--parallelism', '1',
|
||||
];
|
||||
const toolSwitches: string[] = [];
|
||||
@@ -315,9 +308,9 @@ class DotNetCompiler extends BaseCompiler {
|
||||
'DOTNET_JitDisasm=*',
|
||||
'DOTNET_JitDisasmAssemblies=CompilerExplorer',
|
||||
'DOTNET_TieredCompilation=0',
|
||||
this.sdkMajorVersion < 8 ? 'DOTNET_JitDiffableDasm=1' : 'DOTNET_JitDisasmDiffable=1',
|
||||
];
|
||||
let isAot = false;
|
||||
let overrideDiffable = false;
|
||||
let isCrossgen2 = this.sdkMajorVersion === 6;
|
||||
|
||||
while (options.length > 0) {
|
||||
@@ -338,6 +331,9 @@ class DotNetCompiler extends BaseCompiler {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (normalizedName === 'DOTNET_JITDIFFABLEDASM' || normalizedName === 'DOTNET_JITDISASMDIFFABLE') {
|
||||
overrideDiffable = true;
|
||||
}
|
||||
envVarFileContents.push(envVar);
|
||||
}
|
||||
} else if (currentOption === '-p' || currentOption === '--property') {
|
||||
@@ -357,10 +353,25 @@ class DotNetCompiler extends BaseCompiler {
|
||||
const value = options.shift();
|
||||
if (value) {
|
||||
toolOptions.push(currentOption, value);
|
||||
const normalizedValue = value.trim().toUpperCase();
|
||||
if (
|
||||
(currentOption === '--codegenopt' || currentOption === '--codegen-options') &&
|
||||
(normalizedValue.startsWith('JITDIFFABLEDASM=') ||
|
||||
normalizedValue.startsWith('JITDISASMDIFFABLE='))
|
||||
) {
|
||||
overrideDiffable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrideDiffable) {
|
||||
toolOptions.push('--codegenopt', this.sdkMajorVersion < 8 ? 'JitDiffableDasm=1' : 'JitDisasmDiffable=1');
|
||||
envVarFileContents.push(
|
||||
this.sdkMajorVersion < 8 ? 'DOTNET_JitDiffableDasm=1' : 'DOTNET_JitDisasmDiffable=1',
|
||||
);
|
||||
}
|
||||
|
||||
this.setCompilerExecOptions(execOptions, programDir);
|
||||
let compilerResult;
|
||||
|
||||
@@ -384,6 +395,7 @@ class DotNetCompiler extends BaseCompiler {
|
||||
|
||||
if (isCrossgen2) {
|
||||
const crossgen2Result = await this.runCrossgen2(
|
||||
compiler,
|
||||
execOptions,
|
||||
this.clrBuildDir,
|
||||
programDllPath,
|
||||
@@ -423,9 +435,9 @@ class DotNetCompiler extends BaseCompiler {
|
||||
|
||||
override async execBinary(
|
||||
executable: string,
|
||||
maxSize: number | undefined,
|
||||
maxSize: number,
|
||||
executeParameters: ExecutableExecutionOptions,
|
||||
homeDir: string | undefined,
|
||||
homeDir: string,
|
||||
): Promise<BasicExecutionResult> {
|
||||
const programDir = path.dirname(executable);
|
||||
const programOutputPath = path.join(programDir, 'bin', this.buildConfig, this.targetFramework);
|
||||
@@ -443,9 +455,8 @@ class DotNetCompiler extends BaseCompiler {
|
||||
execOptions.input = executeParameters.stdin;
|
||||
const execArgs = ['-p', 'System.Runtime.TieredCompilation=false', programDllPath, ...executeParameters.args];
|
||||
try {
|
||||
const execResult: UnprocessedExecResult = await exec.sandbox(this.corerunPath, execArgs, execOptions);
|
||||
return this.processExecutionResult(execResult);
|
||||
} catch (err: UnprocessedExecResult | any) {
|
||||
return this.execBinaryMaybeWrapped(this.corerunPath, execArgs, execOptions, executeParameters, homeDir);
|
||||
} catch (err: any) {
|
||||
if (err.code && err.stderr) {
|
||||
return this.processExecutionResult(err);
|
||||
} else {
|
||||
@@ -459,15 +470,13 @@ class DotNetCompiler extends BaseCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
async checkRuntimeVersion() {
|
||||
if (!this.versionString) {
|
||||
const versionFilePath = `${this.clrBuildDir}/version.txt`;
|
||||
if (fs.existsSync(versionFilePath)) {
|
||||
const versionString = await fs.readFile(versionFilePath);
|
||||
this.versionString = versionString.toString();
|
||||
} else {
|
||||
this.versionString = '<unknown version>';
|
||||
}
|
||||
async getRuntimeVersion() {
|
||||
const versionFilePath = `${this.clrBuildDir}/version.txt`;
|
||||
if (fs.existsSync(versionFilePath)) {
|
||||
const versionString = await fs.readFile(versionFilePath);
|
||||
return versionString.toString();
|
||||
} else {
|
||||
return '<unknown version>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,8 +488,6 @@ class DotNetCompiler extends BaseCompiler {
|
||||
options: string[],
|
||||
outputPath: string,
|
||||
) {
|
||||
await this.checkRuntimeVersion();
|
||||
|
||||
const corerunOptions = ['--clr-path', coreRoot, '--env', envPath].concat([
|
||||
...options,
|
||||
this.disassemblyLoaderPath,
|
||||
@@ -491,13 +498,16 @@ class DotNetCompiler extends BaseCompiler {
|
||||
|
||||
await fs.writeFile(
|
||||
outputPath,
|
||||
`// coreclr ${this.versionString}\n\n${result.stdout.map(o => o.text).reduce((a, n) => `${a}\n${n}`, '')}`,
|
||||
`// coreclr ${await this.getRuntimeVersion()}\n\n${result.stdout
|
||||
.map(o => o.text)
|
||||
.reduce((a, n) => `${a}\n${n}`, '')}`,
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async runCrossgen2(
|
||||
compiler: string,
|
||||
execOptions: ExecutionOptions,
|
||||
bclPath: string,
|
||||
dllPath: string,
|
||||
@@ -505,22 +515,21 @@ class DotNetCompiler extends BaseCompiler {
|
||||
toolSwitches: string[],
|
||||
outputPath: string,
|
||||
) {
|
||||
await this.checkRuntimeVersion();
|
||||
|
||||
// prettier-ignore
|
||||
const crossgen2Options = [
|
||||
this.crossgen2Path,
|
||||
'-r', path.join(bclPath, '/'),
|
||||
'-r', this.disassemblyLoaderPath,
|
||||
dllPath,
|
||||
'-o', `${AssemblyName}.r2r.dll`,
|
||||
].concat(toolOptions).concat(toolSwitches);
|
||||
|
||||
const compilerExecResult = await this.exec(this.crossgen2Path, crossgen2Options, execOptions);
|
||||
const compilerExecResult = await this.exec(compiler, crossgen2Options, execOptions);
|
||||
const result = this.transformToCompilationResult(compilerExecResult, dllPath);
|
||||
|
||||
await fs.writeFile(
|
||||
outputPath,
|
||||
`// crossgen2 ${this.versionString}\n\n${result.stdout
|
||||
`// crossgen2 ${await this.getRuntimeVersion()}\n\n${result.stdout
|
||||
.map(o => o.text)
|
||||
.reduce((a, n) => `${a}\n${n}`, '')}`,
|
||||
);
|
||||
|
||||
@@ -67,7 +67,7 @@ export class FakeCompiler implements ICompiler {
|
||||
return null;
|
||||
}
|
||||
|
||||
compile(source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries, files) {
|
||||
compile(source, options, backendOptions, filters, bypassCache, tools, executeParameters, libraries, files) {
|
||||
const inputBody = {
|
||||
input: {
|
||||
source: source,
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import path from 'path';
|
||||
import _ from 'underscore';
|
||||
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
@@ -40,6 +39,10 @@ export class HLSLCompiler extends BaseCompiler {
|
||||
|
||||
this.compiler.supportsIntel = false;
|
||||
this.spirvAsm = new SPIRVAsmParser(this.compilerProps);
|
||||
|
||||
this.compiler.supportsLLVMOptPipelineView = true;
|
||||
this.compiler.llvmOptArg = ['-print-before-all', '-print-after-all'];
|
||||
this.compiler.llvmOptNoDiscardValueNamesArg = [];
|
||||
}
|
||||
|
||||
override async generateAST(inputFilename, options) {
|
||||
@@ -91,10 +94,6 @@ export class HLSLCompiler extends BaseCompiler {
|
||||
return options;
|
||||
}
|
||||
|
||||
override getIrOutputFilename(inputFilename: string) {
|
||||
return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase).replace('.s', '.dxil');
|
||||
}
|
||||
|
||||
override async processAsm(result, filters, options) {
|
||||
if (this.isSpirv(result.asm)) {
|
||||
return this.spirvAsm.processAsm(result.asm, filters);
|
||||
|
||||
@@ -36,6 +36,7 @@ import * as utils from '../utils.js';
|
||||
|
||||
import {JavaParser} from './argument-parsers.js';
|
||||
import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
|
||||
import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
|
||||
|
||||
export class JavaCompiler extends BaseCompiler {
|
||||
static get key() {
|
||||
@@ -128,7 +129,7 @@ export class JavaCompiler extends BaseCompiler {
|
||||
return ['-Xlint:all', '-encoding', 'utf8'];
|
||||
}
|
||||
|
||||
override async handleInterpreting(key, executeParameters) {
|
||||
override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions) {
|
||||
const compileResult = await this.getOrBuildExecutable(key, BypassCache.None);
|
||||
if (compileResult.code === 0) {
|
||||
executeParameters.args = [
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
|
||||
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
|
||||
import {KotlinParser} from './argument-parsers.js';
|
||||
@@ -94,7 +95,7 @@ export class KotlinCompiler extends JavaCompiler {
|
||||
*
|
||||
* TODO(supergrecko): Find a better fix than this bandaid for execution
|
||||
*/
|
||||
override async handleInterpreting(key, executeParameters) {
|
||||
override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions) {
|
||||
const alteredKey = {
|
||||
...key,
|
||||
options: ['-include-runtime', '-d', 'example.jar'],
|
||||
|
||||
@@ -185,7 +185,7 @@ export class SPIRVCompiler extends BaseCompiler {
|
||||
|
||||
const index = newOptions.indexOf(outputFile);
|
||||
if (index !== -1) {
|
||||
newOptions[index] = inputFilename.replace(path.extname(inputFilename), '.ll');
|
||||
newOptions[index] = utils.changeExtension(inputFilename, '.ll');
|
||||
}
|
||||
|
||||
return super.runCompiler(compiler, newOptions, inputFilename, execOptions);
|
||||
|
||||
50
lib/compilers/tablegen.ts
Normal file
50
lib/compilers/tablegen.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {TableGenParser} from './argument-parsers.js';
|
||||
import {CompilerOverrideType} from '../../types/compilation/compiler-overrides.interfaces.js';
|
||||
|
||||
export class TableGenCompiler extends BaseCompiler {
|
||||
static get key() {
|
||||
return 'tablegen';
|
||||
}
|
||||
|
||||
override optionsForFilter(filters: ParseFiltersAndOutputOptions, outputFilename: string) {
|
||||
const options: string[] = ['-o', outputFilename];
|
||||
if (this.compiler.includePath) {
|
||||
options.push(`-I${this.compiler.includePath}`);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
override isCfgCompiler() {
|
||||
return false;
|
||||
}
|
||||
|
||||
override getArgumentParser() {
|
||||
return TableGenParser;
|
||||
}
|
||||
|
||||
override async populatePossibleOverrides() {
|
||||
const possibleActions = await TableGenParser.getPossibleActions(this);
|
||||
if (possibleActions.length > 0) {
|
||||
this.compiler.possibleOverrides?.push({
|
||||
name: CompilerOverrideType.action,
|
||||
display_title: 'Action',
|
||||
description:
|
||||
'The action to perform, which is the backend you wish to ' +
|
||||
'run. By default, the records are just printed as text. ' +
|
||||
'Many backends expect to find certain classes and defnitions ' +
|
||||
'in your source code. You may find details of those in the ' +
|
||||
'<a href="https://llvm.org/docs/TableGen/BackEnds.html" target="_blank">documentation</a>, ' +
|
||||
'but if not, refer to use of the backend in the ' +
|
||||
'<a href="https://github.com/llvm/llvm-project" target="_blank">LLVM Project</a> ' +
|
||||
'by searching for the command line name e.g. "gen-attrs".',
|
||||
flags: ['<value>'],
|
||||
values: possibleActions,
|
||||
default: '--print-records',
|
||||
});
|
||||
}
|
||||
|
||||
await super.populatePossibleOverrides();
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,10 @@ import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {LLVMIrBackendOptions} from '../../types/compilation/ir.interfaces.js';
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import {asSafeVer} from '../utils.js';
|
||||
import {asSafeVer, changeExtension} from '../utils.js';
|
||||
|
||||
import {TypeScriptNativeParser} from './argument-parsers.js';
|
||||
import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
|
||||
|
||||
export class TypeScriptNativeCompiler extends BaseCompiler {
|
||||
static get key() {
|
||||
@@ -88,7 +89,7 @@ export class TypeScriptNativeCompiler extends BaseCompiler {
|
||||
const outputFilename = this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase);
|
||||
// As per #4054, if we are asked for binary mode, the output will be in the .s file, no .ll will be emited
|
||||
if (!filters.binary) {
|
||||
return outputFilename.replace('.s', '.ll');
|
||||
return changeExtension(outputFilename, '.ll');
|
||||
}
|
||||
return outputFilename;
|
||||
}
|
||||
@@ -116,7 +117,7 @@ export class TypeScriptNativeCompiler extends BaseCompiler {
|
||||
return this.llvmIr.process(output.stderr.map(l => l.text).join('\n'), irOptions);
|
||||
}
|
||||
|
||||
override async handleInterpreting(key, executeParameters) {
|
||||
override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions) {
|
||||
executeParameters.args = [
|
||||
'--emit=jit',
|
||||
this.tscSharedLib ? '--shared-libs=' + this.tscSharedLib : '-nogc',
|
||||
|
||||
@@ -79,6 +79,10 @@ export class BaseDemangler extends AsmRegex {
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
public canDemangle() {
|
||||
return !!this.demanglerExe;
|
||||
}
|
||||
|
||||
// Iterates over the labels, demangle the label names and updates the start and
|
||||
// end position of the label.
|
||||
protected demangleLabels(labels, tree: PrefixTree) {
|
||||
|
||||
@@ -386,6 +386,7 @@ export async function sandbox(
|
||||
const type = execProps('sandboxType', 'firejail');
|
||||
const dispatchEntry = sandboxDispatchTable[type];
|
||||
if (!dispatchEntry) throw new Error(`Bad sandbox type ${type}`);
|
||||
if (!command) throw new Error(`No executable provided`);
|
||||
return await dispatchEntry(command, args, options);
|
||||
}
|
||||
|
||||
@@ -596,5 +597,6 @@ export async function execute(
|
||||
const type = execProps('executionType', 'none');
|
||||
const dispatchEntry = executeDispatchTable[type];
|
||||
if (!dispatchEntry) throw new Error(`Bad sandbox type ${type}`);
|
||||
if (!command) throw new Error(`No executable provided`);
|
||||
return await dispatchEntry(command, args, options);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
|
||||
import {BypassCache, ExecutionParams} from '../../types/compilation/compilation.interfaces.js';
|
||||
|
||||
// IF YOU MODIFY ANYTHING HERE PLEASE UPDATE THE DOCUMENTATION!
|
||||
|
||||
@@ -36,16 +36,11 @@ export type CompileRequestQueryArgs = {
|
||||
skipPopArgs?: string;
|
||||
};
|
||||
|
||||
export type ExecutionRequestParams = {
|
||||
args?: string | string[];
|
||||
stdin?: string;
|
||||
};
|
||||
|
||||
// TODO find more types for these.
|
||||
export type CompilationRequestArgs = {
|
||||
userArguments: string;
|
||||
compilerOptions: Record<string, any>;
|
||||
executeParameters: ExecutionRequestParams;
|
||||
executeParameters: ExecutionParams;
|
||||
filters: Record<string, boolean>;
|
||||
tools: any;
|
||||
libraries: any[];
|
||||
|
||||
@@ -42,12 +42,7 @@ import {logger} from '../logger.js';
|
||||
import {PropertyGetter} from '../properties.interfaces.js';
|
||||
import * as utils from '../utils.js';
|
||||
|
||||
import {
|
||||
CompileRequestJsonBody,
|
||||
CompileRequestQueryArgs,
|
||||
CompileRequestTextBody,
|
||||
ExecutionRequestParams,
|
||||
} from './compile.interfaces.js';
|
||||
import {CompileRequestJsonBody, CompileRequestQueryArgs, CompileRequestTextBody} from './compile.interfaces.js';
|
||||
import {remove} from '../../shared/common-utils.js';
|
||||
import {CompilerOverrideOptions} from '../../types/compilation/compiler-overrides.interfaces.js';
|
||||
import {BypassCache, CompileChildLibraries, ExecutionParams} from '../../types/compilation/compilation.interfaces.js';
|
||||
@@ -92,7 +87,7 @@ type ParsedRequest = {
|
||||
filters: ParseFiltersAndOutputOptions;
|
||||
bypassCache: BypassCache;
|
||||
tools: any;
|
||||
executionParameters: ExecutionParams;
|
||||
executeParameters: ExecutionParams;
|
||||
libraries: CompileChildLibraries[];
|
||||
};
|
||||
|
||||
@@ -353,7 +348,7 @@ export class CompileHandler {
|
||||
filters: ParseFiltersAndOutputOptions,
|
||||
bypassCache = BypassCache.None,
|
||||
tools;
|
||||
const execReqParams: ExecutionRequestParams = {};
|
||||
const execReqParams: ExecutionParams = {};
|
||||
let libraries: any[] = [];
|
||||
// IF YOU MODIFY ANYTHING HERE PLEASE UPDATE THE DOCUMENTATION!
|
||||
if (req.is('json')) {
|
||||
@@ -366,6 +361,7 @@ export class CompileHandler {
|
||||
const execParams = requestOptions.executeParameters || {};
|
||||
execReqParams.args = execParams.args;
|
||||
execReqParams.stdin = execParams.stdin;
|
||||
execReqParams.runtimeTools = execParams.runtimeTools;
|
||||
backendOptions = requestOptions.compilerOptions || {};
|
||||
filters = {...compiler.getDefaultFilters(), ...requestOptions.filters};
|
||||
tools = requestOptions.tools;
|
||||
@@ -410,11 +406,12 @@ export class CompileHandler {
|
||||
backendOptions.skipAsm = query.skipAsm === 'true';
|
||||
backendOptions.skipPopArgs = query.skipPopArgs === 'true';
|
||||
}
|
||||
const executionParameters: ExecutionParams = {
|
||||
const executeParameters: ExecutionParams = {
|
||||
args: Array.isArray(execReqParams.args)
|
||||
? execReqParams.args || ''
|
||||
: utils.splitArguments(execReqParams.args),
|
||||
stdin: execReqParams.stdin || '',
|
||||
runtimeTools: execReqParams.runtimeTools || [],
|
||||
};
|
||||
|
||||
tools = tools || [];
|
||||
@@ -433,7 +430,7 @@ export class CompileHandler {
|
||||
filters,
|
||||
bypassCache,
|
||||
tools,
|
||||
executionParameters,
|
||||
executeParameters,
|
||||
libraries,
|
||||
};
|
||||
}
|
||||
@@ -539,7 +536,7 @@ export class CompileHandler {
|
||||
return this.handleApiError(error, res, next);
|
||||
}
|
||||
|
||||
const {source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries} =
|
||||
const {source, options, backendOptions, filters, bypassCache, tools, executeParameters, libraries} =
|
||||
parsedRequest;
|
||||
|
||||
let files;
|
||||
@@ -563,17 +560,7 @@ export class CompileHandler {
|
||||
this.compileCounter.inc({language: compiler.lang.id});
|
||||
// eslint-disable-next-line promise/catch-or-return
|
||||
compiler
|
||||
.compile(
|
||||
source,
|
||||
options,
|
||||
backendOptions,
|
||||
filters,
|
||||
bypassCache,
|
||||
tools,
|
||||
executionParameters,
|
||||
libraries,
|
||||
files,
|
||||
)
|
||||
.compile(source, options, backendOptions, filters, bypassCache, tools, executeParameters, libraries, files)
|
||||
.then(
|
||||
result => {
|
||||
if (result.didExecute || (result.execResult && result.execResult.didExecute))
|
||||
|
||||
@@ -637,6 +637,17 @@ const definitions: Record<LanguageKey, LanguageDefinition> = {
|
||||
previewFilter: null,
|
||||
monacoDisassembly: null,
|
||||
},
|
||||
tablegen: {
|
||||
name: 'LLVM TableGen',
|
||||
monaco: 'tablegen',
|
||||
extensions: ['.td'],
|
||||
alias: [],
|
||||
logoUrl: 'llvm.png',
|
||||
logoUrlDark: null,
|
||||
formatter: null,
|
||||
previewFilter: null,
|
||||
monacoDisassembly: null,
|
||||
},
|
||||
toit: {
|
||||
name: 'Toit',
|
||||
monaco: 'toit',
|
||||
|
||||
@@ -242,7 +242,7 @@ export class LlvmIrParser {
|
||||
};
|
||||
}
|
||||
|
||||
if (options.demangle) {
|
||||
if (options.demangle && this.irDemangler.canDemangle()) {
|
||||
return {
|
||||
asm: (await this.irDemangler.process({asm: result})).asm,
|
||||
languageId: 'llvm-ir',
|
||||
|
||||
@@ -86,9 +86,14 @@ export class LLVMOptTransformer extends Transform {
|
||||
}
|
||||
|
||||
override _transform(chunk: any, encoding: string, done: TransformCallback) {
|
||||
this._buffer += chunk.toString();
|
||||
//buffer until we have a start and end if at any time i care about improving performance stash the offset
|
||||
this.processBuffer();
|
||||
// See https://stackoverflow.com/a/40928431/390318 - we have to catch all exceptions here
|
||||
try {
|
||||
this._buffer += chunk.toString();
|
||||
this.processBuffer();
|
||||
} catch (exception) {
|
||||
done(exception as Error);
|
||||
return;
|
||||
}
|
||||
done();
|
||||
}
|
||||
|
||||
|
||||
25
lib/runtime-tools/_all.ts
Normal file
25
lib/runtime-tools/_all.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
export {HeaptrackWrapper} from './heaptrack-wrapper.js';
|
||||
52
lib/runtime-tools/base-runtime-tool.ts
Normal file
52
lib/runtime-tools/base-runtime-tool.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
import {RuntimeToolOptions, TypicalExecutionFunc} from '../../types/execution/execution.interfaces.js';
|
||||
|
||||
export class BaseRuntimeTool {
|
||||
protected dirPath: string;
|
||||
protected sandboxFunc: TypicalExecutionFunc;
|
||||
protected execFunc: TypicalExecutionFunc;
|
||||
protected options: RuntimeToolOptions;
|
||||
protected sandboxType: string;
|
||||
|
||||
constructor(
|
||||
dirPath: string,
|
||||
sandboxFunc: TypicalExecutionFunc,
|
||||
execFunc: TypicalExecutionFunc,
|
||||
options: RuntimeToolOptions,
|
||||
sandboxType: string,
|
||||
) {
|
||||
this.dirPath = dirPath;
|
||||
this.sandboxFunc = sandboxFunc;
|
||||
this.execFunc = execFunc;
|
||||
this.options = options;
|
||||
this.sandboxType = sandboxType;
|
||||
}
|
||||
|
||||
protected getOptionValue(name: string): string | undefined {
|
||||
const option = this.options.find(opt => opt.name === name);
|
||||
if (option) return option.value;
|
||||
}
|
||||
}
|
||||
191
lib/runtime-tools/heaptrack-wrapper.ts
Normal file
191
lib/runtime-tools/heaptrack-wrapper.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
import * as path from 'path';
|
||||
import {ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
|
||||
import {
|
||||
RuntimeToolOptions,
|
||||
TypicalExecutionFunc,
|
||||
UnprocessedExecResult,
|
||||
} from '../../types/execution/execution.interfaces.js';
|
||||
import {O_NONBLOCK, O_RDWR} from 'constants';
|
||||
import * as fs from 'fs';
|
||||
import * as net from 'net';
|
||||
import {pipeline} from 'stream';
|
||||
import {unwrap} from '../assert.js';
|
||||
import {logger} from '../logger.js';
|
||||
import {executeDirect} from '../exec.js';
|
||||
import {PropertyGetter} from '../properties.interfaces.js';
|
||||
import {BaseRuntimeTool} from './base-runtime-tool.js';
|
||||
import {CompilationEnvironment} from '../compilation-env.js';
|
||||
|
||||
export class HeaptrackWrapper extends BaseRuntimeTool {
|
||||
private rawOutput: string;
|
||||
private pipe: string;
|
||||
private interpretedPath: string;
|
||||
private heaptrackPath: string;
|
||||
private mkfifoPath: string;
|
||||
private preload: string;
|
||||
private interpreter: string;
|
||||
private printer: string;
|
||||
|
||||
public static FlamegraphFilename = 'heaptrack.flamegraph.txt';
|
||||
|
||||
constructor(
|
||||
dirPath: string,
|
||||
sandboxFunc: TypicalExecutionFunc,
|
||||
execFunc: TypicalExecutionFunc,
|
||||
options: RuntimeToolOptions,
|
||||
ceProps: PropertyGetter,
|
||||
sandboxType: string,
|
||||
) {
|
||||
super(dirPath, sandboxFunc, execFunc, options, sandboxType);
|
||||
|
||||
this.mkfifoPath = ceProps('mkfifo', '/usr/bin/mkfifo');
|
||||
|
||||
this.pipe = path.join(this.dirPath, 'heaptrack_fifo');
|
||||
this.rawOutput = path.join(this.dirPath, 'heaptrack_raw.txt');
|
||||
this.interpretedPath = path.join(this.dirPath, 'heaptrack_interpreted.txt');
|
||||
|
||||
this.heaptrackPath = ceProps('heaptrackPath', '');
|
||||
|
||||
this.preload = path.join(this.heaptrackPath, 'lib/libheaptrack_preload.so');
|
||||
this.interpreter = path.join(this.heaptrackPath, 'libexec/heaptrack_interpret');
|
||||
this.printer = path.join(this.heaptrackPath, 'bin/heaptrack_print');
|
||||
}
|
||||
|
||||
public static isSupported(compiler: CompilationEnvironment) {
|
||||
return process.platform !== 'win32' && compiler.ceProps('heaptrackPath', '') !== '';
|
||||
}
|
||||
|
||||
private async mkfifo(path: string, rights: number) {
|
||||
await executeDirect(this.mkfifoPath, ['-m', rights.toString(8), path], {});
|
||||
}
|
||||
|
||||
private async makePipe() {
|
||||
await this.mkfifo(this.pipe, 0o666);
|
||||
}
|
||||
|
||||
private addToEnv(execOptions: ExecutionOptions) {
|
||||
if (!execOptions.env) execOptions.env = {};
|
||||
|
||||
if (execOptions.env.LD_PRELOAD) {
|
||||
execOptions.env.LD_PRELOAD = this.preload + ':' + execOptions.env.LD_PRELOAD;
|
||||
} else {
|
||||
execOptions.env.LD_PRELOAD = this.preload;
|
||||
}
|
||||
|
||||
if (this.sandboxType === 'nsjail') {
|
||||
execOptions.env.DUMP_HEAPTRACK_OUTPUT = '/app/heaptrack_fifo';
|
||||
} else {
|
||||
execOptions.env.DUMP_HEAPTRACK_OUTPUT = this.pipe;
|
||||
}
|
||||
}
|
||||
|
||||
private async interpret(execOptions: ExecutionOptions): Promise<UnprocessedExecResult> {
|
||||
return this.execFunc(this.interpreter, [this.rawOutput], execOptions);
|
||||
}
|
||||
|
||||
private async finishPipesAndStreams(fd: number, file: fs.WriteStream, socket: net.Socket) {
|
||||
socket.push(null);
|
||||
await new Promise(resolve => socket.end(() => resolve(true)));
|
||||
|
||||
await new Promise(resolve => file.end(() => resolve(true)));
|
||||
|
||||
file.write(Buffer.from([0]));
|
||||
|
||||
socket.resetAndDestroy();
|
||||
socket.unref();
|
||||
|
||||
await new Promise(resolve => {
|
||||
file.close(err => {
|
||||
if (err) logger.error('Error while closing heaptrack log: ', err);
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise(resolve => fs.close(fd, () => resolve(true)));
|
||||
}
|
||||
|
||||
private async interpretAndSave(execOptions: ExecutionOptions, result: UnprocessedExecResult) {
|
||||
const dirPath = unwrap(execOptions.appHome);
|
||||
execOptions.input = fs.readFileSync(this.rawOutput).toString('utf8');
|
||||
|
||||
const interpretResults = await this.interpret(execOptions);
|
||||
|
||||
if (this.getOptionValue('summary') === 'stderr') {
|
||||
result.stderr += interpretResults.stderr;
|
||||
}
|
||||
|
||||
fs.writeFileSync(this.interpretedPath, interpretResults.stdout);
|
||||
}
|
||||
|
||||
private async saveFlamegraph(execOptions: ExecutionOptions, result: UnprocessedExecResult) {
|
||||
const args = [this.interpretedPath];
|
||||
|
||||
if (this.getOptionValue('graph') === 'yes') {
|
||||
const flamesFilepath = path.join(this.dirPath, HeaptrackWrapper.FlamegraphFilename);
|
||||
args.push('-F', flamesFilepath);
|
||||
}
|
||||
|
||||
const printResults = await this.execFunc(this.printer, args, execOptions);
|
||||
if (printResults.stderr) result.stderr += printResults.stderr;
|
||||
|
||||
if (this.getOptionValue('details') === 'stderr') {
|
||||
result.stderr += printResults.stdout;
|
||||
}
|
||||
}
|
||||
|
||||
public async exec(filepath: string, args: string[], execOptions: ExecutionOptions): Promise<UnprocessedExecResult> {
|
||||
const dirPath = unwrap(execOptions.appHome);
|
||||
|
||||
const runOptions = JSON.parse(JSON.stringify(execOptions));
|
||||
const interpretOptions = JSON.parse(JSON.stringify(execOptions));
|
||||
this.addToEnv(runOptions);
|
||||
|
||||
await this.makePipe();
|
||||
|
||||
const fd = fs.openSync(this.pipe, O_NONBLOCK | O_RDWR);
|
||||
const socket = new net.Socket({fd, readable: true, writable: true});
|
||||
|
||||
const file = fs.createWriteStream(this.rawOutput);
|
||||
pipeline(socket, file, err => {
|
||||
if (err) {
|
||||
logger.error('Error during heaptrack pipeline: ', err);
|
||||
}
|
||||
});
|
||||
|
||||
const result = await this.sandboxFunc(filepath, args, runOptions);
|
||||
|
||||
await this.finishPipesAndStreams(fd, file, socket);
|
||||
|
||||
fs.unlinkSync(this.pipe);
|
||||
|
||||
await this.interpretAndSave(interpretOptions, result);
|
||||
|
||||
await this.saveFlamegraph(execOptions, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
123
lib/utils.ts
123
lib/utils.ts
@@ -74,6 +74,12 @@ export function maskRootdir(filepath: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function changeExtension(filename: string, newExtension: string): string {
|
||||
const lastDot = filename.lastIndexOf('.');
|
||||
if (lastDot === -1) return filename + newExtension;
|
||||
return filename.substring(0, lastDot) + newExtension;
|
||||
}
|
||||
|
||||
const ansiColoursRe = /\x1B\[[\d;]*[Km]/g;
|
||||
|
||||
function _parseOutputLine(line: string, inputFilename?: string, pathPrefix?: string) {
|
||||
@@ -98,40 +104,103 @@ function parseSeverity(message: string): number {
|
||||
|
||||
const SOURCE_RE = /^\s*<source>[(:](\d+)(:?,?(\d+):?)?[):]*\s*(.*)/;
|
||||
const SOURCE_WITH_FILENAME = /^\s*([\w.]*)[(:](\d+)(:?,?(\d+):?)?[):]*\s*(.*)/;
|
||||
const ATFILELINE_RE = /\s*at ([\w-/.]*):(\d+)/;
|
||||
|
||||
export function parseOutput(lines: string, inputFilename?: string, pathPrefix?: string): ResultLine[] {
|
||||
export enum LineParseOption {
|
||||
SourceMasking,
|
||||
RootMasking,
|
||||
SourceWithLineMessage,
|
||||
FileWithLineMessage,
|
||||
AtFileLine,
|
||||
}
|
||||
|
||||
export type LineParseOptions = LineParseOption[];
|
||||
|
||||
export const DefaultLineParseOptions = [
|
||||
LineParseOption.SourceMasking,
|
||||
LineParseOption.RootMasking,
|
||||
LineParseOption.SourceWithLineMessage,
|
||||
LineParseOption.FileWithLineMessage,
|
||||
];
|
||||
|
||||
function applyParse_SourceWithLine(lineObj: ResultLine, filteredLine: string, inputFilename?: string) {
|
||||
const match = filteredLine.match(SOURCE_RE);
|
||||
if (match) {
|
||||
const message = match[4].trim();
|
||||
lineObj.tag = {
|
||||
line: parseInt(match[1]),
|
||||
column: parseInt(match[3] || '0'),
|
||||
text: message,
|
||||
severity: parseSeverity(message),
|
||||
file: inputFilename ? path.basename(inputFilename) : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function applyParse_FileWithLine(lineObj: ResultLine, filteredLine: string) {
|
||||
const match = filteredLine.match(SOURCE_WITH_FILENAME);
|
||||
if (match) {
|
||||
const message = match[5].trim();
|
||||
lineObj.tag = {
|
||||
file: match[1],
|
||||
line: parseInt(match[2]),
|
||||
column: parseInt(match[4] || '0'),
|
||||
text: message,
|
||||
severity: parseSeverity(message),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function applyParse_AtFileLine(lineObj: ResultLine, filteredLine: string) {
|
||||
const match = filteredLine.match(ATFILELINE_RE);
|
||||
if (match) {
|
||||
if (match[1].startsWith('/app/')) {
|
||||
lineObj.tag = {
|
||||
file: match[1].replace(/^\/app\//, ''),
|
||||
line: parseInt(match[2]),
|
||||
column: 0,
|
||||
text: filteredLine,
|
||||
severity: 3,
|
||||
};
|
||||
} else if (!match[1].startsWith('/')) {
|
||||
lineObj.tag = {
|
||||
file: match[1],
|
||||
line: parseInt(match[2]),
|
||||
column: 0,
|
||||
text: filteredLine,
|
||||
severity: 3,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function parseOutput(
|
||||
lines: string,
|
||||
inputFilename?: string,
|
||||
pathPrefix?: string,
|
||||
options: LineParseOptions = DefaultLineParseOptions,
|
||||
): ResultLine[] {
|
||||
const result: ResultLine[] = [];
|
||||
eachLine(lines, line => {
|
||||
line = _parseOutputLine(line, inputFilename, pathPrefix);
|
||||
if (!inputFilename) {
|
||||
if (options.includes(LineParseOption.SourceMasking)) {
|
||||
line = _parseOutputLine(line, inputFilename, pathPrefix);
|
||||
}
|
||||
if (!inputFilename && options.includes(LineParseOption.RootMasking)) {
|
||||
line = maskRootdir(line);
|
||||
}
|
||||
if (line !== null) {
|
||||
const lineObj: ResultLine = {text: line};
|
||||
const filteredline = line.replace(ansiColoursRe, '');
|
||||
let match = filteredline.match(SOURCE_RE);
|
||||
if (match) {
|
||||
const message = match[4].trim();
|
||||
lineObj.tag = {
|
||||
line: parseInt(match[1]),
|
||||
column: parseInt(match[3] || '0'),
|
||||
text: message,
|
||||
severity: parseSeverity(message),
|
||||
file: inputFilename ? path.basename(inputFilename) : undefined,
|
||||
};
|
||||
} else {
|
||||
match = filteredline.match(SOURCE_WITH_FILENAME);
|
||||
if (match) {
|
||||
const message = match[5].trim();
|
||||
lineObj.tag = {
|
||||
file: match[1],
|
||||
line: parseInt(match[2]),
|
||||
column: parseInt(match[4] || '0'),
|
||||
text: message,
|
||||
severity: parseSeverity(message),
|
||||
};
|
||||
}
|
||||
}
|
||||
const filteredLine = line.replace(ansiColoursRe, '');
|
||||
|
||||
if (options.includes(LineParseOption.SourceWithLineMessage))
|
||||
applyParse_SourceWithLine(lineObj, filteredLine, inputFilename);
|
||||
|
||||
if (!lineObj.tag && options.includes(LineParseOption.FileWithLineMessage))
|
||||
applyParse_FileWithLine(lineObj, filteredLine);
|
||||
|
||||
if (!lineObj.tag && options.includes(LineParseOption.AtFileLine))
|
||||
applyParse_AtFileLine(lineObj, filteredLine);
|
||||
|
||||
result.push(lineObj);
|
||||
}
|
||||
});
|
||||
|
||||
3313
package-lock.json
generated
3313
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
68
package.json
68
package.json
@@ -27,7 +27,7 @@
|
||||
"@orchidjs/sifter": "^1.0.3",
|
||||
"@sentry/browser": "^7.28.1",
|
||||
"@sentry/node": "^7.28.1",
|
||||
"@types/morgan": "^1.9.6",
|
||||
"@types/morgan": "^1.9.8",
|
||||
"big-integer": "^1.6.51",
|
||||
"body-parser": "^1.20.2",
|
||||
"bootstrap": "^4.6.2",
|
||||
@@ -38,7 +38,7 @@
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint-plugin-header": "^3.1.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"events": "^3.3.0",
|
||||
"express": "^4.18.2",
|
||||
"file-saver": "^2.0.5",
|
||||
@@ -46,11 +46,9 @@
|
||||
"golden-layout": "^1.5.9",
|
||||
"http-proxy": "^1.18.1",
|
||||
"husky": "^8.0.3",
|
||||
"husky-init": "^8.0.0",
|
||||
"jquery": "^3.6.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"jquery": "^3.7.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jszip": "^3.7.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lru-cache": "^10.0.0",
|
||||
"lz-string": "^1.4.4",
|
||||
@@ -63,9 +61,8 @@
|
||||
"path-browserify": "^1.0.1",
|
||||
"popper.js": "^1.16.1",
|
||||
"profanities": "^3.0.1",
|
||||
"prom-client": "^14.0.1",
|
||||
"prom-client": "^15.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"qs": "^6.11.0",
|
||||
"request": "^2.88.2",
|
||||
"response-time": "^2.3.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
@@ -80,7 +77,6 @@
|
||||
"tree-kill": "^1.2.2",
|
||||
"triple-beam": "^1.3.0",
|
||||
"ts-node": "^10.4.0",
|
||||
"tslib": "^2.3.1",
|
||||
"underscore": "^1.13.2",
|
||||
"url-join": "^5.0.0",
|
||||
"whatwg-fetch": "^3.6.2",
|
||||
@@ -92,31 +88,29 @@
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-typescript": "^7.23.0",
|
||||
"@smithy/util-stream": "^2.0.15",
|
||||
"@types/body-parser": "^1.19.3",
|
||||
"@babel/preset-typescript": "^7.23.2",
|
||||
"@smithy/util-stream": "^2.0.17",
|
||||
"@types/body-parser": "^1.19.5",
|
||||
"@types/bootstrap": "^5.1.6",
|
||||
"@types/chai": "^4.3.6",
|
||||
"@types/chai-as-promised": "^7.1.6",
|
||||
"@types/express": "^4.17.18",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/fs-extra": "^11.0.2",
|
||||
"@types/http-proxy": "^1.17.12",
|
||||
"@types/jquery": "^3.5.10",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@types/mocha": "^10.0.2",
|
||||
"@types/node-targz": "^0.2.1",
|
||||
"@types/nopt": "^3.0.30",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/request": "^2.48.9",
|
||||
"@types/chai": "^4.3.9",
|
||||
"@types/chai-as-promised": "^7.1.8",
|
||||
"@types/express": "^4.17.20",
|
||||
"@types/file-saver": "^2.0.6",
|
||||
"@types/fs-extra": "^11.0.3",
|
||||
"@types/http-proxy": "^1.17.13",
|
||||
"@types/jquery": "^3.5.26",
|
||||
"@types/js-cookie": "^3.0.5",
|
||||
"@types/mocha": "^10.0.3",
|
||||
"@types/node-targz": "^0.2.3",
|
||||
"@types/nopt": "^3.0.31",
|
||||
"@types/request": "^2.48.11",
|
||||
"@types/shell-quote": "^1.7.1",
|
||||
"@types/tar-fs": "^2.0.2",
|
||||
"@types/temp": "^0.9.2",
|
||||
"@types/temp": "^0.9.3",
|
||||
"@types/underscore": "^1.11.4",
|
||||
"@types/webpack-env": "^1.18.2",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
||||
"@typescript-eslint/parser": "^6.7.5",
|
||||
"approvals": "^6.2.2",
|
||||
"approvals": "^6.2.4",
|
||||
"aws-sdk-client-mock": "^3.0.0",
|
||||
"c8": "^8.0.1",
|
||||
"chai": "^4.3.10",
|
||||
@@ -126,41 +120,39 @@
|
||||
"codecov": "^3.8.3",
|
||||
"css-loader": "^6.8.1",
|
||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||
"cypress": "^13.3.0",
|
||||
"cypress": "^13.4.0",
|
||||
"deep-equal-in-any-order": "^2.0.6",
|
||||
"eslint": "^8.51.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-formatter-github": "^1.1.4",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-jsdoc": "^46.8.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-requirejs": "^4.0.1",
|
||||
"eslint-plugin-sonarjs": "^0.21.0",
|
||||
"eslint-plugin-unicorn": "^48.0.1",
|
||||
"eslint-plugin-unicorn": "^49.0.0",
|
||||
"eslint-plugin-unused-imports": "^3.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"lint-staged": "^14.0.1",
|
||||
"lint-staged": "^15.0.2",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"mocha": "^10.2.0",
|
||||
"mock-fs": "^5.2.0",
|
||||
"monaco-editor-webpack-plugin": "^7.1.0",
|
||||
"nock": "^13.3.3",
|
||||
"nock": "^13.3.6",
|
||||
"prettier": "^3.0.3",
|
||||
"sass": "^1.69.1",
|
||||
"sass": "^1.69.4",
|
||||
"sass-loader": "^13.3.2",
|
||||
"sinon": "^16.1.0",
|
||||
"sinon": "^17.0.0",
|
||||
"source-map-loader": "^4.0.1",
|
||||
"supervisor": "^0.12.0",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"ts-loader": "^9.5.0",
|
||||
"typescript": "^4.9.5",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-middleware": "^6.1.1",
|
||||
"webpack-dev-server": "^4.15.1",
|
||||
"webpack-manifest-plugin": "^5.0.0"
|
||||
},
|
||||
"mocha": {
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import type {ConfiguredOverrides} from './compilation/compiler-overrides.interfaces.js';
|
||||
import type {ConfiguredRuntimeTools} from './execution/execution.interfaces.js';
|
||||
import type {CompilerState} from './panes/compiler.interfaces.js';
|
||||
import type {ExecutorState} from './panes/executor.interfaces.js';
|
||||
|
||||
export interface ICompilerShared {
|
||||
updateState(state: CompilerState | ExecutorState);
|
||||
getOverrides(): ConfiguredOverrides | undefined;
|
||||
getRuntimeTools(): ConfiguredRuntimeTools | undefined;
|
||||
}
|
||||
|
||||
@@ -27,11 +27,15 @@ import {CompilerOverridesWidget} from './widgets/compiler-overrides.js';
|
||||
import type {CompilerState} from './panes/compiler.interfaces.js';
|
||||
import type {ConfiguredOverrides} from './compilation/compiler-overrides.interfaces.js';
|
||||
import type {ExecutorState} from './panes/executor.interfaces.js';
|
||||
import {RuntimeToolsWidget} from './widgets/runtime-tools.js';
|
||||
import {ConfiguredRuntimeTools} from './execution/execution.interfaces.js';
|
||||
|
||||
export class CompilerShared implements ICompilerShared {
|
||||
private domRoot: JQuery<HTMLElement>;
|
||||
private overridesButton: JQuery<HTMLElement>;
|
||||
private overridesWidget: CompilerOverridesWidget;
|
||||
private runtimeToolsButton: JQuery<HTMLElement>;
|
||||
private runtimeToolsWidget?: RuntimeToolsWidget;
|
||||
|
||||
constructor(domRoot: JQuery, onChange: () => void) {
|
||||
this.domRoot = domRoot;
|
||||
@@ -43,6 +47,10 @@ export class CompilerShared implements ICompilerShared {
|
||||
return this.overridesWidget.get();
|
||||
}
|
||||
|
||||
public getRuntimeTools(): ConfiguredRuntimeTools | undefined {
|
||||
return this.runtimeToolsWidget?.get();
|
||||
}
|
||||
|
||||
public updateState(state: CompilerState | ExecutorState) {
|
||||
this.overridesWidget.setCompiler(state.compiler, state.lang);
|
||||
|
||||
@@ -51,17 +59,37 @@ export class CompilerShared implements ICompilerShared {
|
||||
} else {
|
||||
this.overridesWidget.setDefaults();
|
||||
}
|
||||
|
||||
if (this.runtimeToolsWidget) {
|
||||
this.runtimeToolsWidget.setCompiler(state.compiler, state.lang);
|
||||
if (state.runtimeTools) {
|
||||
this.runtimeToolsWidget.set(state.runtimeTools);
|
||||
} else {
|
||||
this.runtimeToolsWidget.setDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private initButtons(onChange: () => void) {
|
||||
this.overridesButton = this.domRoot.find('.btn.show-overrides');
|
||||
|
||||
this.overridesWidget = new CompilerOverridesWidget(this.domRoot, this.overridesButton, onChange);
|
||||
|
||||
this.runtimeToolsButton = this.domRoot.find('.btn.show-runtime-tools');
|
||||
if (this.runtimeToolsButton.length > 0) {
|
||||
this.runtimeToolsWidget = new RuntimeToolsWidget(this.domRoot, this.runtimeToolsButton, onChange);
|
||||
}
|
||||
}
|
||||
|
||||
private initCallbacks() {
|
||||
this.overridesButton.on('click', () => {
|
||||
this.overridesWidget.show();
|
||||
});
|
||||
|
||||
if (this.runtimeToolsButton.length > 0) {
|
||||
this.runtimeToolsButton.on('click', () => {
|
||||
this.runtimeToolsWidget?.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import {CfgState} from './panes/cfg-view.interfaces.js';
|
||||
import {LLVMOptPipelineViewState} from './panes/llvm-opt-pipeline.interfaces.js';
|
||||
import {GccDumpViewState} from './panes/gccdump-view.interfaces.js';
|
||||
import {ConfiguredOverrides} from './compilation/compiler-overrides.interfaces.js';
|
||||
import {ConfiguredRuntimeTools} from './execution/execution.interfaces.js';
|
||||
import {IrState} from './panes/ir-view.interfaces.js';
|
||||
export const COMPILER_COMPONENT_NAME = 'compiler';
|
||||
export const EXECUTOR_COMPONENT_NAME = 'executor';
|
||||
export const EDITOR_COMPONENT_NAME = 'codeEditor';
|
||||
@@ -93,6 +95,7 @@ export type PopulatedExecutorState = StateWithLanguage &
|
||||
compilationPanelShown: boolean;
|
||||
compilerOutShown: boolean;
|
||||
overrides?: ConfiguredOverrides;
|
||||
runtimeTools?: ConfiguredRuntimeTools;
|
||||
};
|
||||
export type ExecutorForTreeState = StateWithLanguage &
|
||||
StateWithTree & {
|
||||
@@ -202,13 +205,13 @@ export type PopulatedConformanceViewState = {
|
||||
};
|
||||
|
||||
export type EmptyIrViewState = EmptyState;
|
||||
export type PopulatedIrViewState = StateWithId & {
|
||||
editorid: number;
|
||||
treeid: number;
|
||||
source: string;
|
||||
irOutput: unknown;
|
||||
compilerName: string;
|
||||
};
|
||||
export type PopulatedIrViewState = StateWithId &
|
||||
IrState & {
|
||||
editorid: number;
|
||||
treeid: number;
|
||||
source: string;
|
||||
compilerName: string;
|
||||
};
|
||||
|
||||
export type EmptyLLVMOptPipelineViewState = EmptyState;
|
||||
export type PopulatedLLVMOptPipelineViewState = StateWithId &
|
||||
|
||||
@@ -108,6 +108,7 @@ import {
|
||||
EmptyStackUsageViewState,
|
||||
} from './components.interfaces.js';
|
||||
import {ConfiguredOverrides} from './compilation/compiler-overrides.interfaces.js';
|
||||
import {ConfiguredRuntimeTools} from './execution/execution.interfaces.js';
|
||||
|
||||
/** Get an empty compiler component. */
|
||||
export function getCompiler(editorId: number, lang: string): ComponentConfig<EmptyCompilerState> {
|
||||
@@ -186,6 +187,7 @@ export function getExecutorWith(
|
||||
compilerArgs,
|
||||
treeId: number,
|
||||
overrides?: ConfiguredOverrides,
|
||||
runtimeTools?: ConfiguredRuntimeTools,
|
||||
): ComponentConfig<PopulatedExecutorState> {
|
||||
return {
|
||||
type: 'component',
|
||||
@@ -200,6 +202,7 @@ export function getExecutorWith(
|
||||
compilationPanelShown: true,
|
||||
compilerOutShown: true,
|
||||
overrides: overrides,
|
||||
runtimeTools: runtimeTools,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import './ocaml-mode';
|
||||
import './openclc-mode';
|
||||
import './ptx-mode';
|
||||
import './spirv-mode';
|
||||
import './tablegen-mode';
|
||||
import './v-mode';
|
||||
import './vala-mode';
|
||||
import './zig-mode';
|
||||
|
||||
@@ -138,9 +138,9 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_character_literal = [
|
||||
[/'[^\\']'/, 'string', '@pop'],
|
||||
[/(')(@escapes)(')/, ['string', 'string.escape', {token: 'string', next: '@pop'}]],
|
||||
[/'/, 'string.invalid', '@pop'],
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.at_cpp2_literal_keyword = /(?:nullptr|true|false)\b/;
|
||||
cppfront.at_cpp2_literal = /\d|'|@at_cpp2_literal_keyword|@at_cpp2_string_literal/; // No `.`; `.0` isn't Cpp2.
|
||||
@@ -193,6 +193,15 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
/@at_cpp2_contract_kind/,
|
||||
{
|
||||
cases: {
|
||||
'$S2==contract_kind': {token: 'keyword.contract-kind', next: '@pop'},
|
||||
'@': {token: '@rematch', switchTo: 'parse_cpp2_non_operator_identifier.$S2'},
|
||||
},
|
||||
},
|
||||
],
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_non_operator_identifier.$S2'}],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_non_operator_identifier = [
|
||||
@@ -237,7 +246,7 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
cppfront.at_cpp2_type_id =
|
||||
/@at_cpp2_type_qualifier|@at_cpp2_non_operator_id_expression|@at_cpp2_function_type_id/;
|
||||
cppfront.at_cpp2_function_type_id =
|
||||
/\(\s*(?:(?:@at_cpp2_parameter_direction\s+)?@at_cpp2_non_operator_identifier\s*)?@at_cpp2_unnamed_declaration_head/;
|
||||
/\(\s*\)|\(\s*(?:(?:@at_cpp2_parameter_direction\s+)?@at_cpp2_non_operator_identifier\s*)?@at_cpp2_unnamed_declaration_head/;
|
||||
cppfront.tokenizer.parse_cpp2_type_id = [
|
||||
[/@at_cpp2_type_qualifier/, '@rematch', 'parse_cpp2_type_qualifier_seq'],
|
||||
[/@at_cpp2_keyword_type|_\b/, 'keyword.type.contextual', '@pop'],
|
||||
@@ -432,6 +441,13 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_using_statement = [
|
||||
{include: '@whitespace'},
|
||||
[/using\b/, 'keyword.using'],
|
||||
[/namespace\b/, 'keyword.namespace'],
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_id_expression'}],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_alternative = [
|
||||
{include: '@whitespace'},
|
||||
[
|
||||
@@ -535,51 +551,17 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_contract_string_literal = [
|
||||
{include: '@whitespace'},
|
||||
[/@at_cpp2_string_literal/, {token: '@rematch', switchTo: 'parse_cpp2_string_literal'}],
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_contract_logical_or_expression = [
|
||||
{include: '@whitespace'},
|
||||
[/@at_cpp2_expression/, '@rematch', 'parse_cpp2_logical_or_expression'],
|
||||
[/,/, {token: 'delimiter', switchTo: 'parse_cpp2_contract_string_literal'}],
|
||||
[/\]/, '@rematch', '@pop'],
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_contract_colon = [
|
||||
{include: '@whitespace'},
|
||||
[/:/, {token: 'delimiter.contract-colon', switchTo: 'parse_cpp2_contract_logical_or_expression'}],
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_contract_id_expression = [
|
||||
{include: '@whitespace'},
|
||||
[/(?:Default|Bounds|Null|Type|Testing)\b/, {token: 'constant', switchTo: 'parse_cpp2_contract_colon'}],
|
||||
[/@at_cpp2_non_operator_id_expression/, '@rematch', 'parse_cpp2_id_expression'],
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_contract_colon'}],
|
||||
];
|
||||
cppfront.at_cpp2_contract_kind = /(?:pre|post|assert)\b/;
|
||||
cppfront.tokenizer.parse_cpp2_contract_kind = [
|
||||
{include: '@whitespace'},
|
||||
[/@at_cpp2_contract_kind/, {token: 'keyword.contract-kind', switchTo: 'parse_cpp2_contract_id_expression'}],
|
||||
[/./, 'invalid', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_contract_body = [
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_contract_kind'}],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_contract = [
|
||||
[
|
||||
/\[/,
|
||||
{
|
||||
token: '@rematch',
|
||||
switchTo: 'parse_cpp2_balanced_squares.parse_cpp2_balanced_squares.parse_cpp2_contract_body',
|
||||
},
|
||||
],
|
||||
[/@at_cpp2_contract_kind/, '@rematch', 'parse_cpp2_id_expression.contract_kind'],
|
||||
[/\(/, {token: '@rematch', switchTo: 'parse_cpp2_expression_list'}],
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_statement = [
|
||||
{include: '@whitespace'},
|
||||
[/if\b/, {token: '@rematch', switchTo: 'parse_cpp2_selection_statement'}],
|
||||
[/using\b/, {token: '@rematch', switchTo: 'parse_cpp2_using_statement'}],
|
||||
[/inspect\b/, {token: '@rematch', switchTo: 'parse_cpp2_inspect_expression'}],
|
||||
[/return\b/, {token: '@rematch', switchTo: 'parse_cpp2_return_statement'}],
|
||||
[/@at_cpp2_jump_statement/, {token: '@rematch', switchTo: 'parse_cpp2_jump_statement'}],
|
||||
@@ -587,7 +569,7 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
[/{/, {token: '@rematch', switchTo: 'parse_cpp2_compound_statement'}],
|
||||
[/@at_cpp2_declaration_head/, {token: '@rematch', switchTo: 'parse_cpp2_declaration.definition'}],
|
||||
[/@at_cpp2_parameterized_statement/, {token: '@rematch', switchTo: 'parse_cpp2_parameterized_statement'}],
|
||||
[/\[/, {token: '@rematch', switchTo: 'parse_cpp2_contract'}],
|
||||
[/@at_cpp2_contract_kind/, {token: '@rematch', switchTo: 'parse_cpp2_contract'}],
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_expression_statement.$S2'}],
|
||||
];
|
||||
}
|
||||
@@ -678,25 +660,21 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
[/->/, 'invalid', '@pop'],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_contract_seq = [
|
||||
{include: '@whitespace'},
|
||||
[/\[/, '@rematch', 'parse_cpp2_contract'],
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
|
||||
cppfront.tokenizer.parse_cpp2_full_function_type = [
|
||||
{include: '@whitespace'},
|
||||
[/throws\b/, 'keyword'],
|
||||
[/->/, '@rematch', 'parse_cpp2_return_list'],
|
||||
[/\[/, '@rematch', 'parse_cpp2_contract_seq'],
|
||||
[/@at_cpp2_contract_kind/, '@rematch', 'parse_cpp2_contract'],
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
cppfront.at_cpp2_function_type_id_tail = /throws\b|->|@at_cpp2_contract_kind/;
|
||||
cppfront.tokenizer.parse_cpp2_terse_function = [
|
||||
{include: '@whitespace'},
|
||||
[/\(/, '@rematch', 'parse_cpp2_parameter_declaration_list'],
|
||||
[/throws\b|->|\[/, {token: '@rematch', switchTo: 'parse_cpp2_full_function_type'}],
|
||||
[/@at_cpp2_function_type_id_tail/, {token: '@rematch', switchTo: 'parse_cpp2_full_function_type'}],
|
||||
[/requires\b|==?|;/, '@rematch', '@pop'],
|
||||
[/@at_cpp2_expression/, {token: '@rematch', switchTo: 'parse_cpp2_expression'}],
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
cppfront.tokenizer.parse_cpp2_function_type = [
|
||||
[/./, {token: '@rematch', switchTo: 'parse_cpp2_terse_function'}],
|
||||
@@ -727,7 +705,15 @@ function definition(): monaco.languages.IMonarchLanguage {
|
||||
},
|
||||
],
|
||||
[/==?/, {token: 'delimiter', switchTo: 'parse_cpp2_declaration_initializer.$S2'}],
|
||||
[/;/, 'delimiter', '@pop'],
|
||||
[
|
||||
/;/,
|
||||
{
|
||||
cases: {
|
||||
'$S2==expression': {token: '@rematch', next: '@pop'},
|
||||
'@': {token: 'delimiter', next: '@pop'},
|
||||
},
|
||||
},
|
||||
],
|
||||
[/./, '@rematch', '@pop'],
|
||||
];
|
||||
|
||||
|
||||
194
static/modes/tablegen-mode.ts
Normal file
194
static/modes/tablegen-mode.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
import * as monaco from 'monaco-editor';
|
||||
|
||||
export function definition(): monaco.languages.IMonarchLanguage {
|
||||
return {
|
||||
keywords: [
|
||||
'assert',
|
||||
'class',
|
||||
'code',
|
||||
'def',
|
||||
'dump',
|
||||
'else',
|
||||
'false',
|
||||
'foreach',
|
||||
'defm',
|
||||
'defset',
|
||||
'defvar',
|
||||
'field',
|
||||
'if',
|
||||
'in',
|
||||
'include',
|
||||
'let',
|
||||
'multiclass',
|
||||
'then',
|
||||
'true',
|
||||
],
|
||||
standardTypes: ['bit', 'int', 'string', 'dag', 'bits', 'list'],
|
||||
operators: [
|
||||
'!add',
|
||||
'!and',
|
||||
'!cast',
|
||||
'!con',
|
||||
'!cond',
|
||||
'!dag',
|
||||
'!div',
|
||||
'!empty',
|
||||
'!eq',
|
||||
'!exists',
|
||||
'!filter',
|
||||
'!find',
|
||||
'!foldl',
|
||||
'!foreach',
|
||||
'!ge',
|
||||
'!getdagarg',
|
||||
'!getdagname',
|
||||
'!getdagop',
|
||||
'!gt',
|
||||
'!head',
|
||||
'!if',
|
||||
'!interleave',
|
||||
'!isa',
|
||||
'!le',
|
||||
'!listconcat',
|
||||
'!listremove',
|
||||
'!listsplat',
|
||||
'!logtwo',
|
||||
'!lt',
|
||||
'!mul',
|
||||
'!ne',
|
||||
'!not',
|
||||
'!or',
|
||||
'!range',
|
||||
'!repr',
|
||||
'!setdagarg',
|
||||
'!setdagname',
|
||||
'!setdagop',
|
||||
'!shl',
|
||||
'!size',
|
||||
'!sra',
|
||||
'!srl',
|
||||
'!strconcat',
|
||||
'!sub',
|
||||
'!subst',
|
||||
'!substr',
|
||||
'!tail',
|
||||
'!tolower',
|
||||
'!toupper',
|
||||
'!xor',
|
||||
],
|
||||
brackets: [
|
||||
{
|
||||
open: '(',
|
||||
close: ')',
|
||||
token: 'delimiter.parenthesis',
|
||||
},
|
||||
{
|
||||
open: '[',
|
||||
close: ']',
|
||||
token: 'delimiter.square',
|
||||
},
|
||||
{
|
||||
open: '<',
|
||||
close: '>',
|
||||
token: 'delimiter.angle',
|
||||
},
|
||||
],
|
||||
symbols: /[=><!~&|+\-*/^]+/,
|
||||
delimiters: /[;=.:,`]/,
|
||||
escapes: /\\(?:[abfnrtv\\'\n\r]|x[0-9A-Fa-f]{2}|[0-7]{3}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8}|N\{\w+\})/,
|
||||
|
||||
tokenizer: {
|
||||
root: [
|
||||
[
|
||||
/[a-zA-Z_][a-zA-Z0-9_]*/,
|
||||
{
|
||||
cases: {
|
||||
'@standardTypes': 'type',
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'identifier',
|
||||
},
|
||||
},
|
||||
],
|
||||
{include: '@whitespace'},
|
||||
|
||||
[/[()[\]<>]/, '@brackets'],
|
||||
|
||||
// Numbers
|
||||
[/0x([abcdef]|[ABCDEF]|\d)+/, 'number.hex'],
|
||||
[/0b[01]+1/, 'number.binary'],
|
||||
// Decimal may have + or - in front.
|
||||
[/[-+]?\d+/, 'number'],
|
||||
|
||||
// Strings
|
||||
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
|
||||
[/"/, 'string', '@string'],
|
||||
|
||||
[
|
||||
/@delimiters/,
|
||||
{
|
||||
cases: {
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'delimiter',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
whitespace: [
|
||||
[/[ \t\r\n]+/, 'white'],
|
||||
[/\/\*/, 'comment', '@comment'],
|
||||
[/\/\+/, 'comment', '@nestingcomment'],
|
||||
[/\/\/.*$/, 'comment'],
|
||||
],
|
||||
|
||||
comment: [
|
||||
[/[^/*]+/, 'comment'],
|
||||
[/\*\//, 'comment', '@pop'],
|
||||
[/[/*]/, 'comment'],
|
||||
],
|
||||
|
||||
nestingcomment: [
|
||||
[/[^/+]+/, 'comment'],
|
||||
[/\/\+/, 'comment', '@push'],
|
||||
[/\/\+/, 'comment.invalid'],
|
||||
[/\+\//, 'comment', '@pop'],
|
||||
[/[/+]/, 'comment'],
|
||||
],
|
||||
|
||||
string: [
|
||||
[/[^\\"]+/, 'string'],
|
||||
[/@escapes/, 'string.escape'],
|
||||
[/\\./, 'string.escape.invalid'],
|
||||
[/"/, 'string', '@pop'],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
monaco.languages.register({id: 'tablegen'});
|
||||
monaco.languages.setMonarchTokensProvider('tablegen', definition());
|
||||
|
||||
export {};
|
||||
@@ -23,6 +23,7 @@
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import type {ConfiguredOverrides} from '../compilation/compiler-overrides.interfaces.js';
|
||||
import {ConfiguredRuntimeTools} from '../execution/execution.interfaces.js';
|
||||
import {WidgetState} from '../widgets/libs-widget.interfaces.js';
|
||||
import {MonacoPaneState} from './pane.interfaces.js';
|
||||
|
||||
@@ -36,6 +37,7 @@ export type CompilerState = WidgetState & {
|
||||
wantOptInfo?: boolean;
|
||||
lang?: string;
|
||||
overrides?: ConfiguredOverrides;
|
||||
runtimeTools?: ConfiguredRuntimeTools;
|
||||
};
|
||||
|
||||
// TODO(jeremy-rifkin): This omit is ugly. There should be a better way to do this.
|
||||
|
||||
@@ -679,6 +679,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
currentState.options,
|
||||
treeId ?? 0,
|
||||
currentState.overrides,
|
||||
currentState.runtimeTools,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1281,6 +1282,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
executeParameters: {
|
||||
args: '',
|
||||
stdin: '',
|
||||
runtimeTools: this.getCurrentState().runtimeTools,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1768,14 +1770,46 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
} else if (artifact.type === ArtifactType.smsrom) {
|
||||
this.emulateMiracleSMS(artifact.content);
|
||||
} else if (artifact.type === ArtifactType.timetrace) {
|
||||
this.offerViewInPerfetto(artifact);
|
||||
this.offerViewInSpeedscope(artifact);
|
||||
} else if (artifact.type === ArtifactType.c64prg) {
|
||||
this.emulateC64Prg(artifact);
|
||||
} else if (artifact.type === ArtifactType.heaptracktxt) {
|
||||
this.offerViewInSpeedscope(artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offerViewInSpeedscope(artifact: Artifact): void {
|
||||
this.alertSystem.notify(
|
||||
'Click ' +
|
||||
'<a target="_blank" id="download_link" style="cursor:pointer;" click="javascript:;">here</a>' +
|
||||
' to view ' +
|
||||
artifact.title +
|
||||
' in Speedscope',
|
||||
{
|
||||
group: artifact.type,
|
||||
collapseSimilar: false,
|
||||
dismissTime: 10000,
|
||||
onBeforeShow: function (elem) {
|
||||
elem.find('#download_link').on('click', () => {
|
||||
const tmstr = Date.now();
|
||||
const live_url = 'https://static.ce-cdn.net/speedscope/index.html';
|
||||
const speedscope_url =
|
||||
live_url +
|
||||
'?' +
|
||||
tmstr +
|
||||
'#customFilename=' +
|
||||
artifact.name +
|
||||
'&b64data=' +
|
||||
artifact.content;
|
||||
window.open(speedscope_url);
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
offerViewInPerfetto(artifact: Artifact): void {
|
||||
this.alertSystem.notify(
|
||||
'Click ' +
|
||||
@@ -1784,8 +1818,8 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
artifact.title +
|
||||
' in Perfetto',
|
||||
{
|
||||
group: 'emulation',
|
||||
collapseSimilar: true,
|
||||
group: artifact.type,
|
||||
collapseSimilar: false,
|
||||
dismissTime: 10000,
|
||||
onBeforeShow: function (elem) {
|
||||
elem.find('#download_link').on('click', () => {
|
||||
@@ -3202,6 +3236,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
flagsViewOpen: this.flagsViewOpen,
|
||||
deviceViewOpen: this.deviceViewOpen,
|
||||
overrides: this.compilerShared.getOverrides(),
|
||||
runtimeTools: this.compilerShared.getRuntimeTools(),
|
||||
};
|
||||
this.paneRenaming.addState(state);
|
||||
this.fontScale.addState(state);
|
||||
|
||||
@@ -41,7 +41,7 @@ import '../formatter-registry';
|
||||
import '../modes/_all';
|
||||
import {MonacoPane} from './pane.js';
|
||||
import {Hub} from '../hub.js';
|
||||
import {MonacoPaneState} from './pane.interfaces.js';
|
||||
import {MonacoPaneState, PaneState} from './pane.interfaces.js';
|
||||
import {Container} from 'golden-layout';
|
||||
import {EditorState, LanguageSelectData} from './editor.interfaces.js';
|
||||
import {Language, LanguageKey} from '../../types/languages.interfaces.js';
|
||||
@@ -165,6 +165,15 @@ export class Editor extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Edit
|
||||
// });
|
||||
}
|
||||
|
||||
override initializeCompilerInfo(state: PaneState) {
|
||||
this.compilerInfo = {
|
||||
compilerId: 0,
|
||||
compilerName: '',
|
||||
editorId: 0,
|
||||
treeId: 0,
|
||||
};
|
||||
}
|
||||
|
||||
override initializeDefaults(): void {
|
||||
this.ourCompilers = {};
|
||||
this.ourExecutors = {};
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import type {ConfiguredOverrides} from '../compilation/compiler-overrides.interfaces.js';
|
||||
import type {ConfiguredOverrides} from '../../types/compilation/compiler-overrides.interfaces.js';
|
||||
import type {ConfiguredRuntimeTools} from '../../types/execution/execution.interfaces.js';
|
||||
import type {WidgetState} from '../widgets/libs-widget.interfaces.js';
|
||||
|
||||
export type ExecutorState = WidgetState & {
|
||||
@@ -40,4 +41,5 @@ export type ExecutorState = WidgetState & {
|
||||
lang?: string;
|
||||
compiler: string;
|
||||
overrides?: ConfiguredOverrides;
|
||||
runtimeTools?: ConfiguredRuntimeTools;
|
||||
};
|
||||
|
||||
@@ -61,6 +61,7 @@ import {CompilerShared} from '../compiler-shared.js';
|
||||
import {LangInfo} from './compiler-request.interfaces.js';
|
||||
import {escapeHTML} from '../../shared/common-utils.js';
|
||||
import {CompilerVersionInfo, setCompilerVersionPopoverForPane} from '../widgets/compiler-version-info.js';
|
||||
import {Artifact, ArtifactType} from '../../types/tool.interfaces.js';
|
||||
|
||||
const languages = options.languages;
|
||||
|
||||
@@ -190,6 +191,15 @@ export class Executor extends Pane<ExecutorState> {
|
||||
}
|
||||
}
|
||||
|
||||
override initializeCompilerInfo(state: PaneState) {
|
||||
this.compilerInfo = {
|
||||
compilerId: 0,
|
||||
compilerName: '',
|
||||
editorId: state.editorid,
|
||||
treeId: state.treeid,
|
||||
};
|
||||
}
|
||||
|
||||
override initializeStateDependentProperties(state: PaneState & ExecutorState) {
|
||||
this.sourceTreeId = state.tree ?? null;
|
||||
this.settings = Settings.getStoredSettings();
|
||||
@@ -279,6 +289,7 @@ export class Executor extends Pane<ExecutorState> {
|
||||
executeParameters: {
|
||||
args: this.executionArguments,
|
||||
stdin: this.executionStdin,
|
||||
runtimeTools: this.compilerShared.getRuntimeTools(),
|
||||
},
|
||||
compilerOptions: {
|
||||
executorRequest: true,
|
||||
@@ -678,6 +689,48 @@ export class Executor extends Pane<ExecutorState> {
|
||||
|
||||
if (this.currentLangId)
|
||||
this.eventHub.emit('executeResult', this.id, this.compiler, result, languages[this.currentLangId]);
|
||||
|
||||
this.offerFilesIfPossible(result);
|
||||
}
|
||||
|
||||
offerFilesIfPossible(result: CompilationResult) {
|
||||
if (result.artifacts) {
|
||||
for (const artifact of result.artifacts) {
|
||||
if (artifact.type === ArtifactType.heaptracktxt) {
|
||||
this.offerViewInSpeedscope(artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offerViewInSpeedscope(artifact: Artifact): void {
|
||||
this.alertSystem.notify(
|
||||
'Click ' +
|
||||
'<a target="_blank" id="download_link" style="cursor:pointer;" click="javascript:;">here</a>' +
|
||||
' to view ' +
|
||||
artifact.title +
|
||||
' in Speedscope',
|
||||
{
|
||||
group: artifact.type,
|
||||
collapseSimilar: false,
|
||||
dismissTime: 10000,
|
||||
onBeforeShow: function (elem) {
|
||||
elem.find('#download_link').on('click', () => {
|
||||
const tmstr = Date.now();
|
||||
const live_url = 'https://static.ce-cdn.net/speedscope/index.html';
|
||||
const speedscope_url =
|
||||
live_url +
|
||||
'?' +
|
||||
tmstr +
|
||||
'#customFilename=' +
|
||||
artifact.name +
|
||||
'&b64data=' +
|
||||
artifact.content;
|
||||
window.open(speedscope_url);
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onCompileResponse(request: CompilationRequest, result: CompilationResult, cached: boolean): void {
|
||||
@@ -973,35 +1026,34 @@ export class Executor extends Pane<ExecutorState> {
|
||||
return this.settings.executorCompileOnChange;
|
||||
}
|
||||
|
||||
onOptionsChange(options: string): void {
|
||||
this.options = options;
|
||||
doTypicalOnChange() {
|
||||
this.updateState();
|
||||
if (this.shouldEmitExecutionOnFieldChange()) {
|
||||
this.compile();
|
||||
}
|
||||
}
|
||||
|
||||
onOptionsChange(options: string): void {
|
||||
this.options = options;
|
||||
this.doTypicalOnChange();
|
||||
}
|
||||
|
||||
onExecArgsChange(args: string): void {
|
||||
this.executionArguments = args;
|
||||
this.updateState();
|
||||
if (this.shouldEmitExecutionOnFieldChange()) {
|
||||
this.compile();
|
||||
}
|
||||
this.doTypicalOnChange();
|
||||
}
|
||||
|
||||
onCompilerOverridesChange(): void {
|
||||
this.updateState();
|
||||
if (this.shouldEmitExecutionOnFieldChange()) {
|
||||
this.compile();
|
||||
}
|
||||
this.doTypicalOnChange();
|
||||
}
|
||||
|
||||
onRuntimeToolsChange(): void {
|
||||
this.doTypicalOnChange();
|
||||
}
|
||||
|
||||
onExecStdinChange(newStdin: string): void {
|
||||
this.executionStdin = newStdin;
|
||||
this.updateState();
|
||||
if (this.shouldEmitExecutionOnFieldChange()) {
|
||||
this.compile();
|
||||
}
|
||||
this.doTypicalOnChange();
|
||||
}
|
||||
|
||||
onRequestCompilation(editorId: number | boolean, treeId: number | boolean): void {
|
||||
@@ -1086,6 +1138,7 @@ export class Executor extends Pane<ExecutorState> {
|
||||
stdinPanelShown: !this.panelStdin.hasClass('d-none'),
|
||||
wrap: this.toggleWrapButton.get().wrap,
|
||||
overrides: this.compilerShared.getOverrides(),
|
||||
runtimeTools: this.compilerShared.getRuntimeTools(),
|
||||
};
|
||||
|
||||
this.paneRenaming.addState(state);
|
||||
|
||||
@@ -129,6 +129,14 @@ export class Ir extends MonacoPane<monaco.editor.IStandaloneCodeEditor, IrState>
|
||||
});
|
||||
}
|
||||
|
||||
override getCurrentState() {
|
||||
return {
|
||||
...this.options.get(),
|
||||
...this.filters.get(),
|
||||
...super.getCurrentState(),
|
||||
};
|
||||
}
|
||||
|
||||
override registerEditorActions(): void {
|
||||
this.editor.addAction({
|
||||
id: 'viewsource',
|
||||
|
||||
@@ -171,7 +171,9 @@ export class Output extends Pane<OutputState> {
|
||||
}
|
||||
|
||||
addOutputLines(result: CompilationResult) {
|
||||
const stdout = result.stdout;
|
||||
// When MS upgrade to a server version later than Nov 11, 2022 (the merge of PR #4278)
|
||||
// the `undefined` check can be removed.
|
||||
const stdout = (result.stdout as any) !== undefined ? result.stdout : [];
|
||||
const stderr = result.stderr;
|
||||
for (const obj of stdout.concat(stderr)) {
|
||||
const lineNumber = obj.tag ? obj.tag.line : obj.line;
|
||||
|
||||
@@ -371,6 +371,8 @@ pre.content.wrap * {
|
||||
|
||||
.toast {
|
||||
max-width: 100% !important;
|
||||
// Not set in Bootstrap 4, remove once we upgrade
|
||||
z-index: 1090;
|
||||
}
|
||||
|
||||
.toast-header .close {
|
||||
@@ -378,6 +380,10 @@ pre.content.wrap * {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.toast a {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.font-size-list {
|
||||
min-width: 43px !important;
|
||||
max-height: 70% !important;
|
||||
@@ -691,10 +697,6 @@ div.populararguments div.dropdown-menu {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#overrides-selection .override-search-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#overrides-selection .overrides-how-to-use {
|
||||
font-size: smaller;
|
||||
}
|
||||
@@ -742,6 +744,72 @@ div.populararguments div.dropdown-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#runtimetools-selection .modal-body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-how-to-use {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-selected-col {
|
||||
padding: 0 15px 0 0;
|
||||
min-width: 250px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-results-col {
|
||||
padding: 0 0 0 0;
|
||||
min-width: 450px;
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetool-results-items .card {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
#runtimetools-selection.mobile .runtimetools-results-col {
|
||||
min-width: 250px;
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-results-col span.override {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-results-col span.override-fav {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-favorites-col {
|
||||
padding: 0 0 0 15px;
|
||||
min-width: 325px;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtimetools-favorites-col button {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#runtimetools-selection.mobile .runtimetools-favorites-col {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#runtimetools-selection .runtime-tool-option {
|
||||
line-height: 35px;
|
||||
}
|
||||
#runtimetools-selection .tool-option-name {
|
||||
display: inline-block;
|
||||
min-width: 150px;
|
||||
}
|
||||
#runtimetools-selection .tool-option-select {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
#runtimetools-selection .tool-fav {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.ces-content-root {
|
||||
min-height: 100px;
|
||||
max-height: calc(
|
||||
|
||||
412
static/widgets/runtime-tools.ts
Normal file
412
static/widgets/runtime-tools.ts
Normal file
@@ -0,0 +1,412 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
import $ from 'jquery';
|
||||
import {options} from '../options.js';
|
||||
import {CompilerInfo} from '../compiler.interfaces.js';
|
||||
import {assert} from '../assert.js';
|
||||
import {localStorage} from '../local.js';
|
||||
import {
|
||||
ConfiguredRuntimeTool,
|
||||
ConfiguredRuntimeTools,
|
||||
PossibleRuntimeTools,
|
||||
RuntimeToolOption,
|
||||
RuntimeToolOptions,
|
||||
RuntimeToolType,
|
||||
} from '../../types/execution/execution.interfaces.js';
|
||||
|
||||
const FAV_RUNTIMETOOLS_STORE_KEY = 'favruntimetools';
|
||||
|
||||
export type RuntimeToolsChangeCallback = () => void;
|
||||
|
||||
type FavRuntimeTool = {
|
||||
name: RuntimeToolType;
|
||||
options: string;
|
||||
meta: string;
|
||||
};
|
||||
|
||||
type FavRuntimeTools = FavRuntimeTool[];
|
||||
|
||||
export class RuntimeToolsWidget {
|
||||
private domRoot: JQuery;
|
||||
private popupDomRoot: JQuery<HTMLElement>;
|
||||
private envVarsInput: JQuery<HTMLElement>;
|
||||
private dropdownButton: JQuery;
|
||||
private onChangeCallback: RuntimeToolsChangeCallback;
|
||||
private configured: ConfiguredRuntimeTools = [];
|
||||
private compiler: CompilerInfo | undefined;
|
||||
private possibleTools: PossibleRuntimeTools;
|
||||
|
||||
constructor(domRoot: JQuery, dropdownButton: JQuery, onChangeCallback: RuntimeToolsChangeCallback) {
|
||||
this.domRoot = domRoot;
|
||||
this.popupDomRoot = $('#runtimetools-selection');
|
||||
this.dropdownButton = dropdownButton;
|
||||
this.envVarsInput = this.popupDomRoot.find('.envvars');
|
||||
this.onChangeCallback = onChangeCallback;
|
||||
this.possibleTools = [];
|
||||
}
|
||||
|
||||
private loadStateFromUI(): ConfiguredRuntimeTools {
|
||||
const tools: ConfiguredRuntimeTools = [];
|
||||
|
||||
const envOverrides = this.getEnvOverrides();
|
||||
if (envOverrides.length > 0) {
|
||||
tools.push({
|
||||
name: RuntimeToolType.env,
|
||||
options: envOverrides,
|
||||
});
|
||||
}
|
||||
|
||||
const selects = this.popupDomRoot.find('select');
|
||||
for (const select of selects) {
|
||||
const jqSelect = $(select);
|
||||
|
||||
const rawName = jqSelect.data('tool-name');
|
||||
const optionName = jqSelect.data('tool-option');
|
||||
|
||||
const val = jqSelect.val();
|
||||
if (val) {
|
||||
const name = rawName as RuntimeToolType;
|
||||
assert(name !== RuntimeToolType.env);
|
||||
let tool = tools.find(tool => tool.name === name);
|
||||
if (!tool) {
|
||||
tool = {
|
||||
name: name,
|
||||
options: [],
|
||||
};
|
||||
tools.push(tool);
|
||||
}
|
||||
|
||||
const option: RuntimeToolOption = {
|
||||
name: optionName,
|
||||
value: (val || '') as string,
|
||||
};
|
||||
tool.options.push(option);
|
||||
}
|
||||
}
|
||||
|
||||
return tools;
|
||||
}
|
||||
|
||||
private optionsToString(options: RuntimeToolOptions): string {
|
||||
return options.map(env => `${env.name}=${env.value}`).join('\n');
|
||||
}
|
||||
|
||||
private stringToOptions(options: string): RuntimeToolOptions {
|
||||
return options
|
||||
.split('\n')
|
||||
.map(env => {
|
||||
const arr = env.split('=');
|
||||
if (arr[0]) {
|
||||
return {
|
||||
name: arr[0],
|
||||
value: arr[1],
|
||||
};
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.filter(Boolean) as RuntimeToolOptions;
|
||||
}
|
||||
|
||||
private getEnvOverrides(): RuntimeToolOptions {
|
||||
return this.stringToOptions(this.envVarsInput.val() as string);
|
||||
}
|
||||
|
||||
private selectOverrideFromFave(event) {
|
||||
const elem = $(event.target).parent();
|
||||
const name = elem.data('ov-name');
|
||||
const optionsStr = elem.data('ov-options');
|
||||
const options = this.stringToOptions(optionsStr);
|
||||
|
||||
const tool = this.possibleTools.find(ov => ov.name === name);
|
||||
if (tool) {
|
||||
const configuredTools = this.loadStateFromUI();
|
||||
let configuredTool = configuredTools.find(t => t.name === name);
|
||||
if (!configuredTool) {
|
||||
configuredTool = {
|
||||
name: name,
|
||||
options: [],
|
||||
};
|
||||
configuredTools.push(configuredTool);
|
||||
}
|
||||
|
||||
configuredTool.options = options;
|
||||
|
||||
this.loadStateIntoUI(configuredTools);
|
||||
}
|
||||
}
|
||||
|
||||
private newFavoriteOverrideDiv(fave: FavRuntimeTool) {
|
||||
const div = $('#overrides-favorite-tpl').children().clone();
|
||||
const prefix = fave.name + ': ';
|
||||
div.find('.overrides-name').html(prefix + fave.options.replace(/\n/g, ', '));
|
||||
div.data('ov-name', fave.name);
|
||||
div.data('ov-options', fave.options);
|
||||
div.on('click', this.selectOverrideFromFave.bind(this));
|
||||
return div;
|
||||
}
|
||||
|
||||
private loadFavoritesIntoUI() {
|
||||
const favoritesDiv = this.popupDomRoot.find('.runtimetools-favorites');
|
||||
favoritesDiv.html('');
|
||||
|
||||
const faves = this.getFavorites();
|
||||
for (const fave of faves) {
|
||||
const div: any = this.newFavoriteOverrideDiv(fave);
|
||||
favoritesDiv.append(div);
|
||||
}
|
||||
}
|
||||
|
||||
private addToFavorites(override: ConfiguredRuntimeTool) {
|
||||
if (override.name === RuntimeToolType.env) return;
|
||||
|
||||
const faves = this.getFavorites();
|
||||
|
||||
const fave: FavRuntimeTool = {
|
||||
name: override.name,
|
||||
options: this.optionsToString(override.options),
|
||||
meta: this.compiler?.baseName || this.compiler?.groupName || this.compiler?.name || this.compiler?.id || '',
|
||||
};
|
||||
|
||||
faves.push(fave);
|
||||
|
||||
this.setFavorites(faves);
|
||||
}
|
||||
|
||||
private removeFromFavorites(override: ConfiguredRuntimeTool) {
|
||||
if (override.name === RuntimeToolType.env) return;
|
||||
|
||||
const overrideOptions = this.optionsToString(override.options);
|
||||
|
||||
const faves = this.getFavorites();
|
||||
const faveIdx = faves.findIndex(f => f.name === override.name && f.options === overrideOptions);
|
||||
if (faveIdx !== -1) {
|
||||
faves.splice(faveIdx, 1);
|
||||
this.setFavorites(faves);
|
||||
}
|
||||
}
|
||||
|
||||
private isAFavorite(override: ConfiguredRuntimeTool) {
|
||||
if (override.name === RuntimeToolType.env) return false;
|
||||
|
||||
const overrideOptions = this.optionsToString(override.options);
|
||||
|
||||
const faves = this.getFavorites();
|
||||
const fave = faves.find(f => f.name === override.name && f.options === overrideOptions);
|
||||
return !!fave;
|
||||
}
|
||||
|
||||
private cap(text: string) {
|
||||
if (text.length > 0) {
|
||||
return text[0].toUpperCase() + text.substring(1);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private loadStateIntoUI(configured: ConfiguredRuntimeTools) {
|
||||
this.envVarsInput.val('');
|
||||
|
||||
for (const config of configured) {
|
||||
if (config.name === RuntimeToolType.env) {
|
||||
this.envVarsInput.val(this.optionsToString(config.options));
|
||||
}
|
||||
}
|
||||
|
||||
const container = this.popupDomRoot.find('.possible-runtimetools');
|
||||
container.html('');
|
||||
|
||||
this.possibleTools = this.compiler?.possibleRuntimeTools || [];
|
||||
|
||||
for (const possibleTool of this.possibleTools) {
|
||||
const card = $('#possible-runtime-tool').children().clone();
|
||||
card.find('.tool-name').html(this.cap(possibleTool.name));
|
||||
card.find('.tool-description').html(possibleTool.description);
|
||||
|
||||
const toolOptionsDiv = card.find('.tool-options');
|
||||
|
||||
const faveButton = card.find('.tool-fav-button');
|
||||
faveButton.hide();
|
||||
const faveStar = faveButton.find('.tool-fav-btn-icon');
|
||||
|
||||
const config = configured.find(c => c.name === possibleTool.name);
|
||||
|
||||
for (const toolOption of possibleTool.possibleOptions) {
|
||||
const optionDiv = $('#possible-runtime-tool-option').children().clone();
|
||||
optionDiv.attr('name', toolOption.name);
|
||||
const display_text = this.cap(toolOption.name);
|
||||
optionDiv.find('.tool-option-name').html(display_text);
|
||||
|
||||
const select = optionDiv.find('select');
|
||||
select.data('tool-name', possibleTool.name);
|
||||
select.data('tool-option', toolOption.name);
|
||||
|
||||
const option = $('<option />');
|
||||
option.html('');
|
||||
option.val('');
|
||||
select.append(option);
|
||||
|
||||
for (const toolOptionValue of toolOption.possibleValues) {
|
||||
const option = $('<option />');
|
||||
option.html(toolOptionValue);
|
||||
option.val(toolOptionValue);
|
||||
|
||||
if (config) {
|
||||
const found = config.options.find(
|
||||
configuredOption =>
|
||||
configuredOption.name === toolOption.name && configuredOption.value === toolOptionValue,
|
||||
);
|
||||
if (found) option.attr('selected', 'selected');
|
||||
}
|
||||
|
||||
select.append(option);
|
||||
}
|
||||
|
||||
select.off('change').on('change', () => {
|
||||
const name = possibleTool.name;
|
||||
assert(name !== RuntimeToolType.env);
|
||||
const configured = this.loadStateFromUI();
|
||||
const configuredTool = configured.find(tool => tool.name === name);
|
||||
|
||||
if (configuredTool) {
|
||||
if (this.isAFavorite(configuredTool)) {
|
||||
faveStar.removeClass('far').addClass('fas');
|
||||
} else {
|
||||
faveStar.removeClass('fas').addClass('far');
|
||||
}
|
||||
|
||||
if (configuredTool.options.length !== 0) {
|
||||
faveButton.show();
|
||||
} else {
|
||||
faveButton.hide();
|
||||
}
|
||||
} else {
|
||||
faveStar.removeClass('fas').addClass('far');
|
||||
}
|
||||
});
|
||||
|
||||
toolOptionsDiv.append(optionDiv);
|
||||
}
|
||||
|
||||
if (config && this.isAFavorite(config)) {
|
||||
faveStar.removeClass('far').addClass('fas');
|
||||
}
|
||||
faveButton.show();
|
||||
|
||||
faveButton.on('click', () => {
|
||||
const name = possibleTool.name;
|
||||
assert(name !== RuntimeToolType.env);
|
||||
|
||||
const configured = this.loadStateFromUI();
|
||||
const configuredTool = configured.find(tool => tool.name === name);
|
||||
if (configuredTool) {
|
||||
if (this.isAFavorite(configuredTool)) {
|
||||
this.removeFromFavorites(configuredTool);
|
||||
faveStar.removeClass('fas').addClass('far');
|
||||
} else {
|
||||
this.addToFavorites(configuredTool);
|
||||
faveStar.removeClass('far').addClass('fas');
|
||||
}
|
||||
}
|
||||
|
||||
this.loadFavoritesIntoUI();
|
||||
});
|
||||
|
||||
container.append(card);
|
||||
}
|
||||
|
||||
this.loadFavoritesIntoUI();
|
||||
}
|
||||
|
||||
set(configured: ConfiguredRuntimeTools) {
|
||||
this.configured = configured;
|
||||
this.updateButton();
|
||||
}
|
||||
|
||||
setDefaults() {
|
||||
this.configured = [];
|
||||
|
||||
this.updateButton();
|
||||
}
|
||||
|
||||
setCompiler(compilerId: string, languageId?: string) {
|
||||
this.compiler = options.compilers.find(c => c.id === compilerId);
|
||||
}
|
||||
|
||||
get(): ConfiguredRuntimeTools | undefined {
|
||||
if (this.compiler) {
|
||||
return this.configured;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private getFavorites(): FavRuntimeTools {
|
||||
return JSON.parse(localStorage.get(FAV_RUNTIMETOOLS_STORE_KEY, '[]'));
|
||||
}
|
||||
|
||||
private setFavorites(faves: FavRuntimeTools) {
|
||||
localStorage.set(FAV_RUNTIMETOOLS_STORE_KEY, JSON.stringify(faves));
|
||||
}
|
||||
|
||||
private updateButton() {
|
||||
const selected = this.get();
|
||||
if (selected && selected.length > 0) {
|
||||
this.dropdownButton
|
||||
.addClass('btn-success')
|
||||
.removeClass('btn-light')
|
||||
.prop(
|
||||
'title',
|
||||
'Current tools:\n' +
|
||||
selected
|
||||
.map(ov => {
|
||||
return '- ' + ov.name;
|
||||
})
|
||||
.join('\n'),
|
||||
);
|
||||
} else {
|
||||
this.dropdownButton.removeClass('btn-success').addClass('btn-light').prop('title', 'Overrides');
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.loadStateIntoUI(this.configured);
|
||||
|
||||
const lastOverrides = JSON.stringify(this.configured);
|
||||
|
||||
const popup = this.popupDomRoot.modal();
|
||||
// popup is shared, so clear the events first
|
||||
popup.off('hidden.bs.modal').on('hidden.bs.modal', () => {
|
||||
this.configured = this.loadStateFromUI();
|
||||
|
||||
const newOverrides = JSON.stringify(this.configured);
|
||||
|
||||
if (lastOverrides !== newOverrides) {
|
||||
this.updateButton();
|
||||
this.onChangeCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -197,7 +197,7 @@ ${' '.repeat(65530)}x
|
||||
ret
|
||||
`;
|
||||
const output = parser.process(asm, filters);
|
||||
parseInt(unwrap(output.parsingTime)).should.be.lessThan(200); // reported as ms, generous timeout for ci runner
|
||||
parseInt(unwrap(output.parsingTime)).should.be.lessThan(500); // reported as ms, generous timeout for ci runner
|
||||
});
|
||||
});
|
||||
|
||||
@@ -226,6 +226,6 @@ ${' '.repeat(65530)}x
|
||||
ret
|
||||
`;
|
||||
const output = parser.process(asm, filters);
|
||||
parseInt(unwrap(output.parsingTime)).should.be.lessThan(200); // reported as ms, generous timeout for ci runner
|
||||
parseInt(unwrap(output.parsingTime)).should.be.lessThan(500); // reported as ms, generous timeout for ci runner
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import './utils.js';
|
||||
import {DescribeInstancesCommand, EC2} from '@aws-sdk/client-ec2';
|
||||
import {DescribeInstancesCommand, EC2, Instance} from '@aws-sdk/client-ec2';
|
||||
import {GetParametersCommand, SSM} from '@aws-sdk/client-ssm';
|
||||
import {mockClient} from 'aws-sdk-client-mock';
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('AWS instance fetcher tests', () => {
|
||||
mockEC2.on(DescribeInstancesCommand).resolves({
|
||||
Reservations: [
|
||||
{
|
||||
Instances: [instanceA, instanceB, instanceC, instanceD],
|
||||
Instances: [instanceA, instanceB, instanceC, instanceD] as Instance[],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
365
test/cfg-cases/cfg-llvmir.invoke.json
generated
Normal file
365
test/cfg-cases/cfg-llvmir.invoke.json
generated
Normal file
@@ -0,0 +1,365 @@
|
||||
{
|
||||
"asm": [
|
||||
{
|
||||
"text": "define dso_local noundef i32 @f(int)(i32 noundef %n) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {",
|
||||
"scope": "!10",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "entry:"
|
||||
},
|
||||
{
|
||||
"text": " %retval = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " %n.addr = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " %a = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " %exn.slot = alloca i8*, align 8"
|
||||
},
|
||||
{
|
||||
"text": " %ehselector.slot = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " store i32 %n, i32* %n.addr, align 4"
|
||||
},
|
||||
{
|
||||
"text": " %0 = load i32, i32* %n.addr, align 4",
|
||||
"scope": "!21",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 6,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %call = invoke noundef i32 @g(int)(i32 noundef %0)"
|
||||
},
|
||||
{
|
||||
"text": " to label %invoke.cont unwind label %lpad",
|
||||
"scope": "!22",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 6,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "invoke.cont:"
|
||||
},
|
||||
{
|
||||
"text": " store i32 %call, i32* %a, align 4",
|
||||
"scope": "!20",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 6,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %1 = load i32, i32* %a, align 4",
|
||||
"scope": "!23",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 7,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i32 %1, i32* %retval, align 4",
|
||||
"scope": "!24",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 7,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %return",
|
||||
"scope": "!24",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 7,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "lpad:"
|
||||
},
|
||||
{
|
||||
"text": " %2 = landingpad { i8*, i32 }"
|
||||
},
|
||||
{
|
||||
"text": " catch i8* null",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %3 = extractvalue { i8*, i32 } %2, 0",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i8* %3, i8** %exn.slot, align 8",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %4 = extractvalue { i8*, i32 } %2, 1",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i32 %4, i32* %ehselector.slot, align 4",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %catch",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "catch:"
|
||||
},
|
||||
{
|
||||
"text": " %exn = load i8*, i8** %exn.slot, align 8",
|
||||
"scope": "!26",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 8,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %5 = call i8* @__cxa_begin_catch(i8* %exn) #4",
|
||||
"scope": "!26",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 8,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %6 = load i32, i32* %n.addr, align 4",
|
||||
"scope": "!27",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 11,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i32 %6, i32* %retval, align 4",
|
||||
"scope": "!29",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 11,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " call void @__cxa_end_catch()",
|
||||
"scope": "!30",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 12,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %return"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "try.cont:"
|
||||
},
|
||||
{
|
||||
"text": " call void @llvm.trap()",
|
||||
"scope": "!30",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 12,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " unreachable",
|
||||
"scope": "!30",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 12,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "return:"
|
||||
},
|
||||
{
|
||||
"text": " %7 = load i32, i32* %retval, align 4",
|
||||
"scope": "!31",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " ret i32 %7",
|
||||
"scope": "!31",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 13,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "}"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare void @llvm.dbg.declare(metadata, metadata, metadata) #1"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare noundef i32 @g(int)(i32 noundef) #2"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare i32 @__gxx_personality_v0(...)"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare i8* @__cxa_begin_catch(i8*)"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare void @__cxa_end_catch()"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare void @llvm.trap() #3"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
}
|
||||
],
|
||||
"cfg": {
|
||||
"f(int)(i32 noundef %n) personality i8* bitcast (i32 ": {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "f(int)(i32 noundef %n) personality i8* bitcast (i32 ",
|
||||
"label": "f(int)(i32 noundef %n) personality i8* bitcast (i32 :\n %retval = alloca i32, align 4\n %n.addr = alloca i32, align 4\n %a = alloca i32, align 4\n %exn.slot = alloca i8*, align 8\n %ehselector.slot = alloca i32, align 4\n store i32 %n, i32* %n.addr, align 4\n %0 = load i32, i32* %n.addr, align 4\n %call = invoke noundef i32 @g(int)(i32 noundef %0)\n to label %invoke.cont unwind label %lpad"
|
||||
},
|
||||
{
|
||||
"id": "invoke.cont",
|
||||
"label": "invoke.cont:\n store i32 %call, i32* %a, align 4\n %1 = load i32, i32* %a, align 4\n store i32 %1, i32* %retval, align 4\n br label %return"
|
||||
},
|
||||
{
|
||||
"id": "lpad",
|
||||
"label": "lpad:\n %2 = landingpad { i8*, i32 }\n catch i8* null\n %3 = extractvalue { i8*, i32 } %2, 0\n store i8* %3, i8** %exn.slot, align 8\n %4 = extractvalue { i8*, i32 } %2, 1\n store i32 %4, i32* %ehselector.slot, align 4\n br label %catch"
|
||||
},
|
||||
{
|
||||
"id": "catch",
|
||||
"label": "catch:\n %exn = load i8*, i8** %exn.slot, align 8\n %5 = call i8* @__cxa_begin_catch(i8* %exn) #4\n %6 = load i32, i32* %n.addr, align 4\n store i32 %6, i32* %retval, align 4\n call void @__cxa_end_catch()\n br label %return"
|
||||
},
|
||||
{
|
||||
"id": "try.cont",
|
||||
"label": "try.cont:\n call void @llvm.trap()\n unreachable"
|
||||
},
|
||||
{
|
||||
"id": "return",
|
||||
"label": "return:\n %7 = load i32, i32* %retval, align 4\n ret i32 %7"
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"from": "f(int)(i32 noundef %n) personality i8* bitcast (i32 ",
|
||||
"to": "invoke.cont",
|
||||
"arrows": "to",
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"from": "f(int)(i32 noundef %n) personality i8* bitcast (i32 ",
|
||||
"to": "lpad",
|
||||
"arrows": "to",
|
||||
"color": "grey"
|
||||
},
|
||||
{
|
||||
"from": "invoke.cont",
|
||||
"to": "return",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
},
|
||||
{
|
||||
"from": "lpad",
|
||||
"to": "catch",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
},
|
||||
{
|
||||
"from": "catch",
|
||||
"to": "return",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
352
test/cfg-cases/cfg-llvmir.loop.json
generated
Normal file
352
test/cfg-cases/cfg-llvmir.loop.json
generated
Normal file
@@ -0,0 +1,352 @@
|
||||
{
|
||||
"asm": [
|
||||
{
|
||||
"text": "define dso_local noundef i32 @foo(int*, int*, int)(i32* noundef %a, i32* noundef %b, i32 noundef %size) {",
|
||||
"scope": "!10",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "entry:"
|
||||
},
|
||||
{
|
||||
"text": " %a.addr = alloca i32*, align 8"
|
||||
},
|
||||
{
|
||||
"text": " %b.addr = alloca i32*, align 8"
|
||||
},
|
||||
{
|
||||
"text": " %size.addr = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " %i = alloca i32, align 4"
|
||||
},
|
||||
{
|
||||
"text": " store i32* %a, i32** %a.addr, align 8"
|
||||
},
|
||||
{
|
||||
"text": " store i32* %b, i32** %b.addr, align 8"
|
||||
},
|
||||
{
|
||||
"text": " store i32 %size, i32* %size.addr, align 4"
|
||||
},
|
||||
{
|
||||
"text": " store i32 0, i32* %i, align 4",
|
||||
"scope": "!25",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %for.cond",
|
||||
"scope": "!26",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "for.cond:"
|
||||
},
|
||||
{
|
||||
"text": " %0 = load i32, i32* %i, align 4",
|
||||
"scope": "!27",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %1 = load i32, i32* %size.addr, align 4",
|
||||
"scope": "!29",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %cmp = icmp slt i32 %0, %1",
|
||||
"scope": "!30",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br i1 %cmp, label %for.body, label %for.end",
|
||||
"scope": "!31",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "for.body:"
|
||||
},
|
||||
{
|
||||
"text": " %2 = load i32*, i32** %b.addr, align 8",
|
||||
"scope": "!32",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %3 = load i32, i32* %i, align 4",
|
||||
"scope": "!33",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %idxprom = sext i32 %3 to i64",
|
||||
"scope": "!32",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %arrayidx = getelementptr inbounds i32, i32* %2, i64 %idxprom",
|
||||
"scope": "!32",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %4 = load i32, i32* %arrayidx, align 4",
|
||||
"scope": "!32",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %add = add nsw i32 %4, 12",
|
||||
"scope": "!34",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %5 = load i32*, i32** %a.addr, align 8",
|
||||
"scope": "!35",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %6 = load i32, i32* %i, align 4",
|
||||
"scope": "!36",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %idxprom1 = sext i32 %6 to i64",
|
||||
"scope": "!35",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %arrayidx2 = getelementptr inbounds i32, i32* %5, i64 %idxprom1",
|
||||
"scope": "!35",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i32 %add, i32* %arrayidx2, align 4",
|
||||
"scope": "!37",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %for.inc",
|
||||
"scope": "!35",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "for.inc:"
|
||||
},
|
||||
{
|
||||
"text": " %7 = load i32, i32* %i, align 4",
|
||||
"scope": "!38",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " %inc = add nsw i32 %7, 1",
|
||||
"scope": "!38",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " store i32 %inc, i32* %i, align 4",
|
||||
"scope": "!38",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " br label %for.cond",
|
||||
"scope": "!39",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 3,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "for.end:"
|
||||
},
|
||||
{
|
||||
"text": " call void @llvm.trap()",
|
||||
"scope": "!41",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": " unreachable",
|
||||
"scope": "!41",
|
||||
"source": {
|
||||
"file": null,
|
||||
"line": 4,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "}"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare void @llvm.dbg.declare(metadata, metadata, metadata) #1"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"text": "declare void @llvm.trap() #2"
|
||||
},
|
||||
{
|
||||
"text": ""
|
||||
}
|
||||
],
|
||||
"cfg": {
|
||||
"foo(int*, int*, int)": {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "foo(int*, int*, int)",
|
||||
"label": "foo(int*, int*, int):\n %a.addr = alloca i32*, align 8\n %b.addr = alloca i32*, align 8\n %size.addr = alloca i32, align 4\n %i = alloca i32, align 4\n store i32* %a, i32** %a.addr, align 8\n store i32* %b, i32** %b.addr, align 8\n store i32 %size, i32* %size.addr, align 4\n store i32 0, i32* %i, align 4\n br label %for.cond"
|
||||
},
|
||||
{
|
||||
"id": "for.cond",
|
||||
"label": "for.cond:\n %0 = load i32, i32* %i, align 4\n %1 = load i32, i32* %size.addr, align 4\n %cmp = icmp slt i32 %0, %1\n br i1 %cmp, label %for.body, label %for.end"
|
||||
},
|
||||
{
|
||||
"id": "for.body",
|
||||
"label": "for.body:\n %2 = load i32*, i32** %b.addr, align 8\n %3 = load i32, i32* %i, align 4\n %idxprom = sext i32 %3 to i64\n %arrayidx = getelementptr inbounds i32, i32* %2, i64 %idxprom\n %4 = load i32, i32* %arrayidx, align 4\n %add = add nsw i32 %4, 12\n %5 = load i32*, i32** %a.addr, align 8\n %6 = load i32, i32* %i, align 4\n %idxprom1 = sext i32 %6 to i64\n %arrayidx2 = getelementptr inbounds i32, i32* %5, i64 %idxprom1\n store i32 %add, i32* %arrayidx2, align 4\n br label %for.inc"
|
||||
},
|
||||
{
|
||||
"id": "for.inc",
|
||||
"label": "for.inc:\n %7 = load i32, i32* %i, align 4\n %inc = add nsw i32 %7, 1\n store i32 %inc, i32* %i, align 4\n br label %for.cond"
|
||||
},
|
||||
{
|
||||
"id": "for.end",
|
||||
"label": "for.end:\n call void @llvm.trap()\n unreachable"
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"from": "foo(int*, int*, int)",
|
||||
"to": "for.cond",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
},
|
||||
{
|
||||
"from": "for.cond",
|
||||
"to": "for.body",
|
||||
"arrows": "to",
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"from": "for.cond",
|
||||
"to": "for.end",
|
||||
"arrows": "to",
|
||||
"color": "red"
|
||||
},
|
||||
{
|
||||
"from": "for.body",
|
||||
"to": "for.inc",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
},
|
||||
{
|
||||
"from": "for.inc",
|
||||
"to": "for.cond",
|
||||
"arrows": "to",
|
||||
"color": "blue"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import * as cfg from '../lib/cfg/cfg.js';
|
||||
|
||||
import {fs, makeFakeCompilerInfo, path, resolvePathFromTestRoot} from './utils.js';
|
||||
|
||||
async function DoCfgTest(cfgArg, filename) {
|
||||
async function DoCfgTest(cfgArg, filename, isLlvmIr = false) {
|
||||
const contents = await fs.readJson(filename, 'utf8');
|
||||
const structure = cfg.generateStructure(
|
||||
makeFakeCompilerInfo({
|
||||
@@ -34,7 +34,7 @@ async function DoCfgTest(cfgArg, filename) {
|
||||
version: cfgArg,
|
||||
}),
|
||||
contents.asm,
|
||||
false,
|
||||
isLlvmIr,
|
||||
);
|
||||
structure.should.deep.equal(contents.cfg);
|
||||
}
|
||||
@@ -69,4 +69,12 @@ describe('Cfg test cases', () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('llvmir', () => {
|
||||
for (const filename of files.filter(x => x.includes('llvmir'))) {
|
||||
it(filename, async () => {
|
||||
await DoCfgTest('clang', path.join(testcasespath, filename), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
GCCParser,
|
||||
ICCParser,
|
||||
PascalParser,
|
||||
TableGenParser,
|
||||
VCParser,
|
||||
} from '../../lib/compilers/argument-parsers.js';
|
||||
import {FakeCompiler} from '../../lib/compilers/fake-for-test.js';
|
||||
@@ -272,3 +273,28 @@ describe('ICC argument parser', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TableGen argument parser', () => {
|
||||
it('Should extract actions', () => {
|
||||
const lines = [
|
||||
'USAGE: llvm-tblgen [options] <input file>',
|
||||
'',
|
||||
'OPTIONS:',
|
||||
'',
|
||||
'General options:',
|
||||
'',
|
||||
' -D <macro name> - Name of the macro...',
|
||||
' Action to perform:',
|
||||
' --gen-attrs - Generate attributes',
|
||||
' --print-detailed-records - Print full details...',
|
||||
' --gen-x86-mnemonic-tables - Generate X86...',
|
||||
' --no-warn-on-unused-template-args - Disable...',
|
||||
];
|
||||
const actions = TableGenParser.extractPossibleActions(lines);
|
||||
actions.should.deep.equal([
|
||||
{name: 'gen-attrs: Generate attributes', value: '--gen-attrs'},
|
||||
{name: 'print-detailed-records: Print full details...', value: '--print-detailed-records'},
|
||||
{name: 'gen-x86-mnemonic-tables: Generate X86...', value: '--gen-x86-mnemonic-tables'},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -363,8 +363,9 @@ describe('Compiler tests', () => {
|
||||
res.body.input.options.should.deep.equals({
|
||||
backendOptions: {},
|
||||
bypassCache: BypassCache.None,
|
||||
executionParameters: {
|
||||
executeParameters: {
|
||||
args: [],
|
||||
runtimeTools: [],
|
||||
stdin: '',
|
||||
},
|
||||
filters: {
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
import * as stream from 'stream';
|
||||
|
||||
import {YAMLParseError} from 'yaml';
|
||||
|
||||
import {LLVMOptTransformer} from '../lib/llvm-opt-transformer.js';
|
||||
|
||||
describe('LLVM opt transformer', () => {
|
||||
@@ -94,4 +96,22 @@ Args:
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should error with unparseable yaml data', async () => {
|
||||
const doc = `--- !Analysis
|
||||
broken: not a yaml doc
|
||||
broken: duplicate key makes this invalid
|
||||
...
|
||||
`;
|
||||
const readString = new stream.PassThrough();
|
||||
readString.push(doc);
|
||||
readString.end();
|
||||
return (async () => {
|
||||
const optStream = stream.pipeline(readString, new LLVMOptTransformer(), res => {
|
||||
return res;
|
||||
});
|
||||
for await (const _ of optStream) {
|
||||
// just consume
|
||||
}
|
||||
})().should.be.rejectedWith(YAMLParseError);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
"options": "-O3",
|
||||
"filters": {
|
||||
"binary": false,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
@@ -30,12 +32,14 @@
|
||||
"options": "-O2",
|
||||
"filters": {
|
||||
"binary": false,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"debugCalls": false,
|
||||
"libraryCode": false,
|
||||
"trim": false
|
||||
},
|
||||
"id": "g92",
|
||||
@@ -43,12 +44,14 @@
|
||||
"tools": [],
|
||||
"filters": {
|
||||
"binary": false,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": true,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
@@ -39,12 +40,14 @@
|
||||
"options": "",
|
||||
"filters": {
|
||||
"binary": false,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"execute": true,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": true,
|
||||
"debugCalls": false,
|
||||
"trim": true
|
||||
},
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"execute": true,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": true,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -111,12 +111,14 @@
|
||||
"options": "-g -O3 -flto",
|
||||
"filters": {
|
||||
"binary": false,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -166,12 +166,14 @@
|
||||
"compiler": "g103",
|
||||
"filters": {
|
||||
"binary": true,
|
||||
"binaryObject": false,
|
||||
"commentOnly": true,
|
||||
"demangle": true,
|
||||
"directives": true,
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": false,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
"execute": false,
|
||||
"intel": true,
|
||||
"labels": true,
|
||||
"libraryCode": true,
|
||||
"debugCalls": false,
|
||||
"trim": false
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ import type {PPOptions} from '../../static/panes/pp-view.interfaces.js';
|
||||
import {suCodeEntry} from '../../static/panes/stack-usage-view.interfaces.js';
|
||||
import {ParsedAsmResultLine} from '../asmresult/asmresult.interfaces.js';
|
||||
import {CompilerInfo} from '../compiler.interfaces.js';
|
||||
import {BasicExecutionResult} from '../execution/execution.interfaces.js';
|
||||
import {BasicExecutionResult, ConfiguredRuntimeTools} from '../execution/execution.interfaces.js';
|
||||
import {ParseFiltersAndOutputOptions} from '../features/filters.interfaces.js';
|
||||
import {ResultLine} from '../resultline/resultline.interfaces.js';
|
||||
import {Artifact, ToolResult} from '../tool.interfaces.js';
|
||||
@@ -46,8 +46,9 @@ export type ActiveTools = {
|
||||
};
|
||||
|
||||
export type ExecutionParams = {
|
||||
args: string[] | string;
|
||||
stdin: string;
|
||||
args?: string[] | string;
|
||||
stdin?: string;
|
||||
runtimeTools?: ConfiguredRuntimeTools;
|
||||
};
|
||||
|
||||
export type CompileChildLibraries = {
|
||||
|
||||
@@ -30,6 +30,7 @@ export enum CompilerOverrideType {
|
||||
env = 'env',
|
||||
edition = 'edition',
|
||||
stdver = 'stdver',
|
||||
action = 'action',
|
||||
}
|
||||
|
||||
export type CompilerOverrideTypes = Set<CompilerOverrideType>;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import {BypassCache} from './compilation/compilation.interfaces.js';
|
||||
import {AllCompilerOverrideOptions} from './compilation/compiler-overrides.interfaces.js';
|
||||
import {ICompilerArguments} from './compiler-arguments.interfaces.js';
|
||||
import {PossibleRuntimeTools} from './execution/execution.interfaces.js';
|
||||
import {InstructionSet} from './instructionsets.js';
|
||||
import {Language, LanguageKey} from './languages.interfaces.js';
|
||||
import {Library} from './libraries/libraries.interfaces.js';
|
||||
@@ -124,6 +125,7 @@ export type CompilerInfo = {
|
||||
path: string;
|
||||
};
|
||||
possibleOverrides?: AllCompilerOverrideOptions;
|
||||
possibleRuntimeTools?: PossibleRuntimeTools;
|
||||
disabledFilters: string[];
|
||||
optArg?: string;
|
||||
stackUsageArg?: string;
|
||||
@@ -148,7 +150,7 @@ export type PreliminaryCompilerInfo = Omit<CompilerInfo, 'version' | 'fullVersio
|
||||
export interface ICompiler {
|
||||
possibleArguments: ICompilerArguments;
|
||||
lang: Language;
|
||||
compile(source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries, files);
|
||||
compile(source, options, backendOptions, filters, bypassCache, tools, executeParameters, libraries, files);
|
||||
cmake(files, key, bypassCache: BypassCache);
|
||||
initialise(mtime: Date, clientOptions, isPrediscovered: boolean);
|
||||
getInfo(): CompilerInfo;
|
||||
|
||||
@@ -31,9 +31,41 @@ export type BasicExecutionResult = {
|
||||
timedOut: boolean;
|
||||
};
|
||||
|
||||
export enum RuntimeToolType {
|
||||
env = 'env',
|
||||
heaptrack = 'heaptrack',
|
||||
}
|
||||
|
||||
export type RuntimeToolOption = {
|
||||
name: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type PossibleRuntimeToolOption = {
|
||||
name: string;
|
||||
possibleValues: string[];
|
||||
};
|
||||
|
||||
export type PossibleRuntimeTool = {
|
||||
name: RuntimeToolType;
|
||||
description: string;
|
||||
possibleOptions: PossibleRuntimeToolOption[];
|
||||
};
|
||||
export type PossibleRuntimeTools = PossibleRuntimeTool[];
|
||||
|
||||
export type RuntimeToolOptions = RuntimeToolOption[];
|
||||
|
||||
export type ConfiguredRuntimeTool = {
|
||||
name: RuntimeToolType;
|
||||
options: RuntimeToolOptions;
|
||||
};
|
||||
|
||||
export type ConfiguredRuntimeTools = ConfiguredRuntimeTool[];
|
||||
|
||||
export type ExecutableExecutionOptions = {
|
||||
args: string[];
|
||||
stdin: string;
|
||||
ldPath: string[];
|
||||
env: any;
|
||||
env: Record<string, string>;
|
||||
runtimeTools?: ConfiguredRuntimeTools;
|
||||
};
|
||||
|
||||
@@ -78,6 +78,7 @@ export type LanguageKey =
|
||||
| 'scala'
|
||||
| 'solidity'
|
||||
| 'swift'
|
||||
| 'tablegen'
|
||||
| 'toit'
|
||||
| 'typescript'
|
||||
| 'v'
|
||||
|
||||
@@ -58,6 +58,7 @@ export enum ArtifactType {
|
||||
smsrom = 'smsrom',
|
||||
timetrace = 'timetracejson',
|
||||
c64prg = 'c64prg',
|
||||
heaptracktxt = 'heaptracktxt',
|
||||
}
|
||||
|
||||
export type Artifact = {
|
||||
|
||||
@@ -25,6 +25,8 @@ include library-selection
|
||||
|
||||
include overrides-selection
|
||||
|
||||
include runtimetools-selection
|
||||
|
||||
include timing
|
||||
|
||||
include jsbeebemu
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user