Merge branch 'master' into sync_from_rust_2023_10_25
This commit is contained in:
commit
4d66cd8aa8
35
.github/workflows/ci.yml
vendored
35
.github/workflows/ci.yml
vendored
@ -19,9 +19,8 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- { gcc: "libgccjit.so", extra: "", env_extra: "", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", extra: "", env_extra: "", artifacts_branch: "master-without-128bit-integers" }
|
||||
- { gcc: "libgccjit12.so", extra: "--no-default-features", env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests'", artifacts_branch: "gcc12" }
|
||||
- { gcc: "libgccjit.so", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", artifacts_branch: "master-without-128bit-integers" }
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
@ -33,27 +32,16 @@ jobs:
|
||||
"--extended-regex-tests",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
"--test-failing-rustc",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
# `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
|
||||
run: sudo apt-get install ninja-build ripgrep llvm-14-tools
|
||||
|
||||
- name: Install libgccjit12
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: sudo apt-get install libgccjit-12-dev
|
||||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: main.yml
|
||||
@ -65,11 +53,6 @@ jobs:
|
||||
search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
@ -80,9 +63,6 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@ -119,8 +99,8 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh build ${{ matrix.libgccjit_version.extra }}
|
||||
${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
|
||||
./y.sh build
|
||||
cargo test
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
@ -136,16 +116,15 @@ jobs:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests for GCC 12
|
||||
if: ${{ matrix.libgccjit_version.gcc == 'libgccjit12.so' }}
|
||||
run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
|
||||
|
||||
duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
|
129
.github/workflows/failures.yml
vendored
Normal file
129
.github/workflows/failures.yml
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
# TODO: refactor to avoid duplication with the ci.yml file.
|
||||
name: Failures
|
||||
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- gcc: "libgccjit.so"
|
||||
artifacts_branch: "master"
|
||||
- gcc: "libgccjit_without_int128.so"
|
||||
artifacts_branch: "master-without-128bit-integers"
|
||||
- gcc: "libgccjit12.so"
|
||||
artifacts_branch: "gcc12"
|
||||
extra: "--no-default-features"
|
||||
# FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
|
||||
# Not sure why it's not found otherwise.
|
||||
env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
- name: Install libgccjit12
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: sudo apt-get install libgccjit-12-dev
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: main.yml
|
||||
name: gcc-13
|
||||
path: gcc-13
|
||||
repo: antoyo/gcc
|
||||
branch: ${{ matrix.libgccjit_version.artifacts_branch }}
|
||||
event: push
|
||||
search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Git config
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
|
||||
- name: Prepare dependencies
|
||||
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
|
||||
run: ./y.sh prepare --libgccjit12-patches
|
||||
|
||||
- name: Prepare dependencies
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: ./y.sh prepare
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
id: tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
|
||||
rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
|
115
.github/workflows/gcc12.yml
vendored
Normal file
115
.github/workflows/gcc12.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
name: CI libgccjit 12
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
TEST_FLAGS: "-Cpanic=abort -Zpanic-abort-tests"
|
||||
# FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
|
||||
# Not sure why it's not found otherwise.
|
||||
GCC_EXEC_PREFIX: /usr/lib/gcc/
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# FIXME: re-enable asm tests when GCC can emit in the right syntax.
|
||||
# "--asm-tests",
|
||||
"--test-libcore",
|
||||
"--extended-rand-tests",
|
||||
"--extended-regex-example-tests",
|
||||
"--extended-regex-tests",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
# `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
|
||||
run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
#if: ${{ contains(matrix.commands, 'rustc') }}
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --libgccjit12-patches
|
||||
./y.sh build --no-default-features --sysroot-panic-abort
|
||||
cargo test --no-default-features
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --libgccjit12-patches
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests for GCC 12
|
||||
run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
|
139
.github/workflows/m68k.yml
vendored
Normal file
139
.github/workflows/m68k.yml
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
# TODO: check if qemu-user-static-binfmt is needed (perhaps to run some tests since it probably calls exec).
|
||||
|
||||
name: m68k CI
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
# TODO: remove when confish.sh is removed.
|
||||
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# TODO(antoyo): fix those on m68k.
|
||||
#"--test-libcore",
|
||||
#"--extended-rand-tests",
|
||||
#"--extended-regex-example-tests",
|
||||
#"--extended-regex-tests",
|
||||
#"--test-successful-rustc --nb-parts 2 --current-part 0",
|
||||
#"--test-successful-rustc --nb-parts 2 --current-part 1",
|
||||
#"--test-failing-rustc",
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install qemu qemu-user-static
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download GCC artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: m68k.yml
|
||||
name: gcc-m68k-13
|
||||
repo: cross-cg-gcc-tools/cross-gcc
|
||||
branch: master
|
||||
event: push
|
||||
|
||||
- name: Download VM artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: m68k.yml
|
||||
name: debian-m68k
|
||||
repo: cross-cg-gcc-tools/vms
|
||||
branch: master
|
||||
event: push
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-13.deb
|
||||
echo /usr/lib/ > gcc_path
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: cargo-installed-crates2-ubuntu-latest
|
||||
|
||||
#- name: Cache cargo registry
|
||||
#uses: actions/cache@v3
|
||||
#with:
|
||||
#path: ~/.cargo/registry
|
||||
#key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
#- name: Cache cargo index
|
||||
#uses: actions/cache@v3
|
||||
#with:
|
||||
#path: ~/.cargo/git
|
||||
#key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
#if: ${{ contains(matrix.commands, 'rustc') }}
|
||||
#uses: actions/cache@v3
|
||||
#id: cache-rust-repository
|
||||
#with:
|
||||
#path: rust
|
||||
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
|
||||
|
||||
- name: Prepare VM
|
||||
run: |
|
||||
mkdir vm
|
||||
sudo mount debian-m68k.img vm
|
||||
sudo cp $(which qemu-m68k-static) vm/usr/bin/
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --target-triple m68k-unknown-linux-gnu
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
# Compile is a separate step, as the actions-rs/cargo action supports error annotations
|
||||
- name: Compile
|
||||
uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
command: build
|
||||
args: --release
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
|
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@ -26,11 +26,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
@ -56,9 +51,6 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
8
.github/workflows/stdarch.yml
vendored
8
.github/workflows/stdarch.yml
vendored
@ -26,11 +26,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: llvm/llvm-project
|
||||
path: llvm
|
||||
|
||||
- name: Install packages
|
||||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
@ -70,9 +65,6 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
- name: Set RUST_COMPILER_RT_ROOT
|
||||
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
|
||||
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
10
.ignore
Normal file
10
.ignore
Normal file
@ -0,0 +1,10 @@
|
||||
!/build_sysroot/sysroot_src
|
||||
!/simple-raytracer
|
||||
!/regex
|
||||
!/rand
|
||||
!/test-backend
|
||||
!/gcc_path
|
||||
!/benchmarks
|
||||
!*gimple*
|
||||
!*asm*
|
||||
!.github
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -74,7 +74,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
@ -82,7 +82,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
52
Readme.md
52
Readme.md
@ -55,13 +55,6 @@ $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
|
||||
$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
|
||||
```
|
||||
|
||||
You also need to set RUST_COMPILER_RT_ROOT:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch
|
||||
$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt"
|
||||
```
|
||||
|
||||
Then you can run commands like this:
|
||||
|
||||
```bash
|
||||
@ -91,9 +84,17 @@ $ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run
|
||||
|
||||
If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
|
||||
|
||||
### LTO
|
||||
|
||||
To use LTO, you need to set the variable `FAT_LTO=1` and `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`.
|
||||
Don't set `FAT_LTO` when compiling the sysroot, though: only set `EMBED_LTO_BITCODE=1`.
|
||||
|
||||
Failing to set `EMBED_LTO_BITCODE` will give you the following error:
|
||||
|
||||
```
|
||||
error: failed to copy bitcode to object file: No such file or directory (os error 2)
|
||||
```
|
||||
|
||||
### Rustc
|
||||
|
||||
> You should prefer using the Cargo method.
|
||||
@ -286,6 +287,16 @@ git checkout sync_branch_name
|
||||
git merge master
|
||||
```
|
||||
|
||||
To send the changes to the rust repo:
|
||||
|
||||
```bash
|
||||
cd ../rust
|
||||
git pull origin master
|
||||
git checkbout -b subtree-update_cg_gcc_YYYY-MM-DD
|
||||
PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master
|
||||
git push
|
||||
```
|
||||
|
||||
TODO: write a script that does the above.
|
||||
|
||||
https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
|
||||
@ -303,16 +314,25 @@ generate it in [gimple.md](./doc/gimple.md).
|
||||
|
||||
#### Building libgccjit
|
||||
|
||||
* Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes:
|
||||
* Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`.
|
||||
* Some shells, like fish, don't define the environment variable `$MACHTYPE`.
|
||||
* Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian).
|
||||
* Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc).
|
||||
|
||||
#### Configuring rustc_codegen_gcc
|
||||
|
||||
* Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh.
|
||||
* Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
* Set `linker='-Clinker=m68k-linux-gcc'`.
|
||||
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc_path`.
|
||||
* Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs.
|
||||
* (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?): Remove dylib from build_sysroot/sysroot_src/library/std/Cargo.toml.
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`.
|
||||
|
||||
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
Then, you can use it the following way:
|
||||
|
||||
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
|
||||
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
|
||||
If you get the following error:
|
||||
|
||||
```
|
||||
/usr/bin/ld: unrecognised emulation mode: m68kelf
|
||||
```
|
||||
|
||||
Make sure you set `gcc_path` to the install directory.
|
||||
|
@ -22,7 +22,7 @@ if [[ "$1" == "--release" ]]; then
|
||||
RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
|
||||
else
|
||||
sysroot_channel='debug'
|
||||
cargo build --target $TARGET_TRIPLE --features compiler_builtins/c
|
||||
cargo build --target $TARGET_TRIPLE
|
||||
fi
|
||||
|
||||
# Copy files to sysroot
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::config::set_config;
|
||||
use crate::config::{set_config, ConfigInfo};
|
||||
use crate::utils::{
|
||||
get_gcc_path, run_command, run_command_with_env, run_command_with_output_and_env, walk_dir,
|
||||
get_gcc_path, run_command, run_command_with_output_and_env, walk_dir,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
@ -11,7 +11,8 @@
|
||||
struct BuildArg {
|
||||
codegen_release_channel: bool,
|
||||
sysroot_release_channel: bool,
|
||||
features: Vec<String>,
|
||||
sysroot_panic_abort: bool,
|
||||
flags: Vec<String>,
|
||||
gcc_path: String,
|
||||
}
|
||||
|
||||
@ -30,12 +31,15 @@ fn new() -> Result<Option<Self>, String> {
|
||||
"--release" => build_arg.codegen_release_channel = true,
|
||||
"--release-sysroot" => build_arg.sysroot_release_channel = true,
|
||||
"--no-default-features" => {
|
||||
build_arg.features.push("--no-default-features".to_string());
|
||||
build_arg.flags.push("--no-default-features".to_string());
|
||||
}
|
||||
"--sysroot-panic-abort" => {
|
||||
build_arg.sysroot_panic_abort = true;
|
||||
},
|
||||
"--features" => {
|
||||
if let Some(arg) = args.next() {
|
||||
build_arg.features.push("--features".to_string());
|
||||
build_arg.features.push(arg.as_str().into());
|
||||
build_arg.flags.push("--features".to_string());
|
||||
build_arg.flags.push(arg.as_str().into());
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--features`, found nothing".to_string()
|
||||
@ -46,6 +50,24 @@ fn new() -> Result<Option<Self>, String> {
|
||||
Self::usage();
|
||||
return Ok(None);
|
||||
}
|
||||
"--target-triple" => {
|
||||
if args.next().is_some() {
|
||||
// Handled in config.rs.
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target-triple`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
"--target" => {
|
||||
if args.next().is_some() {
|
||||
// Handled in config.rs.
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
arg => return Err(format!("Unknown argument `{}`", arg)),
|
||||
}
|
||||
}
|
||||
@ -59,8 +81,10 @@ fn usage() {
|
||||
|
||||
--release : Build codegen in release mode
|
||||
--release-sysroot : Build sysroot in release mode
|
||||
--sysroot-panic-abort : Build the sysroot without unwinding support.
|
||||
--no-default-features : Add `--no-default-features` flag
|
||||
--features [arg] : Add a new feature [arg]
|
||||
--target-triple [arg] : Set the target triple to [arg]
|
||||
--help : Show this help
|
||||
"#
|
||||
)
|
||||
@ -69,8 +93,8 @@ fn usage() {
|
||||
|
||||
fn build_sysroot(
|
||||
env: &mut HashMap<String, String>,
|
||||
release_mode: bool,
|
||||
target_triple: &str,
|
||||
args: &BuildArg,
|
||||
config: &ConfigInfo,
|
||||
) -> Result<(), String> {
|
||||
std::env::set_current_dir("build_sysroot")
|
||||
.map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?;
|
||||
@ -119,21 +143,24 @@ fn build_sysroot(
|
||||
let _ = fs::remove_dir_all("sysroot");
|
||||
|
||||
// Builds libs
|
||||
let channel = if release_mode {
|
||||
let rustflags = env
|
||||
.get("RUSTFLAGS")
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
env.insert(
|
||||
"RUSTFLAGS".to_string(),
|
||||
format!("{} -Zmir-opt-level=3", rustflags),
|
||||
);
|
||||
let mut rustflags = env
|
||||
.get("RUSTFLAGS")
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
if args.sysroot_panic_abort {
|
||||
rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests");
|
||||
}
|
||||
env.insert(
|
||||
"RUSTFLAGS".to_string(),
|
||||
format!("{} -Zmir-opt-level=3", rustflags),
|
||||
);
|
||||
let channel = if args.sysroot_release_channel {
|
||||
run_command_with_output_and_env(
|
||||
&[
|
||||
&"cargo",
|
||||
&"build",
|
||||
&"--target",
|
||||
&target_triple,
|
||||
&config.target,
|
||||
&"--release",
|
||||
],
|
||||
None,
|
||||
@ -146,9 +173,7 @@ fn build_sysroot(
|
||||
&"cargo",
|
||||
&"build",
|
||||
&"--target",
|
||||
&target_triple,
|
||||
&"--features",
|
||||
&"compiler_builtins/c",
|
||||
&config.target,
|
||||
],
|
||||
None,
|
||||
Some(env),
|
||||
@ -157,14 +182,14 @@ fn build_sysroot(
|
||||
};
|
||||
|
||||
// Copy files to sysroot
|
||||
let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", target_triple);
|
||||
let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple);
|
||||
fs::create_dir_all(&sysroot_path)
|
||||
.map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?;
|
||||
let copier = |dir_to_copy: &Path| {
|
||||
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
||||
};
|
||||
walk_dir(
|
||||
&format!("target/{}/{}/deps", target_triple, channel),
|
||||
&format!("target/{}/{}/deps", config.target_triple, channel),
|
||||
copier,
|
||||
copier,
|
||||
)?;
|
||||
@ -175,16 +200,6 @@ fn build_sysroot(
|
||||
fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
||||
let mut env = HashMap::new();
|
||||
|
||||
let current_dir =
|
||||
std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
if let Ok(rt_root) = std::env::var("RUST_COMPILER_RT_ROOT") {
|
||||
env.insert("RUST_COMPILER_RT_ROOT".to_string(), rt_root);
|
||||
} else {
|
||||
env.insert(
|
||||
"RUST_COMPILER_RT_ROOT".to_string(),
|
||||
format!("{}", current_dir.join("llvm/compiler-rt").display()),
|
||||
);
|
||||
}
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
|
||||
env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
|
||||
|
||||
@ -196,11 +211,11 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
||||
} else {
|
||||
env.insert("CHANNEL".to_string(), "debug".to_string());
|
||||
}
|
||||
let ref_features = args.features.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
for feature in &ref_features {
|
||||
command.push(feature);
|
||||
let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
for flag in &flags {
|
||||
command.push(flag);
|
||||
}
|
||||
run_command_with_env(&command, None, Some(&env))?;
|
||||
run_command_with_output_and_env(&command, None, Some(&env))?;
|
||||
|
||||
let config = set_config(&mut env, &[], Some(&args.gcc_path))?;
|
||||
|
||||
@ -217,8 +232,8 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> {
|
||||
println!("[BUILD] sysroot");
|
||||
build_sysroot(
|
||||
&mut env,
|
||||
args.sysroot_release_channel,
|
||||
&config.target_triple,
|
||||
args,
|
||||
&config,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
use std::env as std_env;
|
||||
|
||||
pub struct ConfigInfo {
|
||||
pub target: String,
|
||||
pub target_triple: String,
|
||||
pub rustc_command: Vec<String>,
|
||||
pub run_wrapper: Option<&'static str>,
|
||||
}
|
||||
|
||||
// Returns the beginning for the command line of rustc.
|
||||
@ -30,22 +30,46 @@ pub fn set_config(
|
||||
};
|
||||
let host_triple = get_rustc_host_triple()?;
|
||||
let mut linker = None;
|
||||
let mut target_triple = host_triple.as_str();
|
||||
let mut run_wrapper = None;
|
||||
// FIXME: handle this with a command line flag?
|
||||
// let mut target_triple = "m68k-unknown-linux-gnu";
|
||||
let mut target_triple = host_triple.clone();
|
||||
let mut target = target_triple.clone();
|
||||
|
||||
// We skip binary name and the command.
|
||||
let mut args = std::env::args().skip(2);
|
||||
|
||||
let mut set_target_triple = false;
|
||||
let mut set_target = false;
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"--target-triple" => {
|
||||
if let Some(arg) = args.next() {
|
||||
target_triple = arg;
|
||||
set_target_triple = true;
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target-triple`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
},
|
||||
"--target" => {
|
||||
if let Some(arg) = args.next() {
|
||||
target = arg;
|
||||
set_target = true;
|
||||
} else {
|
||||
return Err(
|
||||
"Expected a value after `--target`, found nothing".to_string()
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
if set_target_triple && !set_target {
|
||||
target = target_triple.clone();
|
||||
}
|
||||
|
||||
if host_triple != target_triple {
|
||||
if target_triple == "m68k-unknown-linux-gnu" {
|
||||
target_triple = "mips-unknown-linux-gnu";
|
||||
linker = Some("-Clinker=m68k-linux-gcc");
|
||||
} else if target_triple == "aarch64-unknown-linux-gnu" {
|
||||
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
|
||||
linker = Some("-Clinker=aarch64-linux-gnu-gcc");
|
||||
run_wrapper = Some("qemu-aarch64 -L /usr/aarch64-linux-gnu");
|
||||
} else {
|
||||
return Err(format!("unknown non-native platform `{}`", target_triple));
|
||||
}
|
||||
linker = Some(format!("-Clinker={}-gcc", target_triple));
|
||||
}
|
||||
let current_dir =
|
||||
std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
@ -118,8 +142,8 @@ pub fn set_config(
|
||||
"target/out".to_string(),
|
||||
]);
|
||||
Ok(ConfigInfo {
|
||||
target_triple: target_triple.to_string(),
|
||||
target,
|
||||
target_triple,
|
||||
rustc_command,
|
||||
run_wrapper,
|
||||
})
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
mod config;
|
||||
mod prepare;
|
||||
mod rustc_info;
|
||||
mod test;
|
||||
mod utils;
|
||||
|
||||
macro_rules! arg_error {
|
||||
@ -23,6 +24,7 @@ fn usage() {
|
||||
|
||||
prepare : Run prepare command
|
||||
build : Run build command
|
||||
test : Run test command
|
||||
--help : Show this message"
|
||||
);
|
||||
}
|
||||
@ -30,6 +32,7 @@ fn usage() {
|
||||
pub enum Command {
|
||||
Prepare,
|
||||
Build,
|
||||
Test,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -40,6 +43,7 @@ fn main() {
|
||||
let command = match env::args().nth(1).as_deref() {
|
||||
Some("prepare") => Command::Prepare,
|
||||
Some("build") => Command::Build,
|
||||
Some("test") => Command::Test,
|
||||
Some("--help") => {
|
||||
usage();
|
||||
process::exit(0);
|
||||
@ -55,6 +59,7 @@ fn main() {
|
||||
if let Err(e) = match command {
|
||||
Command::Prepare => prepare::run(),
|
||||
Command::Build => build::run(),
|
||||
Command::Test => test::run(),
|
||||
} {
|
||||
eprintln!("Command failed to run: {e:?}");
|
||||
process::exit(1);
|
||||
|
@ -4,7 +4,7 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
|
||||
fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile: bool) -> Result<(), String> {
|
||||
let rustc_path = match get_rustc_path() {
|
||||
Some(path) => path,
|
||||
None => return Err("`rustc` path not found".to_string()),
|
||||
@ -87,6 +87,22 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
if cross_compile {
|
||||
walk_dir("cross_patches", |_| Ok(()), |file_path: &Path| {
|
||||
patches.push(file_path.to_path_buf());
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
if libgccjit12_patches {
|
||||
walk_dir(
|
||||
"patches/libgccjit12",
|
||||
|_| Ok(()),
|
||||
|file_path: &Path| {
|
||||
patches.push(file_path.to_path_buf());
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
patches.sort();
|
||||
for file_path in patches {
|
||||
println!("[GIT] apply `{}`", file_path.display());
|
||||
@ -156,16 +172,22 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
|
||||
}
|
||||
|
||||
struct PrepareArg {
|
||||
cross_compile: bool,
|
||||
only_libcore: bool,
|
||||
libgccjit12_patches: bool,
|
||||
}
|
||||
|
||||
impl PrepareArg {
|
||||
fn new() -> Result<Option<Self>, String> {
|
||||
let mut only_libcore = false;
|
||||
let mut cross_compile = false;
|
||||
let mut libgccjit12_patches = false;
|
||||
|
||||
for arg in std::env::args().skip(2) {
|
||||
match arg.as_str() {
|
||||
"--only-libcore" => only_libcore = true,
|
||||
"--cross" => cross_compile = true,
|
||||
"--libgccjit12-patches" => libgccjit12_patches = true,
|
||||
"--help" => {
|
||||
Self::usage();
|
||||
return Ok(None);
|
||||
@ -173,7 +195,11 @@ fn new() -> Result<Option<Self>, String> {
|
||||
a => return Err(format!("Unknown argument `{a}`")),
|
||||
}
|
||||
}
|
||||
Ok(Some(Self { only_libcore }))
|
||||
Ok(Some(Self {
|
||||
cross_compile,
|
||||
only_libcore,
|
||||
libgccjit12_patches,
|
||||
}))
|
||||
}
|
||||
|
||||
fn usage() {
|
||||
@ -181,8 +207,10 @@ fn usage() {
|
||||
r#"
|
||||
`prepare` command help:
|
||||
|
||||
--only-libcore : Only setup libcore and don't clone other repositories
|
||||
--help : Show this help
|
||||
--only-libcore : Only setup libcore and don't clone other repositories
|
||||
--cross : Apply the patches needed to do cross-compilation
|
||||
--libgccjit12-patches : Apply patches needed for libgccjit12
|
||||
--help : Show this help
|
||||
"#
|
||||
)
|
||||
}
|
||||
@ -194,7 +222,7 @@ pub fn run() -> Result<(), String> {
|
||||
None => return Ok(()),
|
||||
};
|
||||
let sysroot_path = Path::new("build_sysroot");
|
||||
prepare_libcore(sysroot_path)?;
|
||||
prepare_libcore(sysroot_path, args.libgccjit12_patches, args.cross_compile)?;
|
||||
|
||||
if !args.only_libcore {
|
||||
cargo_install("hyperfine")?;
|
||||
|
15
build_system/src/test.rs
Normal file
15
build_system/src/test.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::utils::run_command_with_output;
|
||||
|
||||
fn get_args<'a>(args: &mut Vec<&'a dyn AsRef<std::ffi::OsStr>>, extra_args: &'a Vec<String>) {
|
||||
for extra_arg in extra_args {
|
||||
args.push(extra_arg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(), String> {
|
||||
let mut args: Vec<&dyn AsRef<std::ffi::OsStr>> = vec![&"bash", &"test.sh"];
|
||||
let extra_args = std::env::args().skip(2).collect::<Vec<_>>();
|
||||
get_args(&mut args, &extra_args);
|
||||
let current_dir = std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
|
||||
run_command_with_output(args.as_slice(), Some(¤t_dir))
|
||||
}
|
25
config.sh
25
config.sh
@ -20,22 +20,21 @@ else
|
||||
fi
|
||||
|
||||
HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
TARGET_TRIPLE=$HOST_TRIPLE
|
||||
#TARGET_TRIPLE="m68k-unknown-linux-gnu"
|
||||
# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
|
||||
TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
|
||||
|
||||
linker=''
|
||||
RUN_WRAPPER=''
|
||||
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
|
||||
TARGET_TRIPLE="mips-unknown-linux-gnu"
|
||||
linker='-Clinker=m68k-linux-gcc'
|
||||
elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
|
||||
# We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
|
||||
linker='-Clinker=aarch64-linux-gnu-gcc'
|
||||
RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
|
||||
else
|
||||
echo "Unknown non-native platform"
|
||||
fi
|
||||
RUN_WRAPPER=run_in_vm
|
||||
if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
|
||||
linker='-Clinker=m68k-unknown-linux-gnu-gcc'
|
||||
elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
|
||||
# We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
|
||||
linker='-Clinker=aarch64-linux-gnu-gcc'
|
||||
else
|
||||
echo "Unknown non-native platform"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
|
||||
@ -60,4 +59,4 @@ export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||
# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
|
||||
# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
|
||||
# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
|
||||
export PATH="/opt/gcc/bin:$PATH"
|
||||
export PATH="/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin:$PATH"
|
||||
|
39
cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
Normal file
39
cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 28 Sep 2023 17:37:38 -0400
|
||||
Subject: [PATCH] Disable libstd and libtest dylib
|
||||
|
||||
---
|
||||
library/std/Cargo.toml | 2 +-
|
||||
library/test/Cargo.toml | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
|
||||
index 5b21355..cb0c49b 100644
|
||||
--- a/library/std/Cargo.toml
|
||||
+++ b/library/std/Cargo.toml
|
||||
@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
+crate-type = ["rlib"]
|
||||
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc", public = true }
|
||||
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
|
||||
index 91a1abd..a58c160 100644
|
||||
--- a/library/test/Cargo.toml
|
||||
+++ b/library/test/Cargo.toml
|
||||
@@ -4,7 +4,7 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
+crate-type = ["rlib"]
|
||||
|
||||
[dependencies]
|
||||
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
|
||||
--
|
||||
2.42.0
|
||||
|
5
doc/tests.md
Normal file
5
doc/tests.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Tests
|
||||
|
||||
## Show the rustc command for UI tests
|
||||
|
||||
Add ` --test-args "--verbose"` to `./x.py test`.
|
@ -9,6 +9,7 @@
|
||||
// add fast paths for low alignment values.
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "arm",
|
||||
target_arch = "m68k",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "powerpc",
|
||||
|
@ -152,7 +152,8 @@ fn main() {
|
||||
let slice = &[0, 1] as &[i32];
|
||||
let slice_ptr = slice as *const [i32] as *const i32;
|
||||
|
||||
assert_eq!(slice_ptr as usize % 4, 0);
|
||||
let align = intrinsics::min_align_of::<*const i32>();
|
||||
assert_eq!(slice_ptr as usize % align, 0);
|
||||
|
||||
//return;
|
||||
|
||||
@ -186,7 +187,10 @@ fn main() {
|
||||
let a: &dyn SomeTrait = &"abc\0";
|
||||
a.object_safe();
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
assert_eq!(intrinsics::size_of_val(a) as u8, 16);
|
||||
#[cfg(target_arch="m68k")]
|
||||
assert_eq!(intrinsics::size_of_val(a) as u8, 8);
|
||||
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
|
||||
|
||||
assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
use std::io::Write;
|
||||
use std::ops::Coroutine;
|
||||
@ -95,6 +96,7 @@ fn main() {
|
||||
|
||||
println!("{:?}", std::intrinsics::caller_location());
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[cfg(feature="master")]
|
||||
unsafe {
|
||||
test_simd();
|
||||
@ -108,6 +110,7 @@ fn main() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_simd() {
|
||||
let x = _mm_setzero_si128();
|
||||
@ -136,6 +139,7 @@ unsafe fn test_simd() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_slli_si128() {
|
||||
#[rustfmt::skip]
|
||||
@ -164,6 +168,7 @@ unsafe fn test_mm_slli_si128() {
|
||||
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_movemask_epi8() {
|
||||
#[rustfmt::skip]
|
||||
@ -178,6 +183,7 @@ unsafe fn test_mm_movemask_epi8() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn test_mm256_movemask_epi8() {
|
||||
let a = _mm256_set1_epi8(-1);
|
||||
@ -187,6 +193,7 @@ unsafe fn test_mm256_movemask_epi8() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_add_epi8() {
|
||||
let a = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
@ -203,6 +210,7 @@ unsafe fn test_mm_add_epi8() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_add_pd() {
|
||||
let a = _mm_setr_pd(1.0, 2.0);
|
||||
@ -212,6 +220,7 @@ unsafe fn test_mm_add_pd() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i) {
|
||||
unsafe {
|
||||
assert_eq!(std::mem::transmute::<_, [u8; 16]>(x), std::mem::transmute::<_, [u8; 16]>(y));
|
||||
@ -219,6 +228,7 @@ fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i)
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
|
||||
@ -227,6 +237,7 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_cvtsi128_si64() {
|
||||
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
|
||||
@ -234,6 +245,7 @@ unsafe fn test_mm_cvtsi128_si64() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn test_mm_cvtepi8_epi16() {
|
||||
let a = _mm_set1_epi8(10);
|
||||
@ -247,6 +259,7 @@ unsafe fn test_mm_cvtepi8_epi16() {
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn test_mm_extract_epi8() {
|
||||
#[rustfmt::skip]
|
||||
|
@ -71,3 +71,4 @@ tests/ui/lto/all-crates.rs
|
||||
tests/ui/async-await/deep-futures-are-freeze.rs
|
||||
tests/ui/closures/capture-unsized-by-ref.rs
|
||||
tests/ui/generator/resume-after-return.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
|
||||
|
@ -19,15 +19,12 @@ tests/ui/simd/intrinsic/generic-reduction-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-select-pass.rs
|
||||
tests/ui/simd/intrinsic/inlining-issue67557-ice.rs
|
||||
tests/ui/simd/intrinsic/inlining-issue67557.rs
|
||||
tests/ui/simd/monomorphize-shuffle-index.rs
|
||||
tests/ui/simd/shuffle.rs
|
||||
tests/ui/simd/simd-bitmask.rs
|
||||
tests/ui/generator/resume-after-return.rs
|
||||
tests/ui/iterators/iter-step-overflow-debug.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
|
||||
tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
|
||||
tests/ui/privacy/reachable-unnameable-items.rs
|
||||
tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
|
||||
tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
|
||||
tests/ui/async-await/async-fn-size-moved-locals.rs
|
||||
tests/ui/async-await/async-fn-size-uninit-locals.rs
|
||||
tests/ui/cfg/cfg-panic.rs
|
||||
@ -38,3 +35,6 @@ tests/ui/simd/issue-85915-simd-ptrs.rs
|
||||
tests/ui/issues/issue-68010-large-zst-consts.rs
|
||||
tests/ui/rust-2018/proc-macro-crate-in-paths.rs
|
||||
tests/ui/target-feature/missing-plusminus.rs
|
||||
tests/ui/sse2.rs
|
||||
tests/ui/codegen/issue-79865-llvm-miscompile.rs
|
||||
tests/ui/intrinsics/intrinsics-integer.rs
|
||||
|
@ -0,0 +1,32 @@
|
||||
From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 19 Oct 2023 13:12:51 -0400
|
||||
Subject: [PATCH] [core] Disable portable-simd test
|
||||
|
||||
---
|
||||
library/core/tests/lib.rs | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index 5814ed4..194ad4c 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -90,7 +90,6 @@
|
||||
#![feature(unwrap_infallible)]
|
||||
#![feature(pointer_byte_offsets)]
|
||||
#![feature(pointer_is_aligned)]
|
||||
-#![feature(portable_simd)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
@@ -157,7 +156,6 @@ mod pin;
|
||||
mod pin_macro;
|
||||
mod ptr;
|
||||
mod result;
|
||||
-mod simd;
|
||||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
--
|
||||
2.42.0
|
||||
|
78
src/abi.rs
78
src/abi.rs
@ -1,3 +1,5 @@
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{ToLValue, ToRValue, Type};
|
||||
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -96,14 +98,23 @@ fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnAbiGcc<'gcc> {
|
||||
pub return_type: Type<'gcc>,
|
||||
pub arguments_type: Vec<Type<'gcc>>,
|
||||
pub is_c_variadic: bool,
|
||||
pub on_stack_param_indices: FxHashSet<usize>,
|
||||
#[cfg(feature = "master")]
|
||||
pub fn_attributes: Vec<FnAttribute<'gcc>>,
|
||||
}
|
||||
|
||||
pub trait FnAbiGccExt<'gcc, 'tcx> {
|
||||
// TODO(antoyo): return a function pointer type instead?
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
|
||||
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc> {
|
||||
let mut on_stack_param_indices = FxHashSet::default();
|
||||
|
||||
// This capacity calculation is approximate.
|
||||
@ -111,7 +122,7 @@ fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>,
|
||||
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
|
||||
);
|
||||
|
||||
let return_ty =
|
||||
let return_type =
|
||||
match self.ret.mode {
|
||||
PassMode::Ignore => cx.type_void(),
|
||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
|
||||
@ -121,6 +132,26 @@ fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>,
|
||||
cx.type_void()
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "master")]
|
||||
let mut non_null_args = Vec::new();
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
|
||||
if cx.sess().opts.optimize == config::OptLevel::No {
|
||||
return ty;
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
|
||||
ty = ty.make_restrict()
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
|
||||
non_null_args.push(arg_index as i32 + 1);
|
||||
}
|
||||
ty
|
||||
};
|
||||
#[cfg(not(feature = "master"))]
|
||||
let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
|
||||
ty
|
||||
};
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| {
|
||||
@ -141,8 +172,9 @@ fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>,
|
||||
let arg_ty = match arg.mode {
|
||||
PassMode::Ignore => continue,
|
||||
PassMode::Pair(a, b) => {
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b));
|
||||
let arg_pos = argument_tys.len();
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
|
||||
argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast { ref cast, pad_i32 } => {
|
||||
@ -151,31 +183,53 @@ fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>,
|
||||
argument_tys.push(Reg::i32().gcc_type(cx));
|
||||
}
|
||||
let ty = cast.gcc_type(cx);
|
||||
apply_attrs(ty, &cast.attrs)
|
||||
apply_attrs(ty, &cast.attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
|
||||
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
|
||||
on_stack_param_indices.insert(argument_tys.len());
|
||||
arg.memory_ty(cx)
|
||||
},
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs),
|
||||
PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs)
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
|
||||
}
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &meta_attrs)
|
||||
let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
|
||||
apply_attrs(ty, &meta_attrs, argument_tys.len())
|
||||
}
|
||||
};
|
||||
argument_tys.push(arg_ty);
|
||||
}
|
||||
|
||||
(return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
|
||||
#[cfg(feature = "master")]
|
||||
let fn_attrs = if non_null_args.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![FnAttribute::NonNull(non_null_args)]
|
||||
};
|
||||
|
||||
FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type: argument_tys,
|
||||
is_c_variadic: self.c_variadic,
|
||||
on_stack_param_indices,
|
||||
#[cfg(feature = "master")]
|
||||
fn_attributes: fn_attrs,
|
||||
}
|
||||
}
|
||||
|
||||
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic);
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
..
|
||||
} = self.gcc_type(cx);
|
||||
let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
|
||||
cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
|
||||
pointer_type
|
||||
}
|
||||
|
@ -53,6 +53,9 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
||||
codegen_fn_attrs.inline
|
||||
};
|
||||
if let Some(attr) = inline_attr(cx, inline) {
|
||||
if let FnAttribute::AlwaysInline = attr {
|
||||
func.add_attribute(FnAttribute::Inline);
|
||||
}
|
||||
func.add_attribute(attr);
|
||||
}
|
||||
|
||||
|
@ -98,10 +98,11 @@ fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTarge
|
||||
.map(|string| &string[1..])
|
||||
.collect();
|
||||
|
||||
// TODO(antoyo): only set on x86 platforms.
|
||||
context.add_command_line_option("-masm=intel");
|
||||
if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
|
||||
context.add_command_line_option("-masm=intel");
|
||||
}
|
||||
|
||||
if !disabled_features.contains("avx") {
|
||||
if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" {
|
||||
// NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for
|
||||
// SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead.
|
||||
// FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar.
|
||||
|
@ -751,9 +751,8 @@ fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> R
|
||||
loaded_value.to_rvalue()
|
||||
}
|
||||
|
||||
fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): use ty.
|
||||
let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile());
|
||||
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer());
|
||||
ptr.dereference(None).to_rvalue()
|
||||
}
|
||||
|
||||
|
@ -424,35 +424,35 @@ fn is_longlong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
}
|
||||
|
||||
fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i8_type
|
||||
self.is_compatible_with(cx.i8_type)
|
||||
}
|
||||
|
||||
fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u8_type
|
||||
self.is_compatible_with(cx.u8_type)
|
||||
}
|
||||
|
||||
fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i16_type
|
||||
self.is_compatible_with(cx.i16_type)
|
||||
}
|
||||
|
||||
fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u16_type
|
||||
self.is_compatible_with(cx.u16_type)
|
||||
}
|
||||
|
||||
fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i32_type
|
||||
self.is_compatible_with(cx.i32_type)
|
||||
}
|
||||
|
||||
fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u32_type
|
||||
self.is_compatible_with(cx.u32_type)
|
||||
}
|
||||
|
||||
fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.i64_type
|
||||
self.is_compatible_with(cx.i64_type)
|
||||
}
|
||||
|
||||
fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
self.unqualified() == cx.u64_type
|
||||
self.is_compatible_with(cx.u64_type)
|
||||
}
|
||||
|
||||
fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
|
||||
|
@ -20,6 +20,7 @@
|
||||
use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
|
||||
|
||||
use crate::callee::get_fn;
|
||||
use crate::common::SignType;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FuncSig<'gcc> {
|
||||
@ -129,29 +130,57 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self {
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let i8_type = context.new_c_type(CType::Int8t);
|
||||
let i16_type = context.new_c_type(CType::Int16t);
|
||||
let i32_type = context.new_c_type(CType::Int32t);
|
||||
let i64_type = context.new_c_type(CType::Int64t);
|
||||
let u8_type = context.new_c_type(CType::UInt8t);
|
||||
let u16_type = context.new_c_type(CType::UInt16t);
|
||||
let u32_type = context.new_c_type(CType::UInt32t);
|
||||
let u64_type = context.new_c_type(CType::UInt64t);
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
#[cfg(feature="master")]
|
||||
{
|
||||
context.new_c_type(ctype).get_aligned(align)
|
||||
}
|
||||
#[cfg(not(feature="master"))]
|
||||
{
|
||||
// Since libgccjit 12 doesn't contain the fix to compare aligned integer types,
|
||||
// only align u128 and i128.
|
||||
if layout.ty.int_size_and_signed(tcx).0.bytes() == 16 {
|
||||
context.new_c_type(ctype).get_aligned(align)
|
||||
}
|
||||
else {
|
||||
context.new_c_type(ctype)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let i8_type = create_type(CType::Int8t, tcx.types.i8);
|
||||
let i16_type = create_type(CType::Int16t, tcx.types.i16);
|
||||
let i32_type = create_type(CType::Int32t, tcx.types.i32);
|
||||
let i64_type = create_type(CType::Int64t, tcx.types.i64);
|
||||
let u8_type = create_type(CType::UInt8t, tcx.types.u8);
|
||||
let u16_type = create_type(CType::UInt16t, tcx.types.u16);
|
||||
let u32_type = create_type(CType::UInt32t, tcx.types.u32);
|
||||
let u64_type = create_type(CType::UInt64t, tcx.types.u64);
|
||||
|
||||
let (i128_type, u128_type) =
|
||||
if supports_128bit_integers {
|
||||
let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
|
||||
let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
|
||||
let i128_type = create_type(CType::Int128t, tcx.types.i128);
|
||||
let u128_type = create_type(CType::UInt128t, tcx.types.u128);
|
||||
(i128_type, u128_type)
|
||||
}
|
||||
else {
|
||||
let i128_type = context.new_array_type(None, i64_type, 2);
|
||||
let u128_type = context.new_array_type(None, u64_type, 2);
|
||||
/*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
|
||||
let i128_align = layout.align.abi.bytes();
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
|
||||
let u128_align = layout.align.abi.bytes();*/
|
||||
|
||||
// TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
|
||||
// gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
|
||||
let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
|
||||
let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
|
||||
(i128_type, u128_type)
|
||||
};
|
||||
|
||||
let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
|
||||
|
||||
// TODO(antoyo): set alignment on those types as well.
|
||||
let float_type = context.new_type::<f32>();
|
||||
let double_type = context.new_type::<f64>();
|
||||
|
||||
@ -167,14 +196,10 @@ pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
let ulonglong_type = context.new_c_type(CType::ULongLong);
|
||||
let sizet_type = context.new_c_type(CType::SizeT);
|
||||
|
||||
let isize_type = context.new_c_type(CType::LongLong);
|
||||
let usize_type = context.new_c_type(CType::ULongLong);
|
||||
let usize_type = sizet_type;
|
||||
let isize_type = usize_type;
|
||||
let bool_type = context.new_type::<bool>();
|
||||
|
||||
// TODO(antoyo): only have those assertions on x86_64.
|
||||
assert_eq!(isize_type.get_size(), i64_type.get_size());
|
||||
assert_eq!(usize_type.get_size(), u64_type.get_size());
|
||||
|
||||
let mut functions = FxHashMap::default();
|
||||
let builtins = [
|
||||
"__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow",
|
||||
@ -192,7 +217,7 @@ pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
|
||||
}
|
||||
|
||||
Self {
|
||||
let mut cx = Self {
|
||||
check_overflow,
|
||||
codegen_unit,
|
||||
context,
|
||||
@ -254,7 +279,10 @@ pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
pointee_infos: Default::default(),
|
||||
structs_as_pointer: Default::default(),
|
||||
cleanup_blocks: Default::default(),
|
||||
}
|
||||
};
|
||||
// TODO(antoyo): instead of doing this, add SsizeT to libgccjit.
|
||||
cx.isize_type = usize_type.to_signed(&cx);
|
||||
cx
|
||||
}
|
||||
|
||||
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
|
||||
|
@ -6,7 +6,7 @@
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::intrinsic::llvm;
|
||||
|
||||
@ -80,9 +80,20 @@ pub fn declare_entry_fn(&self, name: &str, _fn_type: Type<'gcc>, callconv: () /*
|
||||
}
|
||||
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
|
||||
let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic);
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
on_stack_param_indices,
|
||||
#[cfg(feature="master")]
|
||||
fn_attributes,
|
||||
} = fn_abi.gcc_type(self);
|
||||
let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
|
||||
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
|
||||
#[cfg(feature="master")]
|
||||
for fn_attr in fn_attributes {
|
||||
func.add_attribute(fn_attr);
|
||||
}
|
||||
func
|
||||
}
|
||||
|
||||
|
@ -198,9 +198,16 @@ pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) ->
|
||||
None
|
||||
}
|
||||
|
||||
fn arch_to_gcc(name: &str) -> &str {
|
||||
match name {
|
||||
"M68020" => "68020",
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_native(name: &str) -> &str {
|
||||
if name != "native" {
|
||||
return name;
|
||||
return arch_to_gcc(name);
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
|
165
src/int.rs
165
src/int.rs
@ -7,7 +7,9 @@
|
||||
use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{ParamEnv, Ty};
|
||||
use rustc_target::abi::{Endian, call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}};
|
||||
use rustc_target::spec;
|
||||
|
||||
use crate::builder::ToGccComp;
|
||||
use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx};
|
||||
@ -37,11 +39,10 @@ pub fn gcc_not(&self, a: RValue<'gcc>) -> RValue<'gcc> {
|
||||
}
|
||||
else {
|
||||
let element_type = typ.dyncast_array().expect("element type");
|
||||
let values = [
|
||||
self.from_low_high_rvalues(typ,
|
||||
self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
|
||||
self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)),
|
||||
];
|
||||
self.cx.context.new_array_constructor(None, typ, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +101,6 @@ pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
|
||||
self.llbb().end_with_conditional(None, condition, then_block, else_block);
|
||||
|
||||
// TODO(antoyo): take endianness into account.
|
||||
let shift_value = self.gcc_sub(b, sixty_four);
|
||||
let high = self.high(a);
|
||||
let sign =
|
||||
@ -110,11 +110,7 @@ pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
else {
|
||||
zero
|
||||
};
|
||||
let values = [
|
||||
high >> shift_value,
|
||||
sign,
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
|
||||
then_block.add_assignment(None, result, array_value);
|
||||
then_block.end_with_jump(None, after_block);
|
||||
|
||||
@ -130,11 +126,10 @@ pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
|
||||
let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type);
|
||||
let shifted_low = self.context.new_cast(None, shifted_low, native_int_type);
|
||||
let values = [
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
(high << shift_value) | shifted_low,
|
||||
high >> b,
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
actual_else_block.add_assignment(None, result, array_value);
|
||||
actual_else_block.end_with_jump(None, after_block);
|
||||
|
||||
@ -314,18 +309,7 @@ pub fn gcc_checked_binop(&self, oop: OverflowOp, typ: Ty<'_>, lhs: <Self as Back
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
let param_a = self.context.new_parameter(None, a_type, "a");
|
||||
let param_b = self.context.new_parameter(None, b_type, "b");
|
||||
let result_field = self.context.new_field(None, a_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
return (int_result, overflow);
|
||||
return self.operation_with_overflow(func_name, lhs, rhs);
|
||||
},
|
||||
_ => {
|
||||
match oop {
|
||||
@ -350,6 +334,54 @@ pub fn gcc_checked_binop(&self, oop: OverflowOp, typ: Ty<'_>, lhs: <Self as Back
|
||||
(res.dereference(None).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
let param_a = self.context.new_parameter(None, a_type, "a");
|
||||
let param_b = self.context.new_parameter(None, b_type, "b");
|
||||
let result_field = self.context.new_field(None, a_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
|
||||
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
|
||||
let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
|
||||
|
||||
let arg_abi = ArgAbi {
|
||||
layout,
|
||||
mode: PassMode::Direct(ArgAttributes::new()),
|
||||
};
|
||||
let mut fn_abi = FnAbi {
|
||||
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
ret: arg_abi,
|
||||
c_variadic: false,
|
||||
fixed_count: 2,
|
||||
conv: Conv::C,
|
||||
can_unwind: false,
|
||||
};
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C {
|
||||
unwind: false,
|
||||
}).unwrap();
|
||||
|
||||
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let result =
|
||||
if indirect {
|
||||
let return_value = self.current_func().new_local(None, return_type.as_type(), "return_value");
|
||||
let return_param_type = return_type.as_type().make_pointer();
|
||||
let return_param = self.context.new_parameter(None, return_param_type, "return_value");
|
||||
let func = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false);
|
||||
self.llbb().add_eval(None, self.context.new_call(None, func, &[return_value.get_address(None), lhs, rhs]));
|
||||
return_value.to_rvalue()
|
||||
}
|
||||
else {
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
self.context.new_call(None, func, &[lhs, rhs])
|
||||
};
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
return (int_result, overflow);
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
@ -415,6 +447,7 @@ pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RVa
|
||||
IntPredicate::IntNE => {
|
||||
return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type));
|
||||
},
|
||||
// TODO(antoyo): cast to u128 for unsigned comparison. See below.
|
||||
IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
|
||||
IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
|
||||
IntPredicate::IntULT => (ComparisonOp::Equals, 0),
|
||||
@ -444,6 +477,18 @@ pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RVa
|
||||
rhs = self.context.new_cast(None, rhs, a_type);
|
||||
}
|
||||
}
|
||||
match op {
|
||||
IntPredicate::IntUGT | IntPredicate::IntUGE | IntPredicate::IntULT | IntPredicate::IntULE => {
|
||||
if !a_type.is_vector() {
|
||||
let unsigned_type = a_type.to_unsigned(&self.cx);
|
||||
lhs = self.context.new_cast(None, lhs, unsigned_type);
|
||||
rhs = self.context.new_cast(None, rhs, unsigned_type);
|
||||
}
|
||||
},
|
||||
// TODO(antoyo): we probably need to handle signed comparison for unsigned
|
||||
// integers.
|
||||
_ => (),
|
||||
}
|
||||
self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
|
||||
}
|
||||
}
|
||||
@ -455,11 +500,10 @@ pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
a ^ b
|
||||
}
|
||||
else {
|
||||
let values = [
|
||||
self.from_low_high_rvalues(a_type,
|
||||
self.low(a) ^ self.low(b),
|
||||
self.high(a) ^ self.high(b),
|
||||
];
|
||||
self.context.new_array_constructor(None, a_type, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,12 +549,10 @@ pub fn gcc_shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
|
||||
self.llbb().end_with_conditional(None, condition, then_block, else_block);
|
||||
|
||||
// TODO(antoyo): take endianness into account.
|
||||
let values = [
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
zero,
|
||||
self.low(a) << (b - sixty_four),
|
||||
];
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
then_block.add_assignment(None, result, array_value);
|
||||
then_block.end_with_jump(None, after_block);
|
||||
|
||||
@ -521,16 +563,16 @@ pub fn gcc_shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
b0_block.end_with_jump(None, after_block);
|
||||
|
||||
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
|
||||
// TODO(antoyo): adjust this ^ comment.
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
|
||||
let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type);
|
||||
let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type);
|
||||
let values = [
|
||||
|
||||
let array_value = self.from_low_high_rvalues(a_type,
|
||||
self.low(a) << b,
|
||||
(self.high(a) << b) | high_low,
|
||||
];
|
||||
|
||||
let array_value = self.context.new_array_constructor(None, a_type, &values);
|
||||
);
|
||||
actual_else_block.add_assignment(None, result, array_value);
|
||||
actual_else_block.end_with_jump(None, after_block);
|
||||
|
||||
@ -546,16 +588,16 @@ pub fn gcc_bswap(&mut self, mut arg: RValue<'gcc>, width: u64) -> RValue<'gcc> {
|
||||
let arg_type = arg.get_type();
|
||||
if !self.is_native_int_type(arg_type) {
|
||||
let native_int_type = arg_type.dyncast_array().expect("get element type");
|
||||
let lsb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 0)).to_rvalue();
|
||||
let lsb = self.low(arg);
|
||||
let swapped_lsb = self.gcc_bswap(lsb, width / 2);
|
||||
let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type);
|
||||
let msb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 1)).to_rvalue();
|
||||
let msb = self.high(arg);
|
||||
let swapped_msb = self.gcc_bswap(msb, width / 2);
|
||||
let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type);
|
||||
|
||||
// NOTE: we also need to swap the two elements here, in addition to swapping inside
|
||||
// the elements themselves like done above.
|
||||
return self.context.new_array_constructor(None, arg_type, &[swapped_msb, swapped_lsb]);
|
||||
return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
|
||||
}
|
||||
|
||||
// TODO(antoyo): check if it's faster to use string literals and a
|
||||
@ -659,11 +701,10 @@ fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<
|
||||
else {
|
||||
assert!(!a_native && !b_native, "both types should either be native or non-native for or operation");
|
||||
let native_int_type = a_type.dyncast_array().expect("get element type");
|
||||
let values = [
|
||||
self.from_low_high_rvalues(a_type,
|
||||
self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)),
|
||||
self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)),
|
||||
];
|
||||
self.context.new_array_constructor(None, a_type, &values)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -687,11 +728,10 @@ pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<
|
||||
let zero = self.context.new_rvalue_zero(value_type);
|
||||
let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
|
||||
let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
|
||||
let values = [
|
||||
self.from_low_high_rvalues(dest_typ,
|
||||
self.context.new_cast(None, value, dest_element_type),
|
||||
self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
|
||||
];
|
||||
self.context.new_array_constructor(None, dest_typ, &values)
|
||||
)
|
||||
}
|
||||
else {
|
||||
// Since u128 and i128 are the only types that can be unsupported, we know the type of
|
||||
@ -769,20 +809,47 @@ pub fn gcc_float_to_uint_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>)
|
||||
}
|
||||
|
||||
fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 1))
|
||||
let index =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => 1,
|
||||
Endian::Big => 0,
|
||||
};
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
|
||||
.to_rvalue()
|
||||
}
|
||||
|
||||
fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 0))
|
||||
let index =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => 0,
|
||||
Endian::Big => 1,
|
||||
};
|
||||
self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
|
||||
.to_rvalue()
|
||||
}
|
||||
|
||||
fn from_low_high_rvalues(&self, typ: Type<'gcc>, low: RValue<'gcc>, high: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let (first, last) =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => (low, high),
|
||||
Endian::Big => (high, low),
|
||||
};
|
||||
|
||||
let values = [first, last];
|
||||
self.context.new_array_constructor(None, typ, &values)
|
||||
}
|
||||
|
||||
fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
|
||||
let (first, last) =
|
||||
match self.sess().target.options.endian {
|
||||
Endian::Little => (low, high),
|
||||
Endian::Big => (high, low),
|
||||
};
|
||||
|
||||
let native_int_type = typ.dyncast_array().expect("get element type");
|
||||
let values = [
|
||||
self.context.new_rvalue_from_long(native_int_type, low),
|
||||
self.context.new_rvalue_from_long(native_int_type, high),
|
||||
self.context.new_rvalue_from_long(native_int_type, first),
|
||||
self.context.new_rvalue_from_long(native_int_type, last),
|
||||
];
|
||||
self.context.new_array_constructor(None, typ, &values)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -432,15 +432,21 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
|
||||
match name {
|
||||
"llvm.x86.xgetbv" | "llvm.x86.sse2.pause" => {
|
||||
let gcc_name = "__builtin_trap";
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
},
|
||||
_ => unimplemented!("unsupported LLVM intrinsic {}", name),
|
||||
}
|
||||
let gcc_name =
|
||||
match name {
|
||||
"llvm.x86.sse2.pause" => {
|
||||
// NOTE: pause is only a hint, so we use a dummy built-in because target built-ins
|
||||
// are not supported in libgccjit 12.
|
||||
"__builtin_inff"
|
||||
},
|
||||
"llvm.x86.xgetbv" => {
|
||||
"__builtin_trap"
|
||||
},
|
||||
_ => unimplemented!("unsupported LLVM intrinsic {}", name),
|
||||
};
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
|
@ -4,7 +4,9 @@
|
||||
#[cfg(feature="master")]
|
||||
use std::iter;
|
||||
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
|
||||
#[cfg(feature="master")]
|
||||
use gccjit::FunctionType;
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::common::IntPredicate;
|
||||
@ -143,11 +145,15 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
|
||||
|
||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let mut ptr = args[0].immediate();
|
||||
if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
|
||||
ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
|
||||
}
|
||||
let load = self.volatile_load(ptr.get_type(), ptr);
|
||||
let ptr = args[0].immediate();
|
||||
let load =
|
||||
if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
|
||||
let gcc_ty = ty.gcc_type(self);
|
||||
self.volatile_load(gcc_ty, ptr)
|
||||
}
|
||||
else {
|
||||
self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
|
||||
};
|
||||
// TODO(antoyo): set alignment.
|
||||
self.to_immediate(load, self.layout_of(tp_ty))
|
||||
}
|
||||
@ -819,75 +825,58 @@ fn pop_count(&mut self, value: RValue<'gcc>) -> RValue<'gcc> {
|
||||
value
|
||||
};
|
||||
|
||||
if value_type.is_u128(&self.cx) {
|
||||
// TODO(antoyo): implement in the normal algorithm below to have a more efficient
|
||||
// implementation (that does not require a call to __popcountdi2).
|
||||
let popcount = self.context.get_builtin_function("__builtin_popcountll");
|
||||
// only break apart 128-bit ints if they're not natively supported
|
||||
// TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
|
||||
if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
|
||||
let sixty_four = self.gcc_int(value_type, 64);
|
||||
let right_shift = self.gcc_lshr(value, sixty_four);
|
||||
let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
|
||||
let high = self.context.new_call(None, popcount, &[high]);
|
||||
let high = self.pop_count(high);
|
||||
let low = self.gcc_int_cast(value, self.cx.ulonglong_type);
|
||||
let low = self.context.new_call(None, popcount, &[low]);
|
||||
let low = self.pop_count(low);
|
||||
let res = high + low;
|
||||
return self.gcc_int_cast(res, result_type);
|
||||
}
|
||||
|
||||
// First step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x5555555555555555);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 1);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// Use Wenger's algorithm for population count, gcc's seems to play better with it
|
||||
// for (int counter = 0; value != 0; counter++) {
|
||||
// value &= value - 1;
|
||||
// }
|
||||
let func = self.current_func.borrow().expect("func");
|
||||
let loop_head = func.new_block("head");
|
||||
let loop_body = func.new_block("body");
|
||||
let loop_tail = func.new_block("tail");
|
||||
|
||||
// Second step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x3333333333333333);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 2);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
let counter_type = self.int_type;
|
||||
let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
|
||||
let val = self.current_func().new_local(None, value_type, "popcount_value");
|
||||
let zero = self.gcc_zero(counter_type);
|
||||
self.llbb().add_assignment(None, counter, zero);
|
||||
self.llbb().add_assignment(None, val, value);
|
||||
self.br(loop_head);
|
||||
|
||||
// Third step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x0F0F0F0F0F0F0F0F);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 4);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// check if value isn't zero
|
||||
self.switch_to_block(loop_head);
|
||||
let zero = self.gcc_zero(value_type);
|
||||
let cond = self.gcc_icmp(IntPredicate::IntNE, val.to_rvalue(), zero);
|
||||
self.cond_br(cond, loop_body, loop_tail);
|
||||
|
||||
if value_type.is_u8(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
// val &= val - 1;
|
||||
self.switch_to_block(loop_body);
|
||||
let one = self.gcc_int(value_type, 1);
|
||||
let sub = self.gcc_sub(val.to_rvalue(), one);
|
||||
let op = self.gcc_and(val.to_rvalue(), sub);
|
||||
loop_body.add_assignment(None, val, op);
|
||||
|
||||
// Fourth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x00FF00FF00FF00FF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 8);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
// counter += 1
|
||||
let one = self.gcc_int(counter_type, 1);
|
||||
let op = self.gcc_add(counter.to_rvalue(), one);
|
||||
loop_body.add_assignment(None, counter, op);
|
||||
self.br(loop_head);
|
||||
|
||||
if value_type.is_u16(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fifth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x0000FFFF0000FFFF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 16);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u32(&self.cx) {
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Sixth step.
|
||||
let mask = self.context.new_rvalue_from_long(value_type, 0x00000000FFFFFFFF);
|
||||
let left = value & mask;
|
||||
let shifted = value >> self.context.new_rvalue_from_int(value_type, 32);
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
self.context.new_cast(None, value, result_type)
|
||||
// end of loop
|
||||
self.switch_to_block(loop_tail);
|
||||
self.gcc_int_cast(counter.to_rvalue(), result_type)
|
||||
}
|
||||
|
||||
// Algorithm from: https://blog.regehr.org/archives/1063
|
||||
@ -947,15 +936,7 @@ fn saturating_add(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool,
|
||||
128 => "__rust_i128_addo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let param_a = self.context.new_parameter(None, result_type, "a");
|
||||
let param_b = self.context.new_parameter(None, result_type, "b");
|
||||
let result_field = self.context.new_field(None, result_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
self.llbb().add_assignment(None, res, int_result);
|
||||
overflow
|
||||
};
|
||||
@ -1017,15 +998,7 @@ fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool,
|
||||
128 => "__rust_i128_subo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let param_a = self.context.new_parameter(None, result_type, "a");
|
||||
let param_b = self.context.new_parameter(None, result_type, "b");
|
||||
let result_field = self.context.new_field(None, result_type, "result");
|
||||
let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
|
||||
let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
|
||||
let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
|
||||
let result = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
let overflow = result.access_field(None, overflow_field);
|
||||
let int_result = result.access_field(None, result_field);
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
self.llbb().add_assignment(None, res, int_result);
|
||||
overflow
|
||||
};
|
||||
@ -1197,7 +1170,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
|
||||
#[cfg(feature="master")]
|
||||
fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
|
||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||
let (typ, _, _, _) = fn_abi.gcc_type(cx);
|
||||
let return_type = fn_abi.gcc_type(cx).return_type;
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
cx.linkage.set(FunctionType::Internal);
|
||||
let func = cx.declare_fn(name, fn_abi);
|
||||
@ -1207,5 +1180,5 @@ fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig
|
||||
let block = Builder::append_block(cx, func_val, "entry-block");
|
||||
let bx = Builder::build(cx, block);
|
||||
codegen(bx);
|
||||
(typ, func)
|
||||
(return_type, func)
|
||||
}
|
||||
|
@ -251,8 +251,9 @@ fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: Al
|
||||
temp_dir: None,
|
||||
};
|
||||
|
||||
// TODO(antoyo): only set for x86.
|
||||
mods.context.add_command_line_option("-masm=intel");
|
||||
if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
|
||||
mods.context.add_command_line_option("-masm=intel");
|
||||
}
|
||||
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
|
||||
mods
|
||||
}
|
||||
|
14
src/type_.rs
14
src/type_.rs
@ -119,11 +119,11 @@ fn type_isize(&self) -> Type<'gcc> {
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> Type<'gcc> {
|
||||
self.context.new_type::<f32>()
|
||||
self.float_type
|
||||
}
|
||||
|
||||
fn type_f64(&self) -> Type<'gcc> {
|
||||
self.context.new_type::<f64>()
|
||||
self.double_type
|
||||
}
|
||||
|
||||
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
||||
@ -216,17 +216,17 @@ fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> {
|
||||
value.get_type()
|
||||
}
|
||||
|
||||
fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> {
|
||||
// TODO: remove this as well?
|
||||
/*if let Some(struct_type) = ty.is_struct() {
|
||||
#[cfg_attr(feature="master", allow(unused_mut))]
|
||||
fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
|
||||
#[cfg(not(feature="master"))]
|
||||
if let Some(struct_type) = ty.is_struct() {
|
||||
if struct_type.get_field_count() == 0 {
|
||||
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
|
||||
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
|
||||
// zero for ZSTs.
|
||||
// FIXME(antoyo): fix gccjit API.
|
||||
len = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
self.context.new_array_type(None, ty, len)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
|
||||
use crate::abi::{FnAbiGccExt, GccType};
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_::struct_fields;
|
||||
|
||||
@ -372,7 +372,13 @@ fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> {
|
||||
}
|
||||
|
||||
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
||||
let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic)
|
||||
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
||||
let FnAbiGcc {
|
||||
return_type,
|
||||
arguments_type,
|
||||
is_c_variadic,
|
||||
..
|
||||
} = fn_abi.gcc_type(self);
|
||||
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
|
||||
}
|
||||
}
|
||||
|
36
test.sh
36
test.sh
@ -151,7 +151,11 @@ function clean() {
|
||||
|
||||
function mini_tests() {
|
||||
echo "[BUILD] mini_core"
|
||||
$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
|
||||
crate_types="lib,dylib"
|
||||
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
crate_types="lib"
|
||||
fi
|
||||
$RUSTC example/mini_core.rs --crate-name mini_core --crate-type $crate_types --target $TARGET_TRIPLE
|
||||
|
||||
echo "[BUILD] example"
|
||||
$RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
|
||||
@ -166,6 +170,23 @@ function build_sysroot() {
|
||||
time ./build_sysroot/build_sysroot.sh $sysroot_channel
|
||||
}
|
||||
|
||||
# TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible.
|
||||
function run_in_vm() {
|
||||
vm_parent_dir=${CG_GCC_VM_DIR:-$(pwd)}
|
||||
vm_dir=vm
|
||||
exe=$1
|
||||
exe_filename=$(basename $exe)
|
||||
vm_home_dir=$vm_parent_dir/$vm_dir/home
|
||||
vm_exe_path=$vm_home_dir/$exe_filename
|
||||
inside_vm_exe_path=/home/$exe_filename
|
||||
sudo cp $exe $vm_exe_path
|
||||
|
||||
shift
|
||||
pushd $vm_parent_dir
|
||||
sudo chroot $vm_dir qemu-m68k-static $inside_vm_exe_path $@
|
||||
popd
|
||||
}
|
||||
|
||||
function std_tests() {
|
||||
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
|
||||
$RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
|
||||
@ -174,9 +195,12 @@ function std_tests() {
|
||||
echo "[AOT] alloc_system"
|
||||
$RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
|
||||
|
||||
echo "[AOT] alloc_example"
|
||||
$RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/alloc_example
|
||||
# FIXME: doesn't work on m68k.
|
||||
if [[ "$HOST_TRIPLE" == "$TARGET_TRIPLE" ]]; then
|
||||
echo "[AOT] alloc_example"
|
||||
$RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/alloc_example
|
||||
fi
|
||||
|
||||
echo "[AOT] dst_field_align"
|
||||
# FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
|
||||
@ -225,7 +249,7 @@ verbose-tests = true
|
||||
[build]
|
||||
cargo = "$(rustup which cargo)"
|
||||
local-rebuild = true
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
|
||||
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$HOST_TRIPLE/bin/rustc"
|
||||
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
|
||||
@ -393,7 +417,7 @@ function test_rustc() {
|
||||
fi
|
||||
|
||||
echo "[TEST] rustc test suite"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS"
|
||||
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS" # --target $TARGET_TRIPLE
|
||||
}
|
||||
|
||||
function test_failing_rustc() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! The common code for `tests/lang_tests_*.rs`
|
||||
use std::{
|
||||
env::{self, current_dir},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
@ -23,9 +23,29 @@ pub fn main_inner(profile: Profile) {
|
||||
let gcc_path = include_str!("../gcc_path");
|
||||
let gcc_path = gcc_path.trim();
|
||||
env::set_var("LD_LIBRARY_PATH", gcc_path);
|
||||
|
||||
fn rust_filter(filename: &Path) -> bool {
|
||||
filename.extension().expect("extension").to_str().expect("to_str") == "rs"
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn filter(filename: &Path) -> bool {
|
||||
rust_filter(filename)
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn filter(filename: &Path) -> bool {
|
||||
if let Some(filename) = filename.to_str() {
|
||||
if filename.ends_with("gep.rs") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rust_filter(filename)
|
||||
}
|
||||
|
||||
LangTester::new()
|
||||
.test_dir("tests/run")
|
||||
.test_file_filter(|path| path.extension().expect("extension").to_str().expect("to_str") == "rs")
|
||||
.test_file_filter(filter)
|
||||
.test_extract(|source| {
|
||||
let lines =
|
||||
source.lines()
|
||||
@ -50,6 +70,19 @@ pub fn main_inner(profile: Profile) {
|
||||
"-o", exe.to_str().expect("to_str"),
|
||||
path.to_str().expect("to_str"),
|
||||
]);
|
||||
|
||||
// TODO(antoyo): find a way to send this via a cli argument.
|
||||
let test_target = std::env::var("CG_GCC_TEST_TARGET");
|
||||
if let Ok(ref target) = test_target {
|
||||
compiler.args(&["--target", &target]);
|
||||
let linker = format!("{}-gcc", target);
|
||||
compiler.args(&[format!("-Clinker={}", linker)]);
|
||||
let mut env_path = std::env::var("PATH").unwrap_or_default();
|
||||
// TODO(antoyo): find a better way to add the PATH necessary locally.
|
||||
env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path);
|
||||
compiler.env("PATH", env_path);
|
||||
}
|
||||
|
||||
if let Some(flags) = option_env!("TEST_FLAGS") {
|
||||
for flag in flags.split_whitespace() {
|
||||
compiler.arg(&flag);
|
||||
@ -65,8 +98,37 @@ pub fn main_inner(profile: Profile) {
|
||||
}
|
||||
}
|
||||
// Test command 2: run `tempdir/x`.
|
||||
let runtime = Command::new(exe);
|
||||
vec![("Compiler", compiler), ("Run-time", runtime)]
|
||||
if test_target.is_ok() {
|
||||
let vm_parent_dir = std::env::var("CG_GCC_VM_DIR")
|
||||
.map(|dir| PathBuf::from(dir))
|
||||
.unwrap_or_else(|_| std::env::current_dir().unwrap());
|
||||
let vm_dir = "vm";
|
||||
let exe_filename = exe.file_name().unwrap();
|
||||
let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
|
||||
let vm_exe_path = vm_home_dir.join(exe_filename);
|
||||
// FIXME(antoyo): panicking here makes the test pass.
|
||||
let inside_vm_exe_path = PathBuf::from("/home").join(&exe_filename);
|
||||
let mut copy = Command::new("sudo");
|
||||
copy.arg("cp");
|
||||
copy.args(&[&exe, &vm_exe_path]);
|
||||
|
||||
let mut runtime = Command::new("sudo");
|
||||
runtime.args(&["chroot", vm_dir, "qemu-m68k-static"]);
|
||||
runtime.arg(inside_vm_exe_path);
|
||||
runtime.current_dir(vm_parent_dir);
|
||||
vec![
|
||||
("Compiler", compiler),
|
||||
("Copy", copy),
|
||||
("Run-time", runtime),
|
||||
]
|
||||
}
|
||||
else {
|
||||
let runtime = Command::new(exe);
|
||||
vec![
|
||||
("Compiler", compiler),
|
||||
("Run-time", runtime),
|
||||
]
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
#![feature(asm_const)]
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
use std::arch::{asm, global_asm};
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
global_asm!(
|
||||
"
|
||||
.global add_asm
|
||||
@ -20,6 +22,7 @@
|
||||
fn add_asm(a: i64, b: i64) -> i64;
|
||||
}
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
|
||||
asm!(
|
||||
"rep movsb",
|
||||
@ -30,7 +33,8 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_arch="x86_64")]
|
||||
fn asm() {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
}
|
||||
@ -173,3 +177,11 @@ extern "C" fn foo() -> u64 {
|
||||
}
|
||||
assert_eq!(array1, array2);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch="x86_64"))]
|
||||
fn asm() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
asm();
|
||||
}
|
||||
|
@ -35,6 +35,6 @@ trait Receiver {
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
@ -4,138 +4,20 @@
|
||||
// stdout: Success
|
||||
// status: signal
|
||||
|
||||
#![allow(internal_features, unused_attributes)]
|
||||
#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
fn main() {
|
||||
std::panic::set_hook(Box::new(|_| {
|
||||
println!("Success");
|
||||
std::process::abort();
|
||||
}));
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for *mut i32 {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
pub fn fflush(stream: *mut i32) -> i32;
|
||||
|
||||
pub static stdout: *mut i32;
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
// Panicking is expected iff overflow checking is enabled.
|
||||
#[cfg(debug_assertions)]
|
||||
libc::puts("Success\0" as *const str as *const u8);
|
||||
libc::fflush(libc::stdout);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "add"]
|
||||
trait Add<RHS = Self> {
|
||||
type Output;
|
||||
|
||||
fn add(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
impl Add for u8 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for i8 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for i32 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for usize {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for isize {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
let int = 9223372036854775807isize;
|
||||
let int = int + argc; // overflow
|
||||
let arg_count = std::env::args().count();
|
||||
let int = isize::MAX;
|
||||
let _int = int + arg_count as isize; // overflow
|
||||
|
||||
// If overflow checking is disabled, we should reach here.
|
||||
#[cfg(not(debug_assertions))]
|
||||
unsafe {
|
||||
libc::puts("Success\0" as *const str as *const u8);
|
||||
libc::fflush(libc::stdout);
|
||||
intrinsics::abort();
|
||||
println!("Success");
|
||||
std::process::abort();
|
||||
}
|
||||
|
||||
int
|
||||
}
|
||||
|
26
tests/run/volatile.rs
Normal file
26
tests/run/volatile.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Struct {
|
||||
pointer: *const (),
|
||||
func: unsafe fn(*const ()),
|
||||
}
|
||||
|
||||
fn func(ptr: *const ()) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = MaybeUninit::<&Struct>::uninit();
|
||||
x.write(&Struct {
|
||||
pointer: std::ptr::null(),
|
||||
func,
|
||||
});
|
||||
let x = unsafe { x.assume_init() };
|
||||
let value = unsafe { (x as *const Struct).read_volatile() };
|
||||
println!("{:?}", value);
|
||||
}
|
Loading…
Reference in New Issue
Block a user