diff --git a/.github/workflows/basic_cli_build_release.yml b/.github/workflows/basic_cli_build_release.yml index 3719b98b33f..000bcc06f26 100644 --- a/.github/workflows/basic_cli_build_release.yml +++ b/.github/workflows/basic_cli_build_release.yml @@ -1,5 +1,5 @@ on: -# pull_request: + # pull_request: workflow_dispatch: # this cancels workflows currently in progress if you start a new one @@ -46,7 +46,7 @@ jobs: - name: Save roc_nightly archives uses: actions/upload-artifact@v4 with: - path: roc_nightly-* + path: roc_nightly-* build-linux-x86_64-files: runs-on: [ubuntu-20.04] @@ -71,7 +71,6 @@ jobs: basic-cli/platform/linux-x64.rh basic-cli/platform/linux-x64.a - build-linux-arm64-files: runs-on: [self-hosted, Linux, ARM64] needs: [prepare] @@ -84,8 +83,8 @@ jobs: - name: build basic-cli env: CARGO_BUILD_TARGET: aarch64-unknown-linux-musl - CC_aarch64_unknown_linux_musl: clang-16 - AR_aarch64_unknown_linux_musl: llvm-ar-16 + CC_aarch64_unknown_linux_musl: clang-18 + AR_aarch64_unknown_linux_musl: llvm-ar-18 CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld" run: ./ci/build_basic_cli.sh linux_arm64 @@ -134,7 +133,13 @@ jobs: basic-cli/platform/macos-arm64.a create-release-archive: - needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files] + needs: + [ + build-linux-x86_64-files, + build-linux-arm64-files, + build-macos-x86_64-files, + build-macos-apple-silicon-files, + ] name: create release archive runs-on: [ubuntu-20.04] steps: @@ -202,7 +207,6 @@ jobs: needs: [create-release-archive] runs-on: [ubuntu-20.04] steps: - - name: Download the previously uploaded files uses: actions/download-artifact@v4 diff --git a/.github/workflows/basic_webserver_build_release.yml b/.github/workflows/basic_webserver_build_release.yml index 10848a103cb..082d26ae76d 100644 --- a/.github/workflows/basic_webserver_build_release.yml +++ b/.github/workflows/basic_webserver_build_release.yml @@ -28,11 +28,10 @@ jobs: #- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_x86_64-TESTING.tar.gz #- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-TESTING.tar.gz - - name: Save roc_nightly archives uses: actions/upload-artifact@v4 with: - path: roc_nightly-* + path: roc_nightly-* build-linux-x86_64-files: runs-on: [ubuntu-20.04] @@ -57,7 +56,6 @@ jobs: basic-webserver/platform/linux-x64.rh basic-webserver/platform/linux-x64.a - build-linux-arm64-files: runs-on: [self-hosted, Linux, ARM64] needs: [fetch-releases] @@ -70,8 +68,8 @@ jobs: - name: build basic-webserver env: CARGO_BUILD_TARGET: aarch64-unknown-linux-musl - CC_aarch64_unknown_linux_musl: clang-16 - AR_aarch64_unknown_linux_musl: llvm-ar-16 + CC_aarch64_unknown_linux_musl: clang-18 + AR_aarch64_unknown_linux_musl: llvm-ar-18 CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld" run: ./ci/build_basic_webserver.sh linux_arm64 @@ -120,7 +118,13 @@ jobs: basic-webserver/platform/macos-arm64.a create-release-archive: - needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files] + needs: + [ + build-linux-x86_64-files, + build-linux-arm64-files, + build-macos-x86_64-files, + build-macos-apple-silicon-files, + ] name: create release archive runs-on: [ubuntu-20.04] steps: diff --git a/.github/workflows/macos_x86_64.yml b/.github/workflows/macos_x86_64.yml index 745c1f27fce..867e4543e15 100644 --- a/.github/workflows/macos_x86_64.yml +++ b/.github/workflows/macos_x86_64.yml @@ -1,33 +1,36 @@ on: - workflow_call: + workflow_call: name: Macos x86-64 rust tests env: - RUST_BACKTRACE: 1 + RUST_BACKTRACE: 1 jobs: - test-rust-macos-x86-64: - runs-on: [self-hosted, macOS, X64] - timeout-minutes: 90 - env: - RUSTC_WRAPPER: /Users/username1/.cargo/bin/sccache - steps: - - uses: actions/checkout@v4 - - - name: set LLVM_SYS_160_PREFIX - run: echo "LLVM_SYS_160_PREFIX=$(brew --prefix llvm@16)" >> $GITHUB_ENV - - - name: Update PATH to use zig 11 - run: | - echo "PATH=/Users/username1/Downloads/zig-macos-x86_64-0.11.0:$PATH" >> $GITHUB_ENV - - - run: zig version - - - name: test_gen llvm tests - run: cargo nextest-gen-llvm --release --no-fail-fast --locked -E "package(test_gen) - test(gen_str::str_append_scalar)" - - - name: regular rust tests - run: cargo test --locked --release -- --skip opaque_wrap_function --skip gen_list::bool_list_literal --skip platform_switching_swift --skip swift_ui --skip gen_tags::phantom_polymorphic_record && sccache --show-stats - # swift tests are skipped because of "Could not find or use auto-linked library 'swiftCompatibilityConcurrency'" on macos x86_64 CI machine - # this issue may be caused by using older versions of XCode + test-rust-macos-x86-64: + runs-on: [self-hosted, macOS, X64] + timeout-minutes: 90 + env: + RUSTC_WRAPPER: /Users/username1/.cargo/bin/sccache + steps: + - uses: actions/checkout@v4 + + - name: set LLVM_SYS_180_PREFIX + run: echo "LLVM_SYS_180_PREFIX=$(brew --prefix llvm@18)" >> $GITHUB_ENV + + - name: check for zig 13 + run: ls /Users/username1/Downloads/zig-macos-x86_64-0.13.0 + + - name: Update PATH to use zig 13 + run: | + echo "PATH=/Users/username1/Downloads/zig-macos-x86_64-0.13.0:$PATH" >> $GITHUB_ENV + + - run: zig version + + - name: test_gen llvm tests + run: cargo nextest-gen-llvm --release --no-fail-fast --locked -E "package(test_gen) - test(gen_str::str_append_scalar)" + + - name: regular rust tests + run: cargo test --locked --release -- --skip opaque_wrap_function --skip gen_list::bool_list_literal --skip platform_switching_swift --skip swift_ui --skip gen_tags::phantom_polymorphic_record && sccache --show-stats + # swift tests are skipped because of "Could not find or use auto-linked library 'swiftCompatibilityConcurrency'" on macos x86_64 CI machine + # this issue may be caused by using older versions of XCode diff --git a/.github/workflows/nightly_linux_arm64.yml b/.github/workflows/nightly_linux_arm64.yml index 6e6884ca6ea..54f6099d20e 100644 --- a/.github/workflows/nightly_linux_arm64.yml +++ b/.github/workflows/nightly_linux_arm64.yml @@ -2,7 +2,7 @@ on: #pull_request: workflow_dispatch: schedule: - - cron: '0 9 * * *' + - cron: "0 9 * * *" name: Nightly Release Linux arm64/aarch64 @@ -15,9 +15,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Update PATH to use zig 11 + - name: Update PATH to use zig 13 run: | - echo "PATH=/home/username/Downloads/zig-linux-aarch64-0.11.0:$PATH" >> $GITHUB_ENV + echo "PATH=/home/username/Downloads/zig-linux-aarch64-0.13.0:$PATH" >> $GITHUB_ENV - run: zig version @@ -28,15 +28,15 @@ jobs: run: cargo build --profile=release-with-lto --locked --bin roc --bin roc_language_server - name: get commit SHA - run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV + run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV - name: get date run: echo "DATE=$(date "+%Y-%m-%d")" >> $GITHUB_ENV - name: build file name env: - DATE: ${{ env.DATE }} - SHA: ${{ env.SHA }} + DATE: ${{ env.DATE }} + SHA: ${{ env.SHA }} run: echo "RELEASE_FOLDER_NAME=roc_nightly-linux_arm64-$DATE-$SHA" >> $GITHUB_ENV # this makes the roc binary a lot smaller @@ -49,6 +49,6 @@ jobs: - name: Upload roc nightly tar. Actually uploading to github releases has to be done manually. uses: actions/upload-artifact@v4 with: - name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz - path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz - retention-days: 4 + name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz + path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz + retention-days: 4 diff --git a/.github/workflows/nightly_linux_x86_64.yml b/.github/workflows/nightly_linux_x86_64.yml index d907c690f91..577d43392f8 100644 --- a/.github/workflows/nightly_linux_x86_64.yml +++ b/.github/workflows/nightly_linux_x86_64.yml @@ -15,9 +15,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Update PATH to use zig 11 + - name: Update PATH to use zig 13 run: | - echo "PATH=/home/big-ci-user/Downloads/zig-linux-x86_64-0.11.0:$PATH" >> $GITHUB_ENV + echo "PATH=/home/big-ci-user/Downloads/zig-linux-x86_64-0.13.0:$PATH" >> $GITHUB_ENV - run: zig version diff --git a/.github/workflows/nightly_macos_apple_silicon.yml b/.github/workflows/nightly_macos_apple_silicon.yml index eec45896770..ca4d9b814b6 100644 --- a/.github/workflows/nightly_macos_apple_silicon.yml +++ b/.github/workflows/nightly_macos_apple_silicon.yml @@ -8,7 +8,7 @@ name: Nightly Release macOS Apple Silicon env: RUST_BACKTRACE: 1 - LLVM_SYS_160_PREFIX: /opt/homebrew/opt/llvm@16 + LLVM_SYS_180_PREFIX: /opt/homebrew/opt/llvm@18 jobs: test-and-build: @@ -20,9 +20,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Update PATH to use zig 11 + - name: Update PATH to use zig 13 run: | - echo "PATH=/Users/m1ci/Downloads/zig-macos-aarch64-0.11.0:$PATH" >> $GITHUB_ENV + echo "PATH=/Users/m1ci/Downloads/zig-macos-aarch64-0.13.0:$PATH" >> $GITHUB_ENV - run: zig version diff --git a/.github/workflows/nightly_macos_x86_64.yml b/.github/workflows/nightly_macos_x86_64.yml index a3cc1898896..2a8efd2a4cc 100644 --- a/.github/workflows/nightly_macos_x86_64.yml +++ b/.github/workflows/nightly_macos_x86_64.yml @@ -1,62 +1,62 @@ on: - #pull_request: - workflow_dispatch: - schedule: - - cron: "0 9 * * *" # 9=9am utc+0 + #pull_request: + workflow_dispatch: + schedule: + - cron: "0 9 * * *" # 9=9am utc+0 name: Nightly Release macOS x86_64 env: - LLVM_SYS_160_PREFIX: /usr/local/opt/llvm@16 + LLVM_SYS_180_PREFIX: /usr/local/opt/llvm@18 jobs: - test-build-upload: - name: build, test, package and upload nightly release - runs-on: [self-hosted, macOS, X64] - timeout-minutes: 120 - steps: - - uses: actions/checkout@v4 - - - name: Update PATH to use zig 11 - run: | - echo "PATH=/Users/username1/Downloads/zig-macos-x86_64-0.11.0:$PATH" >> $GITHUB_ENV - - - run: zig version - - - name: write version to file - run: ./ci/write_version.sh - - - name: execute rust tests - run: cargo test --release --locked -- --skip opaque_wrap_function --skip gen_list::bool_list_literal --skip platform_switching_swift --skip swift_ui --skip gen_tags::phantom_polymorphic_record - # swift tests are skipped because of "Could not find or use auto-linked library 'swiftCompatibilityConcurrency'" on macos x86_64 CI machine - # this issue may be caused by using older versions of XCode - - - name: build release - run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_language_server - # target-cpu=x86-64 -> For maximal compatibility for all CPU's. - - - name: get commit SHA - run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV - - - name: get date - run: echo "DATE=$(date "+%Y-%m-%d")" >> $GITHUB_ENV - - - name: build file name - env: - DATE: ${{ env.DATE }} - SHA: ${{ env.SHA }} - run: echo "RELEASE_FOLDER_NAME=roc_nightly-macos_x86_64-$DATE-$SHA" >> $GITHUB_ENV - - # this makes the roc binary a lot smaller - - name: strip debug info - run: strip ./target/release-with-lto/roc - - - name: package release - run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }} - - - name: Upload artifact. Actually uploading to github releases has to be done manually. - uses: actions/upload-artifact@v4 - with: - name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz - path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz - retention-days: 4 + test-build-upload: + name: build, test, package and upload nightly release + runs-on: [self-hosted, macOS, X64] + timeout-minutes: 120 + steps: + - uses: actions/checkout@v4 + + - name: Update PATH to use zig 13 + run: | + echo "PATH=/Users/username1/Downloads/zig-macos-x86_64-0.13.0:$PATH" >> $GITHUB_ENV + + - run: zig version + + - name: write version to file + run: ./ci/write_version.sh + + - name: execute rust tests + run: cargo test --release --locked -- --skip opaque_wrap_function --skip gen_list::bool_list_literal --skip platform_switching_swift --skip swift_ui --skip gen_tags::phantom_polymorphic_record + # swift tests are skipped because of "Could not find or use auto-linked library 'swiftCompatibilityConcurrency'" on macos x86_64 CI machine + # this issue may be caused by using older versions of XCode + + - name: build release + run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_language_server + # target-cpu=x86-64 -> For maximal compatibility for all CPU's. + + - name: get commit SHA + run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV + + - name: get date + run: echo "DATE=$(date "+%Y-%m-%d")" >> $GITHUB_ENV + + - name: build file name + env: + DATE: ${{ env.DATE }} + SHA: ${{ env.SHA }} + run: echo "RELEASE_FOLDER_NAME=roc_nightly-macos_x86_64-$DATE-$SHA" >> $GITHUB_ENV + + # this makes the roc binary a lot smaller + - name: strip debug info + run: strip ./target/release-with-lto/roc + + - name: package release + run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }} + + - name: Upload artifact. Actually uploading to github releases has to be done manually. + uses: actions/upload-artifact@v4 + with: + name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz + path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz + retention-days: 4 diff --git a/.github/workflows/test_nightly_many_os.yml b/.github/workflows/test_nightly_many_os.yml index 3704e3e70e5..2f2cee96c0d 100644 --- a/.github/workflows/test_nightly_many_os.yml +++ b/.github/workflows/test_nightly_many_os.yml @@ -9,14 +9,14 @@ jobs: strategy: fail-fast: false matrix: - os: [ macos-13, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04] + os: [macos-13, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04] runs-on: ${{ matrix.os }} timeout-minutes: 90 steps: - uses: actions/checkout@v4 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.13.0 - name: Install zlib on macOS-13 if: matrix.os == 'macos-13' @@ -24,7 +24,7 @@ jobs: - name: get the latest release archive for linux (x86_64) if: startsWith(matrix.os, 'ubuntu') - run: | + run: | curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz - name: get the latest release archive for macos (x86_64) diff --git a/.github/workflows/ubuntu_x86_64.yml b/.github/workflows/ubuntu_x86_64.yml index 70199def20c..9e90ee8a41e 100644 --- a/.github/workflows/ubuntu_x86_64.yml +++ b/.github/workflows/ubuntu_x86_64.yml @@ -17,9 +17,9 @@ jobs: - name: Check for duplicate AUTHORS run: diff <(sort AUTHORS) <(sort AUTHORS | uniq) # The < operator treats a string as a file. diff 'succeeds' if no difference. - - name: Update PATH to use zig 11 + - name: Update PATH to use zig 13 run: | - echo "PATH=/home/big-ci-user/Downloads/zig-linux-x86_64-0.11.0:$PATH" >> $GITHUB_ENV + echo "PATH=/home/big-ci-user/Downloads/zig-linux-x86_64-0.13.0:$PATH" >> $GITHUB_ENV - run: zig version diff --git a/.github/workflows/windows_release_build.yml b/.github/workflows/windows_release_build.yml index 2cb14af3b2c..ec816b35f68 100644 --- a/.github/workflows/windows_release_build.yml +++ b/.github/workflows/windows_release_build.yml @@ -11,7 +11,7 @@ jobs: name: windows-release-build runs-on: windows-2022 env: - LLVM_SYS_160_PREFIX: C:\LLVM-16.0.6-win64 + LLVM_SYS_180_PREFIX: C:\LLVM-18.1.8-win64 timeout-minutes: 150 steps: @@ -21,10 +21,10 @@ jobs: - name: download and install zig run: | - curl.exe -f --output "C:\zig-windows-x86_64-0.11.0.zip" --url https://ziglang.org/download/0.11.0/zig-windows-x86_64-0.11.0.zip + curl.exe -f --output "C:\zig-windows-x86_64-0.13.0.zip" --url https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip cd C:\ - 7z x zig-windows-x86_64-0.11.0.zip - Add-Content $env:GITHUB_PATH "C:\zig-windows-x86_64-0.11.0\" + 7z x zig-windows-x86_64-0.13.0.zip + Add-Content $env:GITHUB_PATH "C:\zig-windows-x86_64-0.13.0\" - name: zig version run: zig version @@ -32,10 +32,10 @@ jobs: - name: install rust nightly 1.77.0 run: rustup install nightly-2024-02-03 - - name: set up llvm 16 + - name: set up llvm 18 run: | - curl.exe -f -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://github.com/roc-lang/llvm-package-windows/releases/download/v16.0.6/LLVM-16.0.6-win64.7z - 7z x LLVM-16.0.6-win64.7z -oC:\LLVM-16.0.6-win64 + curl.exe -f -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://github.com/roc-lang/llvm-package-windows/releases/download/v18.1.8/LLVM-18.1.8-win64.7z + 7z x LLVM-18.1.8-win64.7z -oC:\LLVM-18.1.8-win64 - name: cargo build release. run: cargo build --locked --release diff --git a/.github/workflows/windows_tests.yml b/.github/workflows/windows_tests.yml index 219ec9fbd69..e64a4e03515 100644 --- a/.github/workflows/windows_tests.yml +++ b/.github/workflows/windows_tests.yml @@ -1,62 +1,62 @@ -on: - workflow_call: - -name: windows - subset of tests - -env: - RUST_BACKTRACE: 1 - -jobs: - windows-test-subset: - name: windows-test-subset - runs-on: windows-2022 - env: - LLVM_SYS_160_PREFIX: C:\LLVM-16.0.6-win64 - - timeout-minutes: 150 - steps: - - uses: actions/checkout@v4 - - - run: Add-Content -Path "$env:GITHUB_ENV" -Value "GITHUB_RUNNER_CPU=$((Get-CimInstance Win32_Processor).Name)" - - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "rust-cache-windows-${{env.GITHUB_RUNNER_CPU}}" - - - name: download and install zig - run: | - curl.exe -f --output "C:\zig-windows-x86_64-0.11.0.zip" --url https://ziglang.org/download/0.11.0/zig-windows-x86_64-0.11.0.zip - cd C:\ - 7z x zig-windows-x86_64-0.11.0.zip - Add-Content $env:GITHUB_PATH "C:\zig-windows-x86_64-0.11.0\" - - - run: zig version - - - name: zig tests - run: | - cd crates\compiler\builtins\bitcode\ - zig build test - - - name: install rust nightly 1.77.0 - run: rustup install nightly-2024-02-03 - - - name: set up llvm 16 - run: | - curl.exe -f -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://github.com/roc-lang/llvm-package-windows/releases/download/v16.0.6/LLVM-16.0.6-win64.7z - 7z x LLVM-16.0.6-win64.7z -oC:\LLVM-16.0.6-win64 - - - name: Build tests --release without running. - run: cargo test --locked --release --no-run - - # Why are these tests not build with previous command? => fingerprint error. Use `CARGO_LOG=cargo::core::compiler::fingerprint=info` to investigate - - name: Build specific tests without running. - run: cargo test --locked --release --no-run -p roc_ident -p roc_region -p roc_collections -p roc_can -p roc_types -p roc_solve -p roc_mono -p roc_gen_dev -p roc_gen_wasm -p roc_serialize -p roc_linker -p roc_cli -p test_gen - - - name: Test setjmp/longjmp logic - run: cargo test-gen-dev --locked --release nat_alias && cargo test-gen-dev --locked --release a_crash - - - name: Run gen tests - run: cargo test-gen-llvm --locked --release gen_str - - - name: Actually run the tests. - run: cargo test --locked --release -p roc_ident -p roc_region -p roc_collections -p roc_can -p roc_types -p roc_solve -p roc_mono -p roc_gen_dev -p roc_gen_wasm -p roc_serialize -p roc_linker -p roc_cli +on: + workflow_call: + +name: windows - subset of tests + +env: + RUST_BACKTRACE: 1 + +jobs: + windows-test-subset: + name: windows-test-subset + runs-on: windows-2022 + env: + LLVM_SYS_180_PREFIX: C:\LLVM-18.1.8-win64 + + timeout-minutes: 150 + steps: + - uses: actions/checkout@v4 + + - run: Add-Content -Path "$env:GITHUB_ENV" -Value "GITHUB_RUNNER_CPU=$((Get-CimInstance Win32_Processor).Name)" + + - uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-cache-windows-${{env.GITHUB_RUNNER_CPU}}" + + - name: download and install zig + run: | + curl.exe -f --output "C:\zig-windows-x86_64-0.13.0.zip" --url https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip + cd C:\ + 7z x zig-windows-x86_64-0.13.0.zip + Add-Content $env:GITHUB_PATH "C:\zig-windows-x86_64-0.13.0\" + + - run: zig version + + - name: zig tests + run: | + cd crates\compiler\builtins\bitcode\ + zig build test + + - name: install rust nightly 1.77.0 + run: rustup install nightly-2024-02-03 + + - name: set up llvm 18 + run: | + curl.exe -f -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://github.com/roc-lang/llvm-package-windows/releases/download/v18.1.8/LLVM-18.1.8-win64.7z + 7z x LLVM-18.1.8-win64.7z -oC:\LLVM-18.1.8-win64 + + - name: Build tests --release without running. + run: cargo test --locked --release --no-run + + # Why are these tests not build with previous command? => fingerprint error. Use `CARGO_LOG=cargo::core::compiler::fingerprint=info` to investigate + - name: Build specific tests without running. + run: cargo test --locked --release --no-run -p roc_ident -p roc_region -p roc_collections -p roc_can -p roc_types -p roc_solve -p roc_mono -p roc_gen_dev -p roc_gen_wasm -p roc_serialize -p roc_linker -p roc_cli -p test_gen + + - name: Test setjmp/longjmp logic + run: cargo test-gen-dev --locked --release nat_alias && cargo test-gen-dev --locked --release a_crash + + - name: Run gen tests + run: cargo test-gen-llvm --locked --release gen_str + + - name: Actually run the tests. + run: cargo test --locked --release -p roc_ident -p roc_region -p roc_collections -p roc_can -p roc_types -p roc_solve -p roc_mono -p roc_gen_dev -p roc_gen_wasm -p roc_serialize -p roc_linker -p roc_cli diff --git a/.gitignore b/.gitignore index 04a6c6e09c2..20b80eb243b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,11 @@ # Ignore the following directories and file extensions target generated-docs + +# todo remove after upgrade to zig 0.13.0 zig-cache + +zig-out .zig-cache .direnv .envrc @@ -123,3 +127,5 @@ crates/glue/tests/fixtures/*/test_glue/ # ignore the zig glue files copied into test platforms **/*platform/glue/* +crates/cli/tests/test-projects/test-platform-effects-zig/glue +crates/cli/tests/test-projects/test-platform-simple-zig/glue diff --git a/.llvmenv b/.llvmenv index 946789e6195..7eae4e2e915 100644 --- a/.llvmenv +++ b/.llvmenv @@ -1 +1 @@ -16.0.0 +18.0.0 diff --git a/BUILDING_FROM_SOURCE.md b/BUILDING_FROM_SOURCE.md index 0a147acbf5b..18163e335e4 100644 --- a/BUILDING_FROM_SOURCE.md +++ b/BUILDING_FROM_SOURCE.md @@ -152,7 +152,7 @@ For Ubuntu and Debian: sudo apt -y install lsb-release software-properties-common gnupg wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh -./llvm.sh 16 +./llvm.sh 18 ``` If you use this script, you'll need to add `clang` to your `PATH`. @@ -169,7 +169,7 @@ There are also alternative installation options at -$env:LLVM_SYS_160_PREFIX = 'C:\Users\YOUR_USERNAME\Downloads\LLVM-16.0.6-win64' +$env:LLVM_SYS_180_PREFIX = 'C:\Users\YOUR_USERNAME\Downloads\LLVM-18.1.8-win64' ``` Once all that was done, `cargo build` ran successfully for Roc! diff --git a/Cargo.lock b/Cargo.lock index 2bb04e35c87..6d44a1b6355 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,6 +132,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + [[package]] name = "arrayref" version = "0.3.7" @@ -548,6 +554,13 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "copy_zig_glue" +version = "0.0.1" +dependencies = [ + "roc_test_utils_dir", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -1300,8 +1313,8 @@ checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inkwell" -version = "0.2.0" -source = "git+https://github.com/roc-lang/inkwell?branch=inkwell-llvm-16#d1a596391894933aa1f0f91ec87187e47917cf86" +version = "0.4.0" +source = "git+https://github.com/TheDan64/inkwell?rev=89e06af#89e06af9dd70dc5d6bc5ae42a2a03f680a367d37" dependencies = [ "either", "inkwell_internals", @@ -1313,8 +1326,8 @@ dependencies = [ [[package]] name = "inkwell_internals" -version = "0.8.0" -source = "git+https://github.com/roc-lang/inkwell?branch=inkwell-llvm-16#d1a596391894933aa1f0f91ec87187e47917cf86" +version = "0.9.0" +source = "git+https://github.com/TheDan64/inkwell?rev=89e06af#89e06af9dd70dc5d6bc5ae42a2a03f680a367d37" dependencies = [ "proc-macro2", "quote", @@ -1463,14 +1476,15 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "llvm-sys" -version = "160.1.3" +version = "180.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf51981ac0622b10fe4790763e3de1f3d68a0ee4222e03accaaab6731bd508d" +checksum = "778fa5fa02e32728e718f11eec147e6f134137399ab02fd2c13d32476337affa" dependencies = [ + "anyhow", "cc", "lazy_static", "libc", - "regex", + "regex-lite", "semver", ] @@ -2117,6 +2131,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2395,6 +2415,7 @@ dependencies = [ "clap 4.4.6", "cli_test_utils", "const_format", + "copy_zig_glue", "criterion", "distance", "errno", @@ -4416,6 +4437,7 @@ version = "0.0.1" dependencies = [ "bumpalo", "cli_test_utils", + "copy_zig_glue", "indoc", "roc_build", "roc_command_utils", diff --git a/Cargo.toml b/Cargo.toml index f827deb1deb..1fea315c526 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ "crates/wasm_module", "crates/wasm_interp", "crates/language_server", + "crates/copy_zig_glue", "crates/roc_std_heap", ] @@ -59,26 +60,8 @@ object = { version = "0.32.2", default-features = false, features = [ "read", "write", ] } -# NOTE: roc-lang/inkwell is a fork of TheDan64/inkwell which does not change anything. -# -# The reason for this fork is that the way Inkwell is designed, you have to use -# a particular branch (e.g. "llvm8-0") in Cargo.toml. That would be fine, except that -# breaking changes get pushed directly to that branch, which breaks our build -# without warning. -# -# We tried referencing a specific rev on TheDan64/inkwell directly (instead of branch), -# but although that worked locally, it did not work on GitHub Actions. (After a few -# hours of investigation, gave up trying to figure out why.) So this is the workaround: -# having an immutable tag on the roc-lang/inkwell fork which points to -# a particular "release" of Inkwell. -# -# When we want to update Inkwell, we can sync up roc-lang/inkwell to the latest -# commit of TheDan64/inkwell, push a new tag which points to the latest commit, -# change the tag value in this Cargo.toml to point to that tag, and `cargo update`. -# This way, GitHub Actions works and nobody's builds get broken. -# TODO: Switch this back to roc-lang/inkwell once it is updated -inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-16", features = [ - "llvm16-0", +inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "89e06af", features = [ + "llvm18-0", ] } arrayvec = "0.7.2" base64-url = "1.4.13" @@ -183,6 +166,7 @@ wyhash = "0.5.0" # INTERNAL DEPENDENCIES cli_test_utils = { path = "crates/cli_test_utils" } +copy_zig_glue = { path = "crates/copy_zig_glue" } roc_alias_analysis = { path = "crates/compiler/alias_analysis" } roc_bitcode = { path = "crates/compiler/builtins/bitcode" } roc_bitcode_bc = { path = "crates/compiler/builtins/bitcode/bc" } diff --git a/ci/benchmarks/prep_folder.sh b/ci/benchmarks/prep_folder.sh index 6c1c210afa4..86c3e5fca4d 100755 --- a/ci/benchmarks/prep_folder.sh +++ b/ci/benchmarks/prep_folder.sh @@ -9,6 +9,10 @@ set -euxo pipefail RUSTFLAGS="-C link-arg=-fuse-ld=lld -C target-cpu=native" BENCH_SUFFIX=$1 +# copy the builtin *.zig files into crates/cli/tests/benchmarks/platform +# TODO replace this with a zig package once we have zig 0.13.0 +cargo run --bin copy_zig_glue + cargo criterion -V cd crates/cli && cargo criterion --no-run && cd ../.. mkdir -p bench-folder/crates/cli/tests/benchmarks/ diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 1cad27f86aa..cd55c3dde96 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -43,6 +43,7 @@ sanitizers = ["roc_build/sanitizers"] [dependencies] +copy_zig_glue.workspace = true roc_build.workspace = true roc_builtins.workspace = true roc_can.workspace = true diff --git a/crates/cli/tests/benchmarks/platform/host.zig b/crates/cli/tests/benchmarks/platform/host.zig index b401f55cef0..b37056f9039 100644 --- a/crates/cli/tests/benchmarks/platform/host.zig +++ b/crates/cli/tests/benchmarks/platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -27,7 +27,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -99,23 +99,26 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } const Unit = extern struct {}; -pub fn main() !u8 { +pub export fn main() u8 { // The size might be zero; if so, make it at least 8 so that we don't have a nullptr const size = @max(@as(usize, @intCast(roc__mainForHost_1_exposed_size())), 8); - const raw_output = roc_alloc(@as(usize, @intCast(size)), @alignOf(u64)).?; - var output = @as([*]u8, @ptrCast(raw_output)); + const raw_output = roc_alloc(@as(usize, @intCast(size)), @alignOf(u64)) orelse { + std.log.err("Memory allocation failed", .{}); + return 1; + }; + const output = @as([*]u8, @ptrCast(raw_output)); defer { roc_dealloc(raw_output, @alignOf(u64)); @@ -136,7 +139,7 @@ fn call_the_closure(closure_data_pointer: [*]u8) void { // The size might be zero; if so, make it at least 8 so that we don't have a nullptr const size = @max(roc__mainForHost_0_result_size(), 8); const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable; - var output = @as([*]u8, @ptrCast(raw_output)); + const output = @as([*]u8, @ptrCast(raw_output)); defer { allocator.free(raw_output); diff --git a/crates/cli/tests/cli_tests.rs b/crates/cli/tests/cli_tests.rs index e55ea65cdf6..434b6ef4d87 100644 --- a/crates/cli/tests/cli_tests.rs +++ b/crates/cli/tests/cli_tests.rs @@ -76,6 +76,8 @@ mod cli_tests { #[test] #[cfg_attr(windows, ignore)] fn platform_switching_zig() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root("examples/platform-switching", "rocLovesZig.roc"), @@ -96,6 +98,8 @@ mod cli_tests { #[test] fn platform_switching_wasm() { + copy_zig_glue::initialize_zig_test_platforms(); + // this is a web assembly example, but we don't test with JS at the moment // so let's just check it for now let cli_check = ExecCli::new( @@ -113,6 +117,8 @@ mod cli_tests { ignore = "Flaky failure: Roc command failed with status ExitStatus(ExitStatus(3221225477))" )] fn fibonacci() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root("crates/cli/tests/test-projects/algorithms", "fibonacci.roc"), @@ -134,6 +140,8 @@ mod cli_tests { #[test] #[cfg_attr(windows, ignore)] fn quicksort() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root("crates/cli/tests/test-projects/algorithms", "quicksort.roc"), @@ -184,6 +192,8 @@ mod cli_tests { #[cfg_attr(windows, ignore)] // tea = The Elm Architecture fn terminal_ui_tea() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root("crates/cli/tests/test-projects/tui", "main.roc"), @@ -266,6 +276,8 @@ mod cli_tests { #[test] #[cfg_attr(windows, ignore)] fn multiple_exposed() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root( @@ -461,6 +473,8 @@ mod cli_tests { /// Build the platform host once for all tests in this module fn build_platform_host() { BUILD_PLATFORM_HOST.call_once(|| { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root( @@ -800,6 +814,8 @@ mod cli_tests { /// Build the platform host once for all tests in this module fn build_platform_host() { BUILD_PLATFORM_HOST.call_once(|| { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root( @@ -1031,6 +1047,8 @@ mod cli_tests { /// Build the platform host once for all tests in this module fn build_platform_host() { BUILD_PLATFORM_HOST.call_once(|| { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root("crates/cli/tests/benchmarks/platform", "app.roc"), @@ -1318,6 +1336,8 @@ mod cli_tests { #[cfg_attr(windows, ignore)] /// this tests that a platform can correctly import a package fn platform_requires_pkg() { + copy_zig_glue::initialize_zig_test_platforms(); + let cli_build = ExecCli::new( CMD_BUILD, file_from_root( diff --git a/crates/cli/tests/test-projects/algorithms/fibonacci-platform/host.zig b/crates/cli/tests/test-projects/algorithms/fibonacci-platform/host.zig index 1747815c594..47e33d8bbd4 100644 --- a/crates/cli/tests/test-projects/algorithms/fibonacci-platform/host.zig +++ b/crates/cli/tests/test-projects/algorithms/fibonacci-platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -25,7 +25,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -97,13 +97,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } diff --git a/crates/cli/tests/test-projects/algorithms/quicksort-platform/host.zig b/crates/cli/tests/test-projects/algorithms/quicksort-platform/host.zig index 62df6fe018c..06b015c6907 100644 --- a/crates/cli/tests/test-projects/algorithms/quicksort-platform/host.zig +++ b/crates/cli/tests/test-projects/algorithms/quicksort-platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -22,7 +22,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -94,13 +94,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } @@ -125,14 +125,14 @@ pub export fn main() u8 { numbers[i] = @mod(@as(i64, @intCast(i)), 12); } - var roc_list = RocList{ .elements = numbers, .length = NUM_NUMS, .capacity = NUM_NUMS }; + const roc_list = RocList{ .elements = numbers, .length = NUM_NUMS, .capacity = NUM_NUMS }; // actually call roc to populate the callresult const callresult: RocList = roc__mainForHost_1_exposed(roc_list); // stdout the result const length = @min(20, callresult.length); - var result = callresult.elements[0..length]; + const result = callresult.elements[0..length]; for (result, 0..) |x, i| { if (i == 0) { diff --git a/crates/cli/tests/test-projects/multiple_exposed/platform/host.zig b/crates/cli/tests/test-projects/multiple_exposed/platform/host.zig index dbb8a0d7e18..5ab48472ced 100644 --- a/crates/cli/tests/test-projects/multiple_exposed/platform/host.zig +++ b/crates/cli/tests/test-projects/multiple_exposed/platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -24,7 +24,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -96,13 +96,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } diff --git a/crates/cli/tests/test-projects/platform_requires_pkg/platform/host.zig b/crates/cli/tests/test-projects/platform_requires_pkg/platform/host.zig index 63933b3615e..0d8574224a5 100644 --- a/crates/cli/tests/test-projects/platform_requires_pkg/platform/host.zig +++ b/crates/cli/tests/test-projects/platform_requires_pkg/platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -17,7 +17,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -87,14 +87,14 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_send_signal, .{ .name = "roc_send_signal", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_send_signal, .{ .name = "roc_send_signal", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } @@ -105,7 +105,7 @@ extern fn roc__mainForHost_1_exposed_generic(*RocStr) void; const Unit = extern struct {}; -pub fn main() u8 { +pub export fn main() u8 { const stdout = std.io.getStdOut().writer(); // actually call roc to populate the callresult diff --git a/crates/cli/tests/test-projects/test-platform-effects-zig/host.zig b/crates/cli/tests/test-projects/test-platform-effects-zig/host.zig index 47dddde9c0d..4380a947223 100644 --- a/crates/cli/tests/test-projects/test-platform-effects-zig/host.zig +++ b/crates/cli/tests/test-projects/test-platform-effects-zig/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -28,7 +28,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -95,13 +95,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } @@ -113,7 +113,7 @@ pub export fn main() u8 { // NOTE the return size can be zero, which will segfault. Always allocate at least 8 bytes const size = @max(8, @as(usize, @intCast(roc__mainForHost_1_exposed_size()))); const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable; - var output = @as([*]u8, @ptrCast(raw_output)); + const output = @as([*]u8, @ptrCast(raw_output)); defer { allocator.free(raw_output); diff --git a/crates/cli/tests/test-projects/test-platform-simple-zig/host.zig b/crates/cli/tests/test-projects/test-platform-simple-zig/host.zig index 707bfeb4b26..d621b10bf34 100644 --- a/crates/cli/tests/test-projects/test-platform-simple-zig/host.zig +++ b/crates/cli/tests/test-projects/test-platform-simple-zig/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -79,13 +79,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } diff --git a/crates/cli/tests/test-projects/tui/platform/host.zig b/crates/cli/tests/test-projects/tui/platform/host.zig index 063336b8fd9..b3e6da41e58 100644 --- a/crates/cli/tests/test-projects/tui/platform/host.zig +++ b/crates/cli/tests/test-projects/tui/platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -25,7 +25,7 @@ extern fn roc__mainForHost_0_result_size() i64; fn allocate_model(allocator: *Allocator) MutModel { const size = roc__mainForHost_0_result_size(); const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable; - var output = @as([*]u8, @ptrCast(raw_output)); + const output = @as([*]u8, @ptrCast(raw_output)); return output; } @@ -86,7 +86,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -158,13 +158,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } diff --git a/crates/compiler/build/src/lib.rs b/crates/compiler/build/src/lib.rs index 8cc3304900f..93524ee3a82 100644 --- a/crates/compiler/build/src/lib.rs +++ b/crates/compiler/build/src/lib.rs @@ -3,5 +3,6 @@ // See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod link; +pub mod llvm_passes; pub mod program; pub mod target; diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 508f57ed569..91ca9d1519a 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -80,21 +80,6 @@ pub fn get_relative_path(sub_path: &Path) -> Option { None } -fn find_zig_glue_path() -> PathBuf { - // First try using a lib path relative to the executable. - let path = get_relative_path(Path::new("lib/glue.zig")); - if let Some(path) = path { - return path; - } - // Fallback on the repo path relative to the executable location. - let path = get_relative_path(Path::new("crates/compiler/builtins/bitcode/src/glue.zig")); - if let Some(path) = path { - return path; - } - - internal_error!("cannot find `glue.zig`. Check the source code in find_zig_glue_path() to show all the paths I tried.") -} - fn find_wasi_libc_path() -> PathBuf { // This path is available when built and run from source // Environment variable defined in wasi-libc-sys/build.rs @@ -148,10 +133,6 @@ pub fn build_zig_host_native( zig_cmd.args([ zig_host_src, &format!("-femit-bin={emit_bin}"), - "--mod", - &format!("glue::{}", find_zig_glue_path().to_str().unwrap()), - "--deps", - "glue", // include libc "-lc", // cross-compile? @@ -220,10 +201,6 @@ pub fn build_zig_host_native( zig_cmd.args(&[ zig_host_src, &format!("-femit-bin={}", emit_bin), - "--mod", - &format!("glue::{}", find_zig_glue_path().to_str().unwrap()), - "--deps", - "glue", // include the zig runtime // "-fcompiler-rt", compiler-rt causes segfaults on windows; investigate why // include libc @@ -267,15 +244,8 @@ pub fn build_zig_host_wasm32( "build-obj", zig_host_src, emit_bin, - "--mod", - &format!("glue::{}", find_zig_glue_path().to_str().unwrap()), - "--deps", - "glue", // include the zig runtime // "-fcompiler-rt", - // include libc - "--library", - "c", "-target", "wasm32-wasi", // "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli/tests/benchmarks/platform/host.ll", @@ -1206,10 +1176,6 @@ fn link_wasm32( &format!("-femit-bin={}", output_path.to_str().unwrap()), "-target", "wasm32-wasi-musl", - "--mod", - &format!("glue::{}", find_zig_glue_path().to_str().unwrap()), - "--deps", - "glue", "-fstrip", "-O", "ReleaseSmall", @@ -1237,10 +1203,6 @@ fn link_windows( &format!("-femit-bin={}", output_path.to_str().unwrap()), "-target", "native", - "--mod", - &format!("glue::{}", find_zig_glue_path().to_str().unwrap()), - "--deps", - "glue", "-O", "Debug", "-dynamic", @@ -1389,7 +1351,7 @@ fn run_build_command(mut command: Command, file_to_build: &str, flaky_fail_count if !cmd_output.status.success() { match std::str::from_utf8(&cmd_output.stderr) { Ok(stderr) => { - // flaky error seen on macos 12 apple silicon, related to https://github.com/ziglang/zig/issues/9711 + // flaky error seen on macos 12 apple silicon, related to https://github.com/ziglang/zig/issues/20501 if stderr.contains("unable to save cached ZIR code") { if flaky_fail_counter < max_flaky_fail_count { run_build_command(command, file_to_build, flaky_fail_counter + 1) diff --git a/crates/compiler/build/src/llvm_passes.rs b/crates/compiler/build/src/llvm_passes.rs new file mode 100644 index 00000000000..878d06cbf07 --- /dev/null +++ b/crates/compiler/build/src/llvm_passes.rs @@ -0,0 +1,83 @@ +use roc_error_macros::internal_error; +use roc_mono::ir::OptLevel; +use roc_target::Target; +use std::path::Path; + +// generated using "opt --passes="default" --print-pipeline-passes example.ll" +// +// we also include a "globaldce" pass at the beginning of each pipeline here, which is required +// to prevent bugs with the surgical linker, and also improves the build time. +pub fn get_llvm_passes_str(opt_level: OptLevel) -> &'static str { + match opt_level { + OptLevel::Development | OptLevel::Normal => { + "globaldce,always-inline,coro-cond(coro-early,cgscc(coro-split),coro-cleanup,globaldce),function(annotation-remarks),verify" + }, + OptLevel::Size => { + "globaldce,annotation2metadata,forceattrs,inferattrs,coro-early,function(lower-expect,simplifycfg,sroa,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function(mem2reg,instcombine,simplifycfg),always-inline,require,function(invalidate),require,cgscc(devirt<4>(inline,function-attrs,function(sroa,early-cse,speculative-execution,jump-threading,correlated-propagation,simplifycfg,instcombine,aggressive-instcombine,tailcallelim,simplifycfg,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm,loop-rotate,licm,simple-loop-unswitch),simplifycfg,instcombine,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa,vector-combine,mldst-motion,gvn<>,sccp,bdce,instcombine,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm),coro-elide,simplifycfg,instcombine),function-attrs,function(require),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function(float2int,lower-constant-intrinsics,loop(loop-rotate,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize,infer-alignment,loop-load-elim,instcombine,simplifycfg,vector-combine,instcombine,loop-unroll,transform-warning,sroa,infer-alignment,instcombine,loop-mssa(licm),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify" + }, + OptLevel::Optimize => { + "globaldce,annotation2metadata,forceattrs,inferattrs,coro-early,function(lower-expect,simplifycfg,sroa,early-cse<>,callsite-splitting),openmp-opt,ipsccp,called-value-propagation,globalopt,function(mem2reg,instcombine,simplifycfg),always-inline,require,function(invalidate),require,cgscc(devirt<4>(inline,function-attrs,argpromotion,openmp-opt-cgscc,function(sroa,early-cse,speculative-execution,jump-threading,correlated-propagation,simplifycfg,instcombine,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm,loop-rotate,licm,simple-loop-unswitch),simplifycfg,instcombine,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa,vector-combine,mldst-motion,gvn<>,sccp,bdce,instcombine,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm),coro-elide,simplifycfg,instcombine),function-attrs,function(require),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function(float2int,lower-constant-intrinsics,chr,loop(loop-rotate,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize,infer-alignment,loop-load-elim,instcombine,simplifycfg,slp-vectorizer,vector-combine,instcombine,loop-unroll,transform-warning,sroa,infer-alignment,instcombine,loop-mssa(licm),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify" + }, + } +} + +pub fn optimize_llvm_ir( + env: &roc_gen_llvm::llvm::build::Env, + target: Target, + opt_level: OptLevel, + emit_debug_info: bool, + ll_file_path: &Path, +) { + env.dibuilder.finalize(); + + if !emit_debug_info { + env.module.strip_debug_info(); + } + + // TODO: double check how much time is spent verifying here and below. + // For real compilation, we may not want to pay the cost. + + // Verify the module before optimizing + if let Err(errors) = env.module.verify() { + // write the ll code to a file, so we can modify it + env.module.print_to_file(ll_file_path).unwrap(); + + internal_error!( + "😱 LLVM errors when defining module; I wrote the full LLVM IR to {:?}\n\n {}", + ll_file_path, + errors.to_string(), + ); + } + + // Uncomment this to see the module's optimized LLVM instruction output: + // env.module.print_to_stderr(); + + let inkwell_opt_level = crate::target::convert_opt_level(opt_level); + let inkwell_llvm_passes = get_llvm_passes_str(opt_level); + let inkwell_target_machine = + crate::target::target_machine(target, inkwell_opt_level, inkwell::targets::RelocMode::PIC) + .unwrap_or_else(|| internal_error!("invalid target machine")); + + env.module + .run_passes( + inkwell_llvm_passes, + &inkwell_target_machine, + inkwell::passes::PassBuilderOptions::create(), + ) + .unwrap_or_else(|e| internal_error!("invalid llvm optimization passes: {:?}", e)); + + // Verify the module after optimizing + if let Err(errors) = env.module.verify() { + // write the ll code to a file, so we can modify it + env.module.print_to_file(ll_file_path).unwrap(); + + internal_error!( + "😱 LLVM errors when optimizing module; I wrote the full LLVM IR to {:?}\n\n {}", + ll_file_path, + errors.to_string(), + ); + } + + // Uncomment this to see the module's optimized LLVM instruction output: + // env.module.print_to_stderr(); +} diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 2389edef1bd..ffdb4710ea0 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -204,7 +204,6 @@ fn gen_from_mono_module_llvm<'a>( let builder = context.create_builder(); let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module); - let (mpm, _fpm) = roc_gen_llvm::llvm::build::construct_optimization_passes(module, opt_level); // Compile and add all the Procs before adding main let env = roc_gen_llvm::llvm::build::Env { @@ -264,31 +263,7 @@ fn gen_from_mono_module_llvm<'a>( let generate_final_ir = all_code_gen_start.elapsed(); let code_gen_object_start = Instant::now(); - env.dibuilder.finalize(); - - if !emit_debug_info { - module.strip_debug_info(); - } - - // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); - - mpm.run_on(module); - - // Verify the module - if let Err(errors) = env.module.verify() { - // write the ll code to a file, so we can modify it - env.module.print_to_file(&app_ll_file).unwrap(); - - internal_error!( - "😱 LLVM errors when defining module; I wrote the full LLVM IR to {:?}\n\n {}", - app_ll_file, - errors.to_string(), - ); - } - - // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); + crate::llvm_passes::optimize_llvm_ir(&env, target, opt_level, emit_debug_info, &app_ll_file); let gen_sanitizers = cfg!(feature = "sanitizers") && std::env::var("ROC_SANITIZERS").is_ok(); let memory_buffer = if fuzz || gen_sanitizers { diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 6b46aedeb8b..9234b90e193 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -60,7 +60,7 @@ pub fn arch_str(target: Target) -> &'static str { roc_target::Architecture::X86_32 if cfg!(feature = "target-x86") => "x86", roc_target::Architecture::Aarch64 if cfg!(feature = "target-aarch64") => "aarch64", roc_target::Architecture::Aarch32 if cfg!(feature = "target-arm") => "arm", - roc_target::Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32", + roc_target::Architecture::Wasm32 if cfg!(feature = "target-wasm32") => "wasm32", _ => internal_error!( "TODO gracefully handle unsupported target architecture: {:?}", target.architecture() diff --git a/crates/compiler/builtins/bitcode/benchmark/dec.zig b/crates/compiler/builtins/benchmark-dec.zig similarity index 86% rename from crates/compiler/builtins/bitcode/benchmark/dec.zig rename to crates/compiler/builtins/benchmark-dec.zig index 1793ac2e52e..2173f43a1de 100644 --- a/crates/compiler/builtins/bitcode/benchmark/dec.zig +++ b/crates/compiler/builtins/benchmark-dec.zig @@ -2,8 +2,8 @@ const std = @import("std"); const time = std.time; const Timer = time.Timer; -const RocStr = @import("../src/str.zig").RocStr; -const RocDec = @import("../src/dec.zig").RocDec; +const RocStr = @import("./bitcode/src/str.zig").RocStr; +const RocDec = @import("./bitcode/src/dec.zig").RocDec; fn roc_alloc(_: usize, _: u32) callconv(.C) ?*anyopaque { @panic("Not needed for dec benchmark"); @@ -16,14 +16,22 @@ fn roc_dbg(_: *anyopaque, _: *anyopaque, _: *anyopaque) callconv(.C) void { } comptime { - @export(roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong }); - @export(roc_panic, .{ .name = "roc_panic", .linkage = .Strong }); - @export(roc_dbg, .{ .name = "roc_dbg", .linkage = .Strong }); + @export(roc_alloc, .{ .name = "roc_alloc", .linkage = .strong }); + @export(roc_panic, .{ .name = "roc_panic", .linkage = .strong }); + @export(roc_dbg, .{ .name = "roc_dbg", .linkage = .strong }); } var timer: Timer = undefined; -pub fn main() !void { +pub export fn main() u8 { + run_tests() catch |err| { + std.debug.print("Error: {}\n", .{err}); + return 1; + }; + return 0; +} + +fn run_tests() !void { const stdout = std.io.getStdOut().writer(); try stdout.print("Warning: Timer seems to step in units of 41ns\n\n", .{}); timer = try Timer.start(); @@ -35,11 +43,15 @@ pub fn main() !void { // This number are very close to 1 to avoid over and underflow. const f1 = 1.00123; - const dec1 = RocDec.fromF64(f1).?; + const dec1 = RocDec.fromF64(f1) orelse { + @panic("Failed to create RocDec from f64"); + }; // `asin` and `acos` have a limited range, so they will use this value. const f2 = 0.00130000847; - const dec2 = RocDec.fromF64(f2).?; + const dec2 = RocDec.fromF64(f2) orelse { + @panic("Failed to create RocDec from f64"); + }; try stdout.print("Dec:\n", .{}); try stdout.print("{} additions took ", .{add_sub_n}); @@ -126,11 +138,11 @@ fn avg_runs(comptime T: type, comptime n: usize, comptime op: fn (T, T) T, v: T) var i: usize = 0; while (i < warmups + repeats) : (i += 1) { // Never inline run to ensure it doesn't optimize for the value of `v`. - runs[i] = callWrapper(u64, .never_inline, run, .{ T, n, op, v }); + runs[i] = @call(.never_inline, run, .{ T, n, op, v }); } - var real_runs = runs[warmups..runs.len]; - std.sort.sort(u64, real_runs, {}, comptime std.sort.asc(u64)); + const real_runs = runs[warmups..runs.len]; + std.sort.insertion(u64, real_runs, {}, comptime std.sort.asc(u64)); const median = real_runs[real_runs.len / 2]; const highest = real_runs[real_runs.len - 1]; @@ -146,19 +158,19 @@ fn run(comptime T: type, comptime n: usize, comptime op: fn (T, T) T, v: T) u64 // Split into outer and inner loop to avoid breaking comptime. const max_inline = 100; - comptime var outer = n / max_inline; - comptime var inner = std.math.min(n, max_inline); + const outer = n / max_inline; + const inner = @min(n, max_inline); var i: usize = 0; while (i < outer) : (i += 1) { comptime var j = 0; inline while (j < inner) : (j += 1) { - a = callWrapper(T, .always_inline, op, .{ a, v }); + a = @call(.always_inline, op, .{ a, v }); } } const rem = n % max_inline; - comptime var j = 0; + const j = 0; inline while (j < rem) : (j += 1) { - a = callWrapper(T, .always_inline, op, .{ a, v }); + a = @call(.always_inline, op, .{ a, v }); } // Clobber `a` to avoid removal as dead code. @@ -170,11 +182,6 @@ fn run(comptime T: type, comptime n: usize, comptime op: fn (T, T) T, v: T) u64 return timer.read(); } -// This is needed to work around a bug with using `@call` in loops. -inline fn callWrapper(comptime T: type, call_modifier: anytype, comptime func: anytype, params: anytype) T { - return @call(.{ .modifier = call_modifier }, func, params); -} - fn addF64(x: f64, y: f64) f64 { return x + y; } diff --git a/crates/compiler/builtins/bitcode/benchmark.sh b/crates/compiler/builtins/benchmark.sh similarity index 61% rename from crates/compiler/builtins/bitcode/benchmark.sh rename to crates/compiler/builtins/benchmark.sh index 410188d4519..89f66b0bc4c 100755 --- a/crates/compiler/builtins/bitcode/benchmark.sh +++ b/crates/compiler/builtins/benchmark.sh @@ -3,5 +3,5 @@ # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ set -euxo pipefail -zig build-exe benchmark/dec.zig -O ReleaseFast --main-pkg-path . -./dec +zig build-exe benchmark-dec.zig -O ReleaseFast +./benchmark-dec diff --git a/crates/compiler/builtins/bitcode/bc/build.rs b/crates/compiler/builtins/bitcode/bc/build.rs index 603214ae2d1..035e2bc2e36 100644 --- a/crates/compiler/builtins/bitcode/bc/build.rs +++ b/crates/compiler/builtins/bitcode/bc/build.rs @@ -19,7 +19,7 @@ fn main() { // dunce can be removed once ziglang/zig#5109 is fixed let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap().join(".."); - // workaround for github.com/ziglang/zig/issues/9711 + // workaround for github.com/ziglang/zig/issues/20501 #[cfg(target_os = "macos")] let zig_cache_dir = tempdir().expect("Failed to create temp directory for zig cache"); #[cfg(target_os = "macos")] @@ -69,9 +69,9 @@ fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) { let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path"); println!("Compiling 64-bit bitcode to: {dest_bc_64bit}"); - // workaround for github.com/ziglang/zig/issues/9711 + // workaround for github.com/ziglang/zig/issues/20501 #[cfg(target_os = "macos")] - let _ = fs::remove_dir_all("./zig-cache"); + let _ = fs::remove_dir_all("./.zig-cache"); let mut zig_cmd = zig(); @@ -126,7 +126,7 @@ fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> { let entry = entry?; let path_buf = entry.path(); if path_buf.is_dir() { - if !path_buf.ends_with("zig-cache") { + if !path_buf.ends_with(".zig-cache") { get_zig_files(&path_buf, cb).unwrap(); } } else { diff --git a/crates/compiler/builtins/bitcode/build.rs b/crates/compiler/builtins/bitcode/build.rs index d84fbcccca4..9d55cae56a7 100644 --- a/crates/compiler/builtins/bitcode/build.rs +++ b/crates/compiler/builtins/bitcode/build.rs @@ -19,7 +19,7 @@ fn main() { // dunce can be removed once ziglang/zig#5109 is fixed let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap(); - // workaround for github.com/ziglang/zig/issues/9711 + // workaround for github.com/ziglang/zig/issues/20501 #[cfg(target_os = "macos")] let zig_cache_dir = tempdir().expect("Failed to create temp directory for zig cache"); #[cfg(target_os = "macos")] @@ -70,6 +70,10 @@ fn generate_object_file(bitcode_path: &Path, zig_object: &str, object_file_name: println!("Compiling zig object `{zig_object}` to: {src_obj}"); + // workaround for github.com/ziglang/zig/issues/20501 + #[cfg(target_os = "macos")] + let _ = fs::remove_dir_all("./.zig-cache"); + let mut zig_cmd = zig(); zig_cmd @@ -119,7 +123,7 @@ fn copy_zig_builtins_to_target_dir(bitcode_path: &Path) { }); } -// recursively copy all the .zig files from this directory, but do *not* recurse into zig-cache/ +// recursively copy all the .zig files from this directory, but do *not* recurse into .zig-cache/ fn cp_unless_zig_cache(src_dir: &Path, target_dir: &Path) -> io::Result<()> { // Make sure the destination directory exists before we try to copy anything into it. std::fs::create_dir_all(target_dir).unwrap_or_else(|err| { @@ -146,8 +150,8 @@ fn cp_unless_zig_cache(src_dir: &Path, target_dir: &Path) -> io::Result<()> { err ); }); - } else if src_path.is_dir() && src_filename != "zig-cache" { - // Recursively copy all directories except zig-cache + } else if src_path.is_dir() && src_filename != ".zig-cache" { + // Recursively copy all directories except .zig-cache cp_unless_zig_cache(&src_path, &target_dir.join(src_filename))?; } } @@ -199,7 +203,7 @@ fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> { let entry = entry?; let path_buf = entry.path(); if path_buf.is_dir() { - if !path_buf.ends_with("zig-cache") { + if !path_buf.ends_with(".zig-cache") { get_zig_files(&path_buf, cb).unwrap(); } } else { diff --git a/crates/compiler/builtins/bitcode/build.zig b/crates/compiler/builtins/bitcode/build.zig index f9a373327d9..fb76a5de619 100644 --- a/crates/compiler/builtins/bitcode/build.zig +++ b/crates/compiler/builtins/bitcode/build.zig @@ -11,9 +11,7 @@ pub fn build(b: *Build) void { const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast }); // Options - const fallback_main_path = "./src/main.zig"; - const main_path_desc = b.fmt("Override path to main.zig. Used by \"ir\" and \"test\". Defaults to \"{s}\". ", .{fallback_main_path}); - const main_path = .{ .path = b.option([]const u8, "main-path", main_path_desc) orelse fallback_main_path }; + const main_path = b.path("src/main.zig"); // Tests const main_tests = b.addTest(.{ .root_source_file = main_path, .link_libc = true }); @@ -21,17 +19,36 @@ pub fn build(b: *Build) void { test_step.dependOn(&b.addRunArtifact(main_tests).step); // Targets - const host_target = b.standardTargetOptions(.{ - .default_target = CrossTarget{ - .cpu_model = .baseline, - .os_tag = builtin.os.tag, - }, + const host_target = b.resolveTargetQuery(.{ + .cpu_model = .baseline, + .os_tag = builtin.os.tag, + }); + const linux32_target = b.resolveTargetQuery(.{ + .cpu_arch = std.Target.Cpu.Arch.x86, + .os_tag = std.Target.Os.Tag.linux, + .abi = std.Target.Abi.none, + }); + const linux_x64_target = b.resolveTargetQuery(.{ + .cpu_arch = std.Target.Cpu.Arch.x86_64, + .os_tag = std.Target.Os.Tag.linux, + .abi = std.Target.Abi.none, + }); + const linux_aarch64_target = b.resolveTargetQuery(.{ + .cpu_arch = std.Target.Cpu.Arch.aarch64, + .os_tag = std.Target.Os.Tag.linux, + .abi = std.Target.Abi.none, + }); + const windows64_target = b.resolveTargetQuery(.{ + .cpu_arch = std.Target.Cpu.Arch.x86_64, + .os_tag = std.Target.Os.Tag.windows, + .abi = std.Target.Abi.none, + }); + const wasm32_target = b.resolveTargetQuery(.{ + // 32-bit wasm + .cpu_arch = std.Target.Cpu.Arch.wasm32, + .os_tag = std.Target.Os.Tag.freestanding, + .abi = std.Target.Abi.none, }); - const linux32_target = makeLinux32Target(); - const linux_x64_target = makeLinuxX64Target(); - const linux_aarch64_target = makeLinuxAarch64Target(); - const windows64_target = makeWindows64Target(); - const wasm32_target = makeWasm32Target(); // LLVM IR generateLlvmIrFile(b, mode, host_target, main_path, "ir", "builtins-host"); @@ -51,15 +68,16 @@ pub fn build(b: *Build) void { fn generateLlvmIrFile( b: *Build, mode: std.builtin.Mode, - target: CrossTarget, + target: std.Build.ResolvedTarget, main_path: LazyPath, step_name: []const u8, object_name: []const u8, ) void { - const obj = b.addObject(.{ .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true }); - obj.strip = true; - obj.disable_stack_probing = true; - if (target.cpu_arch != .wasm32) + const obj = b.addObject(.{ .strip = true, .pic = true, .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true }); + + obj.root_module.stack_check = false; + + if (target.result.cpu.arch != std.Target.Cpu.Arch.wasm32) obj.bundle_compiler_rt = true; // Generating the bin seems required to get zig to generate the llvm ir. @@ -83,23 +101,24 @@ fn generateLlvmIrFile( fn generateObjectFile( b: *Build, mode: std.builtin.Mode, - target: CrossTarget, + target: std.Build.ResolvedTarget, main_path: LazyPath, step_name: []const u8, object_name: []const u8, ) void { - const obj = b.addObject(.{ .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true }); - obj.strip = true; + const is_wasm = target.result.cpu.arch == .wasm32 or target.result.cpu.arch == .wasm64; + const obj = b.addObject(.{ .strip = true, .pic = !is_wasm, .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true }); + obj.link_function_sections = true; - obj.force_pic = true; - obj.disable_stack_probing = true; - if (target.cpu_arch != .wasm32) + obj.root_module.stack_check = false; + + if (!is_wasm) obj.bundle_compiler_rt = true; const obj_file = obj.getEmittedBin(); const suffix = - if (target.os_tag == .windows) + if (target.result.os.tag == std.Target.Os.Tag.windows) "obj" else "o"; @@ -110,54 +129,3 @@ fn generateObjectFile( obj_step.dependOn(&install.step); b.getInstallStep().dependOn(obj_step); } - -fn makeLinux32Target() CrossTarget { - var target = CrossTarget.parse(.{}) catch unreachable; - - target.cpu_arch = std.Target.Cpu.Arch.x86; - target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.none; - - return target; -} - -fn makeLinuxAarch64Target() CrossTarget { - var target = CrossTarget.parse(.{}) catch unreachable; - - target.cpu_arch = std.Target.Cpu.Arch.aarch64; - target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.none; - - return target; -} - -fn makeLinuxX64Target() CrossTarget { - var target = CrossTarget.parse(.{}) catch unreachable; - - target.cpu_arch = std.Target.Cpu.Arch.x86_64; - target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.none; - - return target; -} - -fn makeWindows64Target() CrossTarget { - var target = CrossTarget.parse(.{}) catch unreachable; - - target.cpu_arch = std.Target.Cpu.Arch.x86_64; - target.os_tag = std.Target.Os.Tag.windows; - target.abi = std.Target.Abi.none; - - return target; -} - -fn makeWasm32Target() CrossTarget { - var target = CrossTarget.parse(.{}) catch unreachable; - - // 32-bit wasm - target.cpu_arch = std.Target.Cpu.Arch.wasm32; - target.os_tag = std.Target.Os.Tag.freestanding; - target.abi = std.Target.Abi.none; - - return target; -} diff --git a/crates/compiler/builtins/bitcode/src/dec.zig b/crates/compiler/builtins/bitcode/src/dec.zig index 8a3f91124a0..53a4cb3df77 100644 --- a/crates/compiler/builtins/bitcode/src/dec.zig +++ b/crates/compiler/builtins/bitcode/src/dec.zig @@ -32,7 +32,7 @@ pub const RocDec = extern struct { } pub fn fromF64(num: f64) ?RocDec { - var result: f64 = num * comptime @as(f64, @floatFromInt(one_point_zero_i128)); + const result: f64 = num * comptime @as(f64, @floatFromInt(one_point_zero_i128)); if (result > comptime @as(f64, @floatFromInt(math.maxInt(i128)))) { return null; @@ -42,7 +42,7 @@ pub const RocDec = extern struct { return null; } - var ret: RocDec = .{ .num = @as(i128, @intFromFloat(result)) }; + const ret: RocDec = .{ .num = @as(i128, @intFromFloat(result)) }; return ret; } @@ -61,13 +61,13 @@ pub const RocDec = extern struct { const roc_str_slice = roc_str.asSlice(); - var is_negative: bool = roc_str_slice[0] == '-'; - var initial_index: usize = if (is_negative) 1 else 0; + const is_negative: bool = roc_str_slice[0] == '-'; + const initial_index: usize = if (is_negative) 1 else 0; var point_index: ?usize = null; var index: usize = initial_index; while (index < length) { - var byte: u8 = roc_str_slice[index]; + const byte: u8 = roc_str_slice[index]; if (byte == '.' and point_index == null) { point_index = index; index += 1; @@ -85,20 +85,20 @@ pub const RocDec = extern struct { if (point_index) |pi| { before_str_length = pi; - var after_str_len = (length - 1) - pi; + const after_str_len = (length - 1) - pi; if (after_str_len > decimal_places) { // TODO: runtime exception for too many decimal places! return null; } - var diff_decimal_places = decimal_places - after_str_len; + const diff_decimal_places = decimal_places - after_str_len; - var after_str = roc_str_slice[pi + 1 .. length]; - var after_u64 = std.fmt.parseUnsigned(u64, after_str, 10) catch null; + const after_str = roc_str_slice[pi + 1 .. length]; + const after_u64 = std.fmt.parseUnsigned(u64, after_str, 10) catch null; after_val_i128 = if (after_u64) |f| @as(i128, @intCast(f)) * math.pow(i128, 10, diff_decimal_places) else null; } - var before_str = roc_str_slice[initial_index..before_str_length]; - var before_val_not_adjusted = std.fmt.parseUnsigned(i128, before_str, 10) catch null; + const before_str = roc_str_slice[initial_index..before_str_length]; + const before_val_not_adjusted = std.fmt.parseUnsigned(i128, before_str, 10) catch null; var before_val_i128: ?i128 = null; if (before_val_not_adjusted) |before| { @@ -115,7 +115,7 @@ pub const RocDec = extern struct { const dec: RocDec = blk: { if (before_val_i128) |before| { if (after_val_i128) |after| { - var answer = @addWithOverflow(before, after); + const answer = @addWithOverflow(before, after); const result = answer[0]; const overflowed = answer[1]; if (overflowed == 1) { @@ -239,13 +239,16 @@ pub const RocDec = extern struct { } pub fn negate(self: RocDec) ?RocDec { - var negated = math.negate(self.num) catch null; + const negated = math.negate(self.num) catch null; return if (negated) |n| .{ .num = n } else null; } pub fn abs(self: RocDec) !RocDec { - const absolute = try math.absInt(self.num); - return RocDec{ .num = absolute }; + const absolute = @abs(self.num); + if (absolute <= @as(u128, @intCast(std.math.maxInt(i128)))) { + return RocDec{ .num = @intCast(absolute) }; + } + return error.OutOfRange; } pub fn addWithOverflow(self: RocDec, other: RocDec) WithOverflow(RocDec) { @@ -314,7 +317,8 @@ pub const RocDec = extern struct { const is_answer_negative = (self_i128 < 0) != (other_i128 < 0); - const self_u128 = @as(u128, @intCast(math.absInt(self_i128) catch { + const self_u128 = @abs(self_i128); + if (self_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { if (other_i128 == 0) { return .{ .value = RocDec{ .num = 0 }, .has_overflowed = false }; } else if (other_i128 == RocDec.one_point_zero.num) { @@ -324,9 +328,10 @@ pub const RocDec = extern struct { } else { return .{ .value = RocDec.max, .has_overflowed = true }; } - })); + } - const other_u128 = @as(u128, @intCast(math.absInt(other_i128) catch { + const other_u128 = @abs(other_i128); + if (other_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { if (self_i128 == 0) { return .{ .value = RocDec{ .num = 0 }, .has_overflowed = false }; } else if (self_i128 == RocDec.one_point_zero.num) { @@ -336,7 +341,7 @@ pub const RocDec = extern struct { } else { return .{ .value = RocDec.max, .has_overflowed = true }; } - })); + } const unsigned_answer = mul_and_decimalize(self_u128, other_u128); if (is_answer_negative) { @@ -471,7 +476,8 @@ pub const RocDec = extern struct { // // We do checked_abs because if we had -i128::MAX before, this will overflow. - const numerator_abs_i128 = math.absInt(numerator_i128) catch { + const numerator_u128 = @abs(numerator_i128); + if (numerator_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { // Currently, if you try to do multiplication on i64::MIN, panic // unless you're specifically multiplying by 0 or 1. // @@ -481,10 +487,10 @@ pub const RocDec = extern struct { } else { roc_panic("Decimal division overflow in numerator!", 0); } - }; - const numerator_u128 = @as(u128, @intCast(numerator_abs_i128)); + } - const denominator_abs_i128 = math.absInt(denominator_i128) catch { + const denominator_u128 = @abs(denominator_i128); + if (denominator_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { // Currently, if you try to do multiplication on i64::MIN, panic // unless you're specifically multiplying by 0 or 1. // @@ -494,8 +500,7 @@ pub const RocDec = extern struct { } else { roc_panic("Decimal division overflow in denominator!", 0); } - }; - const denominator_u128 = @as(u128, @intCast(denominator_abs_i128)); + } const numerator_u256: U256 = mul_u128(numerator_u128, math.pow(u128, 10, decimal_places)); const answer = div_u256_by_u128(numerator_u256, denominator_u128); @@ -523,7 +528,7 @@ pub const RocDec = extern struct { // This is dec/(b0+1), but as a multiplication. // So dec * (1/(b0+1)). This is way faster. const dec = self.num; - const tmp = @as(i128, @intCast(num_.mul_u128(math.absCast(dec), 249757942369376157886101012127821356963).hi >> (190 - 128))); + const tmp = @as(i128, @intCast(num_.mul_u128(@abs(dec), 249757942369376157886101012127821356963).hi >> (190 - 128))); const q0 = if (dec < 0) -tmp else tmp; const upper = q0 * b0; @@ -787,8 +792,8 @@ fn div_u256_by_u128(numer: U256, denom: u128) U256 { // K X // --- // 0 K - var denom_leading_zeros = @clz(denom); - var numer_hi_leading_zeros = @clz(numer.hi); + const denom_leading_zeros = @clz(denom); + const numer_hi_leading_zeros = @clz(numer.hi); sr = 1 + N_UDWORD_BITS + denom_leading_zeros - numer_hi_leading_zeros; // 2 <= sr <= N_UTWORD_BITS - 1 // q.all = n.all << (N_UTWORD_BITS - sr); @@ -865,7 +870,7 @@ fn div_u256_by_u128(numer: U256, denom: u128) U256 { // // As an implementation of `as_u256`, we wrap a negative value around to the maximum value of U256. - var s_u128 = math.shr(u128, hi, 127); + const s_u128 = math.shr(u128, hi, 127); var s_hi: u128 = undefined; var s_lo: u128 = undefined; if (s_u128 == 1) { @@ -875,7 +880,7 @@ fn div_u256_by_u128(numer: U256, denom: u128) U256 { s_hi = 0; s_lo = 0; } - var s = .{ + const s = .{ .hi = s_hi, .lo = s_lo, }; @@ -893,8 +898,8 @@ fn div_u256_by_u128(numer: U256, denom: u128) U256 { sr -= 1; } - var hi = (q.hi << 1) | (q.lo >> (127)); - var lo = (q.lo << 1) | carry; + const hi = (q.hi << 1) | (q.lo >> (127)); + const lo = (q.lo << 1) | carry; return .{ .hi = hi, .lo = lo }; } @@ -906,122 +911,122 @@ const expectEqualSlices = testing.expectEqualSlices; const expect = testing.expect; test "fromU64" { - var dec = RocDec.fromU64(25); + const dec = RocDec.fromU64(25); try expectEqual(RocDec{ .num = 25000000000000000000 }, dec); } test "fromF64" { - var dec = RocDec.fromF64(25.5); + const dec = RocDec.fromF64(25.5); try expectEqual(RocDec{ .num = 25500000000000000000 }, dec.?); } test "fromF64 overflow" { - var dec = RocDec.fromF64(1e308); + const dec = RocDec.fromF64(1e308); try expectEqual(dec, null); } test "fromStr: empty" { - var roc_str = RocStr.init("", 0); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("", 0); + const dec = RocDec.fromStr(roc_str); try expectEqual(dec, null); } test "fromStr: 0" { - var roc_str = RocStr.init("0", 1); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("0", 1); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = 0 }, dec.?); } test "fromStr: 1" { - var roc_str = RocStr.init("1", 1); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("1", 1); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec.one_point_zero, dec.?); } test "fromStr: 123.45" { - var roc_str = RocStr.init("123.45", 6); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("123.45", 6); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = 123450000000000000000 }, dec.?); } test "fromStr: .45" { - var roc_str = RocStr.init(".45", 3); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init(".45", 3); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); } test "fromStr: 0.45" { - var roc_str = RocStr.init("0.45", 4); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("0.45", 4); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?); } test "fromStr: 123" { - var roc_str = RocStr.init("123", 3); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("123", 3); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = 123000000000000000000 }, dec.?); } test "fromStr: -.45" { - var roc_str = RocStr.init("-.45", 4); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("-.45", 4); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); } test "fromStr: -0.45" { - var roc_str = RocStr.init("-0.45", 5); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("-0.45", 5); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?); } test "fromStr: -123" { - var roc_str = RocStr.init("-123", 4); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("-123", 4); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = -123000000000000000000 }, dec.?); } test "fromStr: -123.45" { - var roc_str = RocStr.init("-123.45", 7); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("-123.45", 7); + const dec = RocDec.fromStr(roc_str); try expectEqual(RocDec{ .num = -123450000000000000000 }, dec.?); } test "fromStr: abc" { - var roc_str = RocStr.init("abc", 3); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("abc", 3); + const dec = RocDec.fromStr(roc_str); try expectEqual(dec, null); } test "fromStr: 123.abc" { - var roc_str = RocStr.init("123.abc", 7); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("123.abc", 7); + const dec = RocDec.fromStr(roc_str); try expectEqual(dec, null); } test "fromStr: abc.123" { - var roc_str = RocStr.init("abc.123", 7); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init("abc.123", 7); + const dec = RocDec.fromStr(roc_str); try expectEqual(dec, null); } test "fromStr: .123.1" { - var roc_str = RocStr.init(".123.1", 6); - var dec = RocDec.fromStr(roc_str); + const roc_str = RocStr.init(".123.1", 6); + const dec = RocDec.fromStr(roc_str); try expectEqual(dec, null); } @@ -1234,46 +1239,46 @@ test "div: 20 / 2" { test "div: 8 / 5" { var dec: RocDec = RocDec.fromU64(8); - var res: RocDec = RocDec.fromStr(RocStr.init("1.6", 3)).?; + const res: RocDec = RocDec.fromStr(RocStr.init("1.6", 3)).?; try expectEqual(res, dec.div(RocDec.fromU64(5))); } test "div: 10 / 3" { var numer: RocDec = RocDec.fromU64(10); - var denom: RocDec = RocDec.fromU64(3); + const denom: RocDec = RocDec.fromU64(3); var roc_str = RocStr.init("3.333333333333333333", 20); errdefer roc_str.decref(); defer roc_str.decref(); - var res: RocDec = RocDec.fromStr(roc_str).?; + const res: RocDec = RocDec.fromStr(roc_str).?; try expectEqual(res, numer.div(denom)); } test "div: 341 / 341" { var number1: RocDec = RocDec.fromU64(341); - var number2: RocDec = RocDec.fromU64(341); + const number2: RocDec = RocDec.fromU64(341); try expectEqual(RocDec.fromU64(1), number1.div(number2)); } test "div: 342 / 343" { var number1: RocDec = RocDec.fromU64(342); - var number2: RocDec = RocDec.fromU64(343); - var roc_str = RocStr.init("0.997084548104956268", 20); + const number2: RocDec = RocDec.fromU64(343); + const roc_str = RocStr.init("0.997084548104956268", 20); try expectEqual(RocDec.fromStr(roc_str), number1.div(number2)); } test "div: 680 / 340" { var number1: RocDec = RocDec.fromU64(680); - var number2: RocDec = RocDec.fromU64(340); + const number2: RocDec = RocDec.fromU64(340); try expectEqual(RocDec.fromU64(2), number1.div(number2)); } test "div: 500 / 1000" { - var number1: RocDec = RocDec.fromU64(500); - var number2: RocDec = RocDec.fromU64(1000); - var roc_str = RocStr.init("0.5", 3); + const number1: RocDec = RocDec.fromU64(500); + const number2: RocDec = RocDec.fromU64(1000); + const roc_str = RocStr.init("0.5", 3); try expectEqual(RocDec.fromStr(roc_str), number1.div(number2)); } @@ -1282,35 +1287,35 @@ test "log: 1" { } test "fract: 0" { - var roc_str = RocStr.init("0", 1); + const roc_str = RocStr.init("0", 1); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 0 }, dec.fract()); } test "fract: 1" { - var roc_str = RocStr.init("1", 1); + const roc_str = RocStr.init("1", 1); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 0 }, dec.fract()); } test "fract: 123.45" { - var roc_str = RocStr.init("123.45", 6); + const roc_str = RocStr.init("123.45", 6); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 450000000000000000 }, dec.fract()); } test "fract: -123.45" { - var roc_str = RocStr.init("-123.45", 7); + const roc_str = RocStr.init("-123.45", 7); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = -450000000000000000 }, dec.fract()); } test "fract: .45" { - var roc_str = RocStr.init(".45", 3); + const roc_str = RocStr.init(".45", 3); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 450000000000000000 }, dec.fract()); @@ -1324,35 +1329,35 @@ test "fract: -0.00045" { } test "trunc: 0" { - var roc_str = RocStr.init("0", 1); + const roc_str = RocStr.init("0", 1); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 0 }, dec.trunc()); } test "trunc: 1" { - var roc_str = RocStr.init("1", 1); + const roc_str = RocStr.init("1", 1); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec.one_point_zero, dec.trunc()); } test "trunc: 123.45" { - var roc_str = RocStr.init("123.45", 6); + const roc_str = RocStr.init("123.45", 6); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 123000000000000000000 }, dec.trunc()); } test "trunc: -123.45" { - var roc_str = RocStr.init("-123.45", 7); + const roc_str = RocStr.init("-123.45", 7); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = -123000000000000000000 }, dec.trunc()); } test "trunc: .45" { - var roc_str = RocStr.init(".45", 3); + const roc_str = RocStr.init(".45", 3); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 0 }, dec.trunc()); @@ -1366,64 +1371,64 @@ test "trunc: -0.00045" { } test "round: 123.45" { - var roc_str = RocStr.init("123.45", 6); + const roc_str = RocStr.init("123.45", 6); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = 123000000000000000000 }, dec.round()); } test "round: -123.45" { - var roc_str = RocStr.init("-123.45", 7); + const roc_str = RocStr.init("-123.45", 7); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = -123000000000000000000 }, dec.round()); } test "round: 0.5" { - var roc_str = RocStr.init("0.5", 3); + const roc_str = RocStr.init("0.5", 3); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec.one_point_zero, dec.round()); } test "round: -0.5" { - var roc_str = RocStr.init("-0.5", 4); + const roc_str = RocStr.init("-0.5", 4); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec{ .num = -1000000000000000000 }, dec.round()); } test "powInt: 3.1 ^ 0" { - var roc_str = RocStr.init("3.1", 3); + const roc_str = RocStr.init("3.1", 3); var dec = RocDec.fromStr(roc_str).?; try expectEqual(RocDec.one_point_zero, dec.powInt(0)); } test "powInt: 3.1 ^ 1" { - var roc_str = RocStr.init("3.1", 3); + const roc_str = RocStr.init("3.1", 3); var dec = RocDec.fromStr(roc_str).?; try expectEqual(dec, dec.powInt(1)); } test "powInt: 2 ^ 2" { - var roc_str = RocStr.init("4", 1); - var dec = RocDec.fromStr(roc_str).?; + const roc_str = RocStr.init("4", 1); + const dec = RocDec.fromStr(roc_str).?; try expectEqual(dec, RocDec.two_point_zero.powInt(2)); } test "powInt: 0.5 ^ 2" { - var roc_str = RocStr.init("0.25", 4); - var dec = RocDec.fromStr(roc_str).?; + const roc_str = RocStr.init("0.25", 4); + const dec = RocDec.fromStr(roc_str).?; try expectEqual(dec, RocDec.zero_point_five.powInt(2)); } test "pow: 0.5 ^ 2.0" { - var roc_str = RocStr.init("0.25", 4); - var dec = RocDec.fromStr(roc_str).?; + const roc_str = RocStr.init("0.25", 4); + const dec = RocDec.fromStr(roc_str).?; try expectEqual(dec, RocDec.zero_point_five.pow(RocDec.two_point_zero)); } @@ -1464,7 +1469,7 @@ pub fn toF64(arg: RocDec) callconv(.C) f64 { } pub fn exportFromInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T) callconv(.C) i128 { const this = @as(i128, @intCast(self)); @@ -1476,7 +1481,7 @@ pub fn exportFromInt(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn fromU64C(arg: u64) callconv(.C) i128 { @@ -1585,28 +1590,28 @@ pub fn mulSaturatedC(arg1: RocDec, arg2: RocDec) callconv(.C) RocDec { } pub fn exportRound(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: RocDec) callconv(.C) T { return @as(T, @intCast(@divFloor(input.round().num, RocDec.one_point_zero_i128))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportFloor(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: RocDec) callconv(.C) T { return @as(T, @intCast(@divFloor(input.floor().num, RocDec.one_point_zero_i128))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCeiling(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: RocDec) callconv(.C) T { return @as(T, @intCast(@divFloor(input.ceiling().num, RocDec.one_point_zero_i128))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } diff --git a/crates/compiler/builtins/bitcode/src/expect.zig b/crates/compiler/builtins/bitcode/src/expect.zig index 7ae9826c1df..1fcdd3ee986 100644 --- a/crates/compiler/builtins/bitcode/src/expect.zig +++ b/crates/compiler/builtins/bitcode/src/expect.zig @@ -1,7 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); -const Atomic = std.atomic.Atomic; +const Atomic = std.atomic.Value; const O_RDWR: c_int = 2; const O_CREAT: c_int = 64; @@ -83,11 +83,10 @@ pub fn notifyParent(shared_buffer: [*]u8, tag: u32) callconv(.C) void { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { const usize_ptr = @as([*]u32, @ptrCast(@alignCast(shared_buffer))); const atomic_ptr = @as(*Atomic(u32), @ptrCast(&usize_ptr[5])); - atomic_ptr.storeUnchecked(tag); + atomic_ptr.store(tag, .unordered); // wait till the parent is done before proceeding - const Ordering = std.atomic.Ordering; - while (atomic_ptr.load(Ordering.Acquire) != 0) { + while (atomic_ptr.load(.acquire) != 0) { std.atomic.spinLoopHint(); } } diff --git a/crates/compiler/builtins/bitcode/src/glue.zig b/crates/compiler/builtins/bitcode/src/glue.zig deleted file mode 100644 index 4343bd03ce4..00000000000 --- a/crates/compiler/builtins/bitcode/src/glue.zig +++ /dev/null @@ -1,7 +0,0 @@ -// This is a glue package that just re-exports other libs useful for zig hosts. -// Long term, a slimmed down version of these libraries without all of the roc builtins should be create via `roc glue`. -// We also should make RocList use comptime types in order to make it nice to use in zig. - -pub const dec = @import("dec.zig"); -pub const list = @import("list.zig"); -pub const str = @import("str.zig"); diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index c95e6e8063e..65b4957cabb 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -931,7 +931,7 @@ inline fn listReplaceInPlaceHelp( copy: CopyFn, ) RocList { // the element we will replace - var element_at_index = (list.bytes orelse unreachable) + (index * element_width); + const element_at_index = (list.bytes orelse unreachable) + (index * element_width); // copy out the old element copy((out_element orelse unreachable), element_at_index); diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index 9923a8566f1..f1b3ccfaa13 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -16,7 +16,7 @@ const dec = @import("dec.zig"); var FLTUSED: i32 = 0; comptime { if (builtin.os.tag == .windows) { - @export(FLTUSED, .{ .name = "_fltused", .linkage = .Weak }); + @export(FLTUSED, .{ .name = "_fltused", .linkage = .weak }); } } @@ -52,7 +52,7 @@ comptime { exportDecFn(dec.fromI128, "from_i128"); exportDecFn(dec.toStr, "to_str"); - inline for (INTEGERS) |T| { + for (INTEGERS) |T| { dec.exportFromInt(T, ROC_BUILTINS ++ ".dec.from_int."); dec.exportRound(T, ROC_BUILTINS ++ ".dec.round."); @@ -115,7 +115,7 @@ comptime { exportNumFn(num.f32FromParts, "f32_from_parts"); exportNumFn(num.f64FromParts, "f64_from_parts"); - inline for (INTEGERS, 0..) |T, i| { + for (INTEGERS, 0..) |T, i| { num.exportPow(T, ROC_BUILTINS ++ "." ++ NUM ++ ".pow_int."); num.exportDivCeil(T, ROC_BUILTINS ++ "." ++ NUM ++ ".div_ceil."); @@ -151,15 +151,15 @@ comptime { num.exportCountOneBits(T, ROC_BUILTINS ++ "." ++ NUM ++ ".count_one_bits."); } - inline for (INTEGERS) |FROM| { - inline for (INTEGERS) |TO| { + for (INTEGERS) |FROM| { + for (INTEGERS) |TO| { // We're exporting more than we need here, but that's okay. num.exportToIntCheckingMax(FROM, TO, ROC_BUILTINS ++ "." ++ NUM ++ ".int_to_" ++ @typeName(TO) ++ "_checking_max."); num.exportToIntCheckingMaxAndMin(FROM, TO, ROC_BUILTINS ++ "." ++ NUM ++ ".int_to_" ++ @typeName(TO) ++ "_checking_max_and_min."); } } - inline for (FLOATS) |T| { + for (FLOATS) |T| { num.exportAsin(T, ROC_BUILTINS ++ "." ++ NUM ++ ".asin."); num.exportAcos(T, ROC_BUILTINS ++ "." ++ NUM ++ ".acos."); num.exportAtan(T, ROC_BUILTINS ++ "." ++ NUM ++ ".atan."); @@ -212,12 +212,12 @@ comptime { exportStrFn(str.strAllocationPtr, "allocation_ptr"); exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity"); - inline for (INTEGERS) |T| { + for (INTEGERS) |T| { str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int."); num.exportParseInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".to_int."); } - inline for (FLOATS) |T| { + for (FLOATS) |T| { str.exportFromFloat(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_float."); num.exportParseFloat(T, ROC_BUILTINS ++ "." ++ STR ++ ".to_float."); } @@ -238,8 +238,8 @@ comptime { exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount"); exportUtilsFn(utils.dictPseudoSeed, "dict_pseudo_seed"); - @export(panic_utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .Weak }); - @export(dbg_utils.dbg_impl, .{ .name = "roc_builtins.utils." ++ "dbg_impl", .linkage = .Weak }); + @export(panic_utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .weak }); + @export(dbg_utils.dbg_impl, .{ .name = "roc_builtins.utils." ++ "dbg_impl", .linkage = .weak }); if (builtin.target.cpu.arch != .wasm32) { exportUtilsFn(expect.expectFailedStartSharedBuffer, "expect_failed_start_shared_buffer"); @@ -247,17 +247,17 @@ comptime { exportUtilsFn(expect.notifyParentExpect, "notify_parent_expect"); // sets the buffer used for expect failures - @export(expect.setSharedBuffer, .{ .name = "set_shared_buffer", .linkage = .Weak }); + @export(expect.setSharedBuffer, .{ .name = "set_shared_buffer", .linkage = .weak }); exportUtilsFn(expect.readSharedBufferEnv, "read_env_shared_buffer"); } if (builtin.target.cpu.arch == .aarch64) { - @export(__roc_force_setjmp, .{ .name = "__roc_force_setjmp", .linkage = .Weak }); - @export(__roc_force_longjmp, .{ .name = "__roc_force_longjmp", .linkage = .Weak }); + @export(__roc_force_setjmp, .{ .name = "__roc_force_setjmp", .linkage = .weak }); + @export(__roc_force_longjmp, .{ .name = "__roc_force_longjmp", .linkage = .weak }); } else if (builtin.os.tag == .windows) { - @export(__roc_force_setjmp_windows, .{ .name = "__roc_force_setjmp", .linkage = .Weak }); - @export(__roc_force_longjmp_windows, .{ .name = "__roc_force_longjmp", .linkage = .Weak }); + @export(__roc_force_setjmp_windows, .{ .name = "__roc_force_setjmp", .linkage = .weak }); + @export(__roc_force_longjmp_windows, .{ .name = "__roc_force_longjmp", .linkage = .weak }); } } @@ -372,7 +372,7 @@ comptime { // Export helpers - Must be run inside a comptime fn exportBuiltinFn(comptime func: anytype, comptime func_name: []const u8) void { - @export(func, .{ .name = "roc_builtins." ++ func_name, .linkage = .Strong }); + @export(func, .{ .name = "roc_builtins." ++ func_name, .linkage = .strong }); } fn exportNumFn(comptime func: anytype, comptime func_name: []const u8) void { exportBuiltinFn(func, "num." ++ func_name); diff --git a/crates/compiler/builtins/bitcode/src/num.zig b/crates/compiler/builtins/bitcode/src/num.zig index 34d97d1c362..a1eff35a95e 100644 --- a/crates/compiler/builtins/bitcode/src/num.zig +++ b/crates/compiler/builtins/bitcode/src/num.zig @@ -67,7 +67,7 @@ pub fn mul_u128(a: u128, b: u128) U256 { } pub fn exportParseInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(buf: RocStr) callconv(.C) NumParseResult(T) { // a radix of 0 will make zig determine the radix from the frefix: // * A prefix of "0b" implies radix=2, @@ -82,11 +82,11 @@ pub fn exportParseInt(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportParseFloat(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(buf: RocStr) callconv(.C) NumParseResult(T) { if (std.fmt.parseFloat(T, buf.asSlice())) |success| { return .{ .errorcode = 0, .value = success }; @@ -95,20 +95,20 @@ pub fn exportParseFloat(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportNumToFloatCast(comptime T: type, comptime F: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(x: T) callconv(.C) F { return @floatFromInt(x); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportPow(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(base: T, exp: T) callconv(.C) T { switch (@typeInfo(T)) { // std.math.pow can handle ints via powi, but it turns any errors to unreachable @@ -127,153 +127,153 @@ pub fn exportPow(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportIsNan(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) bool { return std.math.isNan(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportIsInfinite(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) bool { return std.math.isInf(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportIsFinite(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) bool { return std.math.isFinite(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAsin(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return std.math.asin(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAcos(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return std.math.acos(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAtan(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return std.math.atan(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportSin(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return math.sin(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCos(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return math.cos(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportTan(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return math.tan(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportLog(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return @log(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportFAbs(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { - return @fabs(input); + return @abs(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportSqrt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: T) callconv(.C) T { return math.sqrt(input); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportRound(comptime F: type, comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: F) callconv(.C) T { return @as(T, @intFromFloat((math.round(input)))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportFloor(comptime F: type, comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: F) callconv(.C) T { return @as(T, @intFromFloat((math.floor(input)))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCeiling(comptime F: type, comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: F) callconv(.C) T { return @as(T, @intFromFloat((math.ceil(input)))); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportDivCeil(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(a: T, b: T) callconv(.C) T { return math.divCeil(T, a, b) catch { roc_panic("Integer division by 0!", 0); }; } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn ToIntCheckedResult(comptime T: type) type { @@ -286,7 +286,7 @@ pub fn ToIntCheckedResult(comptime T: type) type { } pub fn exportToIntCheckingMax(comptime From: type, comptime To: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: From) callconv(.C) ToIntCheckedResult(To) { if (input > std.math.maxInt(To)) { return .{ .out_of_bounds = true, .value = 0 }; @@ -294,11 +294,11 @@ pub fn exportToIntCheckingMax(comptime From: type, comptime To: type, comptime n return .{ .out_of_bounds = false, .value = @as(To, @intCast(input)) }; } }.func; - @export(f, .{ .name = name ++ @typeName(From), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(From), .linkage = .strong }); } pub fn exportToIntCheckingMaxAndMin(comptime From: type, comptime To: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(input: From) callconv(.C) ToIntCheckedResult(To) { if (input > std.math.maxInt(To) or input < std.math.minInt(To)) { return .{ .out_of_bounds = true, .value = 0 }; @@ -306,7 +306,7 @@ pub fn exportToIntCheckingMaxAndMin(comptime From: type, comptime To: type, comp return .{ .out_of_bounds = false, .value = @as(To, @intCast(input)) }; } }.func; - @export(f, .{ .name = name ++ @typeName(From), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(From), .linkage = .strong }); } fn isMultipleOf(comptime T: type, lhs: T, rhs: T) bool { @@ -325,12 +325,12 @@ fn isMultipleOf(comptime T: type, lhs: T, rhs: T) bool { } pub fn exportIsMultipleOf(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) bool { return @call(.always_inline, isMultipleOf, .{ T, self, other }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } fn addWithOverflow(comptime T: type, self: T, other: T) WithOverflow(T) { @@ -348,16 +348,16 @@ fn addWithOverflow(comptime T: type, self: T, other: T) WithOverflow(T) { } pub fn exportAddWithOverflow(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) WithOverflow(T) { return @call(.always_inline, addWithOverflow, .{ T, self, other }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAddSaturatedInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = addWithOverflow(T, self, other); if (result.has_overflowed) { @@ -372,20 +372,20 @@ pub fn exportAddSaturatedInt(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAddWrappedInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { return self +% other; } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportAddOrPanic(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = addWithOverflow(T, self, other); if (result.has_overflowed) { @@ -395,7 +395,7 @@ pub fn exportAddOrPanic(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } fn subWithOverflow(comptime T: type, self: T, other: T) WithOverflow(T) { @@ -413,16 +413,16 @@ fn subWithOverflow(comptime T: type, self: T, other: T) WithOverflow(T) { } pub fn exportSubWithOverflow(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) WithOverflow(T) { return @call(.always_inline, subWithOverflow, .{ T, self, other }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportSubSaturatedInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = subWithOverflow(T, self, other); if (result.has_overflowed) { @@ -438,20 +438,20 @@ pub fn exportSubSaturatedInt(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportSubWrappedInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { return self -% other; } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportSubOrPanic(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = subWithOverflow(T, self, other); if (result.has_overflowed) { @@ -461,7 +461,7 @@ pub fn exportSubOrPanic(comptime T: type, comptime name: []const u8) void { } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } fn mulWithOverflow(comptime T: type, comptime W: type, self: T, other: T) WithOverflow(T) { @@ -472,7 +472,8 @@ fn mulWithOverflow(comptime T: type, comptime W: type, self: T, other: T) WithOv const max = std.math.maxInt(i128); const min = std.math.minInt(i128); - const self_u128 = @as(u128, @intCast(math.absInt(self) catch { + const self_u128 = @abs(self); + if (self_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { if (other == 0) { return .{ .value = 0, .has_overflowed = false }; } else if (other == 1) { @@ -482,9 +483,10 @@ fn mulWithOverflow(comptime T: type, comptime W: type, self: T, other: T) WithOv } else { return .{ .value = max, .has_overflowed = true }; } - })); + } - const other_u128 = @as(u128, @intCast(math.absInt(other) catch { + const other_u128 = @abs(other); + if (other_u128 > @as(u128, @intCast(std.math.maxInt(i128)))) { if (self == 0) { return .{ .value = 0, .has_overflowed = false }; } else if (self == 1) { @@ -494,7 +496,7 @@ fn mulWithOverflow(comptime T: type, comptime W: type, self: T, other: T) WithOv } else { return .{ .value = max, .has_overflowed = true }; } - })); + } const answer256: U256 = mul_u128(self_u128, other_u128); @@ -539,31 +541,31 @@ fn mulWithOverflow(comptime T: type, comptime W: type, self: T, other: T) WithOv } pub fn exportMulWithOverflow(comptime T: type, comptime W: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) WithOverflow(T) { return @call(.always_inline, mulWithOverflow, .{ T, W, self, other }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportMulSaturatedInt(comptime T: type, comptime W: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = @call(.always_inline, mulWithOverflow, .{ T, W, self, other }); return result.value; } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportMulWrappedInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { return self *% other; } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn shiftRightZeroFillI128(self: i128, other: u8) callconv(.C) i128 { @@ -635,7 +637,7 @@ pub fn greaterThanOrEqualU128(self: u128, other: u128) callconv(.C) bool { } pub fn exportMulOrPanic(comptime T: type, comptime W: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T, other: T) callconv(.C) T { const result = @call(.always_inline, mulWithOverflow, .{ T, W, self, other }); if (result.has_overflowed) { @@ -645,34 +647,34 @@ pub fn exportMulOrPanic(comptime T: type, comptime W: type, comptime name: []con } } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCountLeadingZeroBits(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T) callconv(.C) u8 { return @as(u8, @clz(self)); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCountTrailingZeroBits(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T) callconv(.C) u8 { return @as(u8, @ctz(self)); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn exportCountOneBits(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(self: T) callconv(.C) u8 { return @as(u8, @popCount(self)); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } pub fn f32ToParts(self: f32) callconv(.C) F32Parts { diff --git a/crates/compiler/builtins/bitcode/src/sort.zig b/crates/compiler/builtins/bitcode/src/sort.zig index a02bb4b4662..722a5bee90d 100644 --- a/crates/compiler/builtins/bitcode/src/sort.zig +++ b/crates/compiler/builtins/bitcode/src/sort.zig @@ -61,7 +61,7 @@ pub fn fluxsort( } else { if (utils.alloc(len * @sizeOf(usize), @alignOf(usize))) |alloc_ptr| { // Build list of pointers to sort. - var arr_ptr = @as([*]Opaque, @ptrCast(@alignCast(alloc_ptr))); + const arr_ptr = @as([*]Opaque, @ptrCast(@alignCast(alloc_ptr))); defer utils.dealloc(alloc_ptr, @alignOf(usize)); for (0..len) |i| { arr_ptr[i] = array + i * element_width; @@ -552,7 +552,7 @@ fn flux_default_partition( ) usize { var arr_ptr = array; var swap_ptr = swap; - var pivot_ptr = pivot; + const pivot_ptr = pivot; var x_ptr = x; // len guaranteed compares @@ -621,7 +621,7 @@ fn flux_reverse_partition( ) void { var arr_ptr = array; var swap_ptr = swap; - var pivot_ptr = pivot; + const pivot_ptr = pivot; var x_ptr = x; // len guaranteed compares @@ -661,9 +661,9 @@ test "flux_default_partition" { var pivot: i64 = 0; var arr: [32]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [32]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [32]i64{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, @@ -748,9 +748,9 @@ test "flux_reverse_partition" { var pivot: i64 = 0; var arr: [32]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [32]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [32]i64{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 17, 17, 17, 17, 17, 17, 17, @@ -809,7 +809,7 @@ fn median_of_cube_root( // Using a pointer to div as an int is to get a random offset from 0 to div. var arr_ptr = x_ptr + (@intFromPtr(&div) / 16 % div) * element_width; - var swap_ptr = if (x_ptr == array) swap else array; + const swap_ptr = if (x_ptr == array) swap else array; for (0..cbrt) |cnt| { copy(swap_ptr + cnt * element_width, arr_ptr); @@ -953,7 +953,7 @@ fn binary_median( ptr_b += len * element_width; } } - var from = if (compare(cmp, cmp_data, ptr_a, ptr_b, indirect) == GT) ptr_a else ptr_b; + const from = if (compare(cmp, cmp_data, ptr_a, ptr_b, indirect) == GT) ptr_a else ptr_b; copy(out, from); } @@ -963,10 +963,10 @@ test "median_of_cube_root" { var generic = false; var swap: [32]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); { var arr: [32]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [32]i64{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, @@ -1001,7 +1001,7 @@ test "median_of_nine" { { var arr: [9]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [9]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; median_of_nine(arr_ptr, 10, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, @ptrCast(&out), false); @@ -1030,7 +1030,7 @@ test "trim_four" { var test_count: i64 = 0; var arr: [4]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [4]i64{ 1, 2, 3, 4 }; trim_four(arr_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -1054,7 +1054,7 @@ test "binary_median" { { var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [10]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; binary_median(arr_ptr, arr_ptr + 5 * @sizeOf(i64), 5, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, @ptrCast(&out), false); @@ -1068,7 +1068,7 @@ test "binary_median" { } { var arr: [16]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [16]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; binary_median(arr_ptr, arr_ptr + 8 * @sizeOf(i64), 8, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, @ptrCast(&out), false); @@ -1141,7 +1141,7 @@ pub fn quadsort( } else { if (utils.alloc(len * @sizeOf(usize), @alignOf(usize))) |alloc_ptr| { // Build list of pointers to sort. - var arr_ptr = @as([*]Opaque, @ptrCast(@alignCast(alloc_ptr))); + const arr_ptr = @as([*]Opaque, @ptrCast(@alignCast(alloc_ptr))); defer utils.dealloc(alloc_ptr, @alignOf(usize)); for (0..len) |i| { arr_ptr[i] = array + i * element_width; @@ -1184,7 +1184,7 @@ fn quadsort_direct( inc_n_data: IncN, comptime indirect: bool, ) void { - var arr_ptr = array; + const arr_ptr = array; if (len < 32) { // TODO: This is a solid amount of stack space. Is that ok? // That said, it only ever allocates once (not recursive). @@ -1194,7 +1194,7 @@ fn quadsort_direct( const swap = @as([*]u8, @ptrCast(&swap_buffer[0])); tail_swap(arr_ptr, len, swap, cmp, cmp_data, element_width, copy, data_is_owned, inc_n_data, indirect); } else if (quad_swap(arr_ptr, len, cmp, cmp_data, element_width, copy, data_is_owned, inc_n_data, indirect) != .sorted) { - var swap_len = len; + const swap_len = len; // This is optional, for about 5% perf hit, lower memory usage on large arrays. // if (len > 4194304) { @@ -1253,7 +1253,7 @@ fn rotate_merge( inc_n_data: IncN, comptime indirect: bool, ) void { - var end_ptr = array + len * element_width; + const end_ptr = array + len * element_width; if (len <= block_len * 2 and len -% block_len <= swap_len) { partial_backwards_merge(array, len, swap, swap_len, block_len, cmp, cmp_data, element_width, copy, data_is_owned, inc_n_data, indirect); @@ -1301,10 +1301,10 @@ fn rotate_merge_block( return; } - var right_block = left_block / 2; + const right_block = left_block / 2; left_block -= right_block; - var left = monobound_binary_first(array + (left_block + right_block) * element_width, right, array + left_block * element_width, cmp, cmp_data, element_width, data_is_owned, inc_n_data, indirect); + const left = monobound_binary_first(array + (left_block + right_block) * element_width, right, array + left_block * element_width, cmp, cmp_data, element_width, data_is_owned, inc_n_data, indirect); right -= left; if (left != 0) { @@ -1473,7 +1473,7 @@ fn trinity_rotation( var bridge = left_len - right_len; if (bridge <= swap_len and bridge > 3) { var c_ptr = a_ptr + right_len * element_width; - var d_ptr = c_ptr + left_len * element_width; + const d_ptr = c_ptr + left_len * element_width; @memcpy(swap[0..(bridge * element_width)], c_ptr[0..(bridge * element_width)]); @@ -1543,9 +1543,9 @@ test "rotate_merge" { var test_count: i64 = 0; var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [10]i64{ 7, 8, 5, 6, 3, 4, 1, 2, 9, 10 }; rotate_merge(arr_ptr, 10, swap_ptr, 10, 2, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -1573,9 +1573,9 @@ test "monobound_binary_first" { var test_count: i64 = 0; var arr = [25]i64{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49 }; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var value: i64 = undefined; - var value_ptr = @as([*]u8, @ptrCast(&value)); + const value_ptr = @as([*]u8, @ptrCast(&value)); value = 7; var res = monobound_binary_first(arr_ptr, 25, value_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), true, &test_inc_n_data, false); @@ -1606,9 +1606,9 @@ test "monobound_binary_first" { test "trinity_rotation" { { var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); // Even. arr = [10]i64{ 6, 7, 8, 9, 10, 1, 2, 3, 4, 5 }; @@ -1637,9 +1637,9 @@ test "trinity_rotation" { } { var arr: [16]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [5]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); // left larger, bridge in swap. arr = [16]i64{ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6 }; @@ -1781,8 +1781,8 @@ fn partial_backwards_merge( inc_n_data(cmp_data, 2); } const lte = compare(cmp, cmp_data, left_tail, right_tail, indirect) != GT; - var x = if (lte) element_width else 0; - var not_x = if (!lte) element_width else 0; + const x = if (lte) element_width else 0; + const not_x = if (!lte) element_width else 0; dest_tail -= element_width; copy(dest_tail + x, right_tail); right_tail -= element_width; @@ -1816,8 +1816,8 @@ fn partial_backwards_merge( } // Couldn't move two elements, do a cross swap and continue. const lte = compare(cmp, cmp_data, left_tail, right_tail, indirect) != GT; - var x = if (lte) element_width else 0; - var not_x = if (!lte) element_width else 0; + const x = if (lte) element_width else 0; + const not_x = if (!lte) element_width else 0; dest_tail -= element_width; copy(dest_tail + x, right_tail); right_tail -= element_width; @@ -1983,8 +1983,8 @@ fn partial_forward_merge( } // Couldn't move two elements, do a cross swap and continue. const lte = compare(cmp, cmp_data, left_head, right_head, indirect) != GT; - var x = if (lte) element_width else 0; - var not_x = if (!lte) element_width else 0; + const x = if (lte) element_width else 0; + const not_x = if (!lte) element_width else 0; copy(dest_head + x, right_head); right_head += element_width; copy(dest_head + not_x, left_head); @@ -2096,9 +2096,9 @@ test "tail_merge" { const expected = [10]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [10]i64{ 7, 8, 5, 6, 3, 4, 1, 2, 9, 10 }; tail_merge(arr_ptr, 10, swap_ptr, 10, 2, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -2122,9 +2122,9 @@ test "partial_backwards_merge" { const expected = [10]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [10]i64{ 3, 4, 5, 6, 7, 8, 1, 2, 9, 10 }; partial_backwards_merge(arr_ptr, 10, swap_ptr, 10, 6, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -2154,9 +2154,9 @@ test "partial_backwards_merge" { } var arr: [64]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [64]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); // chunks for (0..16) |i| { @@ -2202,9 +2202,9 @@ test "partial_forward_merge" { const expected = [10]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [10]i64{ 3, 4, 5, 6, 7, 8, 1, 2, 9, 10 }; partial_forward_merge(arr_ptr, 10, swap_ptr, 10, 6, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -2461,9 +2461,9 @@ test "quad_merge" { const expected = [10]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var arr: [10]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [10]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); var size: usize = undefined; arr = [10]i64{ 7, 8, 5, 6, 3, 4, 1, 2, 9, 10 }; @@ -2503,9 +2503,9 @@ test "quad_merge_block" { const expected = [8]i64{ 1, 2, 3, 4, 5, 6, 7, 8 }; var arr: [8]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); var swap: [8]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); // case 0 - totally unsorted arr = [8]i64{ 7, 8, 5, 6, 3, 4, 1, 2 }; @@ -2547,8 +2547,8 @@ test "cross_merge" { var src: [64]i64 = undefined; var dest: [64]i64 = undefined; - var src_ptr = @as([*]u8, @ptrCast(&src[0])); - var dest_ptr = @as([*]u8, @ptrCast(&dest[0])); + const src_ptr = @as([*]u8, @ptrCast(&src[0])); + const dest_ptr = @as([*]u8, @ptrCast(&dest[0])); // Opitimal case, ordered but swapped for (0..32) |i| { @@ -2941,7 +2941,7 @@ fn quad_reversal( test "quad_swap" { var test_count: i64 = 0; var arr: [75]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [75]i64{ // multiple ordered chunks @@ -2997,8 +2997,8 @@ test "quad_swap" { test "quad_swap_merge" { var arr: [8]i64 = undefined; var swap: [8]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); arr = [8]i64{ 5, 6, 7, 8, 1, 2, 3, 4 }; swap = [8]i64{ 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -3019,15 +3019,15 @@ test "quad_swap_merge" { test "quad_reversal" { { var arr = [8]i64{ 8, 7, 6, 5, 4, 3, 2, 1 }; - var start_ptr = @as([*]u8, @ptrCast(&arr[0])); - var end_ptr = @as([*]u8, @ptrCast(&arr[7])); + const start_ptr = @as([*]u8, @ptrCast(&arr[0])); + const end_ptr = @as([*]u8, @ptrCast(&arr[7])); quad_reversal(start_ptr, end_ptr, @sizeOf(i64), &test_i64_copy); try testing.expectEqual(arr, [8]i64{ 1, 2, 3, 4, 5, 6, 7, 8 }); } { var arr = [9]i64{ 9, 8, 7, 6, 5, 4, 3, 2, 1 }; - var start_ptr = @as([*]u8, @ptrCast(&arr[0])); - var end_ptr = @as([*]u8, @ptrCast(&arr[8])); + const start_ptr = @as([*]u8, @ptrCast(&arr[0])); + const end_ptr = @as([*]u8, @ptrCast(&arr[8])); quad_reversal(start_ptr, end_ptr, @sizeOf(i64), &test_i64_copy); try testing.expectEqual(arr, [9]i64{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }); } @@ -3130,7 +3130,7 @@ fn parity_merge( test "tail_swap" { var test_count: i64 = 0; var swap: [31]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); var arr: [31]i64 = undefined; var expected: [31]i64 = undefined; @@ -3138,7 +3138,7 @@ test "tail_swap" { arr[i] = @intCast(i + 1); expected[i] = @intCast(i + 1); } - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); for (0..10) |seed| { var rng = std.rand.DefaultPrng.init(seed); @@ -3154,10 +3154,10 @@ test "parity_merge" { var test_count: i64 = 0; { var dest: [8]i64 = undefined; - var dest_ptr = @as([*]u8, @ptrCast(&dest[0])); + const dest_ptr = @as([*]u8, @ptrCast(&dest[0])); var arr: [8]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [8]i64{ 1, 3, 5, 7, 2, 4, 6, 8 }; dest = [8]i64{ 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -3173,10 +3173,10 @@ test "parity_merge" { } { var dest: [9]i64 = undefined; - var dest_ptr = @as([*]u8, @ptrCast(&dest[0])); + const dest_ptr = @as([*]u8, @ptrCast(&dest[0])); var arr: [9]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [9]i64{ 1, 3, 5, 8, 2, 4, 6, 7, 9 }; dest = [9]i64{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -3395,8 +3395,8 @@ fn parity_swap_six( } { const gt = compare(cmp, cmp_data, arr_ptr, arr_ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; - var not_x = if (!gt) element_width else 0; + const x = if (gt) element_width else 0; + const not_x = if (!gt) element_width else 0; copy(swap, arr_ptr + x); copy(swap + element_width, arr_ptr + not_x); copy(swap + 2 * element_width, arr_ptr + 2 * element_width); @@ -3404,8 +3404,8 @@ fn parity_swap_six( } { const gt = compare(cmp, cmp_data, arr_ptr, arr_ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; - var not_x = if (!gt) element_width else 0; + const x = if (gt) element_width else 0; + const not_x = if (!gt) element_width else 0; copy(swap + 4 * element_width, arr_ptr + x); copy(swap + 5 * element_width, arr_ptr + not_x); copy(swap + 3 * element_width, arr_ptr - element_width); @@ -3472,8 +3472,8 @@ fn parity_swap_seven( { const gt = compare(cmp, cmp_data, arr_ptr, arr_ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; - var not_x = if (!gt) element_width else 0; + const x = if (gt) element_width else 0; + const not_x = if (!gt) element_width else 0; copy(swap, arr_ptr + x); copy(swap + element_width, arr_ptr + not_x); copy(swap + 2 * element_width, arr_ptr + 2 * element_width); @@ -3481,16 +3481,16 @@ fn parity_swap_seven( } { const gt = compare(cmp, cmp_data, arr_ptr, arr_ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; - var not_x = if (!gt) element_width else 0; + const x = if (gt) element_width else 0; + const not_x = if (!gt) element_width else 0; copy(swap + 3 * element_width, arr_ptr + x); copy(swap + 4 * element_width, arr_ptr + not_x); arr_ptr += 2 * element_width; } { const gt = compare(cmp, cmp_data, arr_ptr, arr_ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; - var not_x = if (!gt) element_width else 0; + const x = if (gt) element_width else 0; + const not_x = if (!gt) element_width else 0; copy(swap + 5 * element_width, arr_ptr + x); copy(swap + 6 * element_width, arr_ptr + not_x); } @@ -3518,11 +3518,11 @@ fn parity_swap_seven( test "tiny_sort" { var test_count: i64 = 0; var swap: [7]i64 = undefined; - var swap_ptr = @as([*]u8, @ptrCast(&swap[0])); + const swap_ptr = @as([*]u8, @ptrCast(&swap[0])); { var arr: [7]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [7]i64{ 3, 1, 2, 5, 4, 7, 6 }; tiny_sort(arr_ptr, 7, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -3536,7 +3536,7 @@ test "tiny_sort" { } { var arr: [6]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [6]i64{ 3, 1, 2, 6, 4, 5 }; tiny_sort(arr_ptr, 6, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -3550,7 +3550,7 @@ test "tiny_sort" { } { var arr: [5]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [5]i64{ 2, 1, 4, 3, 5 }; tiny_sort(arr_ptr, 5, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -3564,7 +3564,7 @@ test "tiny_sort" { } { var arr: [4]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); arr = [4]i64{ 4, 2, 1, 3 }; tiny_sort(arr_ptr, 4, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); @@ -3578,14 +3578,14 @@ test "tiny_sort" { } { var arr = [3]i64{ 2, 3, 1 }; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); tiny_sort(arr_ptr, 3, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); try testing.expectEqual(test_count, 0); try testing.expectEqual(arr, [3]i64{ 1, 2, 3 }); } { var arr = [2]i64{ 2, 1 }; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); tiny_sort(arr_ptr, 2, swap_ptr, &test_i64_compare_refcounted, @ptrCast(&test_count), @sizeOf(i64), &test_i64_copy, true, &test_inc_n_data, false); try testing.expectEqual(test_count, 0); try testing.expectEqual(arr, [2]i64{ 1, 2 }); @@ -3734,7 +3734,7 @@ inline fn swap_branchless_return_gt( ) u8 { // While not guaranteed branchless, tested in godbolt for x86_64, aarch32, aarch64, riscv64, and wasm32. const gt = compare(cmp, cmp_data, ptr, ptr + element_width, indirect) == GT; - var x = if (gt) element_width else 0; + const x = if (gt) element_width else 0; const from = if (gt) ptr else ptr + element_width; copy(tmp, from); copy(ptr, ptr + x); @@ -3783,8 +3783,8 @@ inline fn compare_inc( test "parity_merge_four" { var arr: [8]i64 = undefined; var dest: [8]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); - var dest_ptr = @as([*]u8, @ptrCast(&dest[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const dest_ptr = @as([*]u8, @ptrCast(&dest[0])); arr = [8]i64{ 1, 2, 3, 4, 5, 6, 7, 8 }; dest = [8]i64{ 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -3805,8 +3805,8 @@ test "parity_merge_four" { test "parity_merge_two" { var arr: [4]i64 = undefined; var dest: [4]i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); - var dest_ptr = @as([*]u8, @ptrCast(&dest[0])); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const dest_ptr = @as([*]u8, @ptrCast(&dest[0])); arr = [4]i64{ 1, 2, 3, 4 }; dest = [4]i64{ 0, 0, 0, 0 }; @@ -3873,8 +3873,8 @@ test "tail_branchless_merge" { test "swap" { var arr: [2]i64 = undefined; var tmp: i64 = undefined; - var arr_ptr = @as([*]u8, @ptrCast(&arr[0])); - var tmp_ptr = @as([*]u8, @ptrCast(&tmp)); + const arr_ptr = @as([*]u8, @ptrCast(&arr[0])); + const tmp_ptr = @as([*]u8, @ptrCast(&tmp)); arr = [2]i64{ 10, 20 }; swap_branchless(arr_ptr, tmp_ptr, &test_i64_compare, null, @sizeOf(i64), &test_i64_copy, false); diff --git a/crates/compiler/builtins/bitcode/src/str.zig b/crates/compiler/builtins/bitcode/src/str.zig index c47b6a70e80..eea4596791f 100644 --- a/crates/compiler/builtins/bitcode/src/str.zig +++ b/crates/compiler/builtins/bitcode/src/str.zig @@ -212,7 +212,7 @@ pub const RocStr = extern struct { // just return the bytes return str; } else { - var new_str = RocStr.allocateBig(str.length, str.length); + const new_str = RocStr.allocateBig(str.length, str.length); var old_bytes: [*]u8 = @as([*]u8, @ptrCast(str.bytes)); var new_bytes: [*]u8 = @as([*]u8, @ptrCast(new_str.bytes)); @@ -274,7 +274,7 @@ pub const RocStr = extern struct { const source_ptr = self.asU8ptr(); const dest_ptr = result.asU8ptrMut(); - std.mem.copy(u8, dest_ptr[0..old_length], source_ptr[0..old_length]); + @memcpy(dest_ptr[0..old_length], source_ptr[0..old_length]); @memset(dest_ptr[old_length..new_length], 0); self.decref(); @@ -290,7 +290,7 @@ pub const RocStr = extern struct { const source_ptr = self.asU8ptr(); - std.mem.copy(u8, dest_ptr[0..old_length], source_ptr[0..old_length]); + @memcpy(dest_ptr[0..old_length], source_ptr[0..old_length]); @memset(dest_ptr[old_length..new_length], 0); self.decref(); @@ -554,13 +554,13 @@ pub fn strNumberOfBytes(string: RocStr) callconv(.C) usize { // Str.fromInt pub fn exportFromInt(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(int: T) callconv(.C) RocStr { return @call(.always_inline, strFromIntHelp, .{ T, int }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } fn strFromIntHelp(comptime T: type, int: T) RocStr { @@ -568,9 +568,9 @@ fn strFromIntHelp(comptime T: type, int: T) RocStr { const size = comptime blk: { // the string representation of the minimum i128 value uses at most 40 characters var buf: [40]u8 = undefined; - var resultMin = std.fmt.bufPrint(&buf, "{}", .{std.math.minInt(T)}) catch unreachable; - var resultMax = std.fmt.bufPrint(&buf, "{}", .{std.math.maxInt(T)}) catch unreachable; - var result = if (resultMin.len > resultMax.len) resultMin.len else resultMax.len; + const resultMin = std.fmt.bufPrint(&buf, "{}", .{std.math.minInt(T)}) catch unreachable; + const resultMax = std.fmt.bufPrint(&buf, "{}", .{std.math.maxInt(T)}) catch unreachable; + const result = if (resultMin.len > resultMax.len) resultMin.len else resultMax.len; break :blk result; }; @@ -582,13 +582,13 @@ fn strFromIntHelp(comptime T: type, int: T) RocStr { // Str.fromFloat pub fn exportFromFloat(comptime T: type, comptime name: []const u8) void { - comptime var f = struct { + const f = struct { fn func(float: T) callconv(.C) RocStr { return @call(.always_inline, strFromFloatHelp, .{ T, float }); } }.func; - @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); + @export(f, .{ .name = name ++ @typeName(T), .linkage = .strong }); } fn strFromFloatHelp(comptime T: type, float: T) RocStr { @@ -662,7 +662,7 @@ test "strSplitHelp: empty delimiter" { strSplitOnHelp(array_ptr, str, delimiter); - var expected = [1]RocStr{ + const expected = [1]RocStr{ str, }; @@ -696,7 +696,7 @@ test "strSplitHelp: no delimiter" { strSplitOnHelp(array_ptr, str, delimiter); - var expected = [1]RocStr{ + const expected = [1]RocStr{ str, }; @@ -735,7 +735,7 @@ test "strSplitHelp: empty start" { const one = RocStr.init("a", 1); - var expected = [2]RocStr{ + const expected = [2]RocStr{ RocStr.empty(), one, }; @@ -777,7 +777,7 @@ test "strSplitHelp: empty end" { const one = RocStr.init("1", 1); const two = RocStr.init("2", 1); - var expected = [3]RocStr{ + const expected = [3]RocStr{ one, two, RocStr.empty(), }; @@ -813,7 +813,7 @@ test "strSplitHelp: string equals delimiter" { strSplitOnHelp(array_ptr, str_delimiter, str_delimiter); - var expected = [2]RocStr{ RocStr.empty(), RocStr.empty() }; + const expected = [2]RocStr{ RocStr.empty(), RocStr.empty() }; defer { for (array) |rocStr| { @@ -851,7 +851,7 @@ test "strSplitHelp: delimiter on sides" { const ghi_arr = "ghi"; const ghi = RocStr.init(ghi_arr, ghi_arr.len); - var expected = [3]RocStr{ + const expected = [3]RocStr{ RocStr.empty(), ghi, RocStr.empty(), }; @@ -892,7 +892,7 @@ test "strSplitHelp: three pieces" { const b = RocStr.init("b", 1); const c = RocStr.init("c", 1); - var expected_array = [array_len]RocStr{ + const expected_array = [array_len]RocStr{ a, b, c, }; @@ -928,7 +928,7 @@ test "strSplitHelp: overlapping delimiter 1" { strSplitOnHelp(array_ptr, str, delimiter); - var expected = [2]RocStr{ + const expected = [2]RocStr{ RocStr.empty(), RocStr.init("a", 1), }; @@ -953,7 +953,7 @@ test "strSplitHelp: overlapping delimiter 2" { strSplitOnHelp(array_ptr, str, delimiter); - var expected = [3]RocStr{ + const expected = [3]RocStr{ RocStr.empty(), RocStr.empty(), RocStr.empty(), @@ -1364,7 +1364,7 @@ fn strJoinWith(list: RocListStr, separator: RocStr) RocStr { total_size += separator.len() * (len - 1); var result = RocStr.allocate(total_size); - var result_ptr = result.asU8ptrMut(); + const result_ptr = result.asU8ptrMut(); var offset: usize = 0; for (slice[0 .. len - 1]) |substr| { @@ -1943,7 +1943,7 @@ pub fn strTrimEnd(input_string: RocStr) callconv(.C) RocStr { fn countLeadingWhitespaceBytes(string: RocStr) usize { var byte_count: usize = 0; - var bytes = string.asU8ptr()[0..string.len()]; + const bytes = string.asU8ptr()[0..string.len()]; var iter = unicode.Utf8View.initUnchecked(bytes).iterator(); while (iter.nextCodepoint()) |codepoint| { if (isWhitespace(codepoint)) { @@ -1959,7 +1959,7 @@ fn countLeadingWhitespaceBytes(string: RocStr) usize { fn countTrailingWhitespaceBytes(string: RocStr) usize { var byte_count: usize = 0; - var bytes = string.asU8ptr()[0..string.len()]; + const bytes = string.asU8ptr()[0..string.len()]; var iter = ReverseUtf8View.initUnchecked(bytes).iterator(); while (iter.nextCodepoint()) |codepoint| { if (isWhitespace(codepoint)) { diff --git a/crates/compiler/builtins/bitcode/src/utils.zig b/crates/compiler/builtins/bitcode/src/utils.zig index 0b3644f6429..dbf42fa24d6 100644 --- a/crates/compiler/builtins/bitcode/src/utils.zig +++ b/crates/compiler/builtins/bitcode/src/utils.zig @@ -1,6 +1,5 @@ const std = @import("std"); const builtin = @import("builtin"); -const Monotonic = std.builtin.AtomicOrder.Monotonic; const DEBUG_INCDEC = false; const DEBUG_TESTING_ALLOC = false; @@ -56,20 +55,20 @@ fn testing_roc_dbg(loc: *anyopaque, message: *anyopaque, src: *anyopaque) callco comptime { // During tests, use the testing allocators to satisfy these functions. if (builtin.is_test) { - @export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong }); - @export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .Strong }); - @export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .Strong }); - @export(testing_roc_panic, .{ .name = "roc_panic", .linkage = .Strong }); - @export(testing_roc_dbg, .{ .name = "roc_dbg", .linkage = .Strong }); + @export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .strong }); + @export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .strong }); + @export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .strong }); + @export(testing_roc_panic, .{ .name = "roc_panic", .linkage = .strong }); + @export(testing_roc_dbg, .{ .name = "roc_dbg", .linkage = .strong }); if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(testing_roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(testing_roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(testing_roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(testing_roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(testing_roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(testing_roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } } @@ -198,10 +197,10 @@ const Refcount = enum { atomic, }; -const RC_TYPE = Refcount.normal; +const RC_TYPE: Refcount = .normal; pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void { - if (RC_TYPE == Refcount.none) return; + if (RC_TYPE == .none) return; if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { std.debug.print("| increment {*}: ", .{ptr_to_refcount}); @@ -212,7 +211,7 @@ pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void { // Note: we assume that a refcount will never overflow. // As such, we do not need to cap incrementing. switch (RC_TYPE) { - Refcount.normal => { + .normal => { if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { const old = @as(usize, @bitCast(ptr_to_refcount.*)); const new = old + @as(usize, @intCast(amount)); @@ -225,10 +224,10 @@ pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void { ptr_to_refcount.* += amount; }, - Refcount.atomic => { - _ = @atomicRmw(isize, ptr_to_refcount, std.builtin.AtomicRmwOp.Add, amount, Monotonic); + .atomic => { + _ = @atomicRmw(isize, ptr_to_refcount, .Add, amount, .monotonic); }, - Refcount.none => unreachable, + .none => unreachable, } } } @@ -242,7 +241,7 @@ pub fn decrefRcPtrC( // (NOT the start of the data, or the start of the allocation) // this is of course unsafe, but we trust what we get from the llvm side - var bytes = @as([*]isize, @ptrCast(bytes_or_null)); + const bytes = @as([*]isize, @ptrCast(bytes_or_null)); return @call(.always_inline, decref_ptr_to_refcount, .{ bytes, alignment, elements_refcounted }); } @@ -263,7 +262,7 @@ pub fn decrefDataPtrC( alignment: u32, elements_refcounted: bool, ) callconv(.C) void { - var bytes = bytes_or_null orelse return; + const bytes = bytes_or_null orelse return; const data_ptr = @intFromPtr(bytes); const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11; @@ -279,7 +278,7 @@ pub fn increfDataPtrC( bytes_or_null: ?[*]u8, inc_amount: isize, ) callconv(.C) void { - var bytes = bytes_or_null orelse return; + const bytes = bytes_or_null orelse return; const ptr = @intFromPtr(bytes); const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11; @@ -295,7 +294,7 @@ pub fn freeDataPtrC( alignment: u32, elements_refcounted: bool, ) callconv(.C) void { - var bytes = bytes_or_null orelse return; + const bytes = bytes_or_null orelse return; const ptr = @intFromPtr(bytes); const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11; @@ -312,7 +311,7 @@ pub fn freeRcPtrC( alignment: u32, elements_refcounted: bool, ) callconv(.C) void { - var bytes = bytes_or_null orelse return; + const bytes = bytes_or_null orelse return; return free_ptr_to_refcount(bytes, alignment, elements_refcounted); } @@ -326,7 +325,7 @@ pub fn decref( return; } - var bytes = bytes_or_null orelse return; + const bytes = bytes_or_null orelse return; const isizes: [*]isize = @as([*]isize, @ptrCast(@alignCast(bytes))); @@ -338,7 +337,7 @@ inline fn free_ptr_to_refcount( alignment: u32, elements_refcounted: bool, ) void { - if (RC_TYPE == Refcount.none) return; + if (RC_TYPE == .none) return; const ptr_width = @sizeOf(usize); const required_space: usize = if (elements_refcounted) (2 * ptr_width) else ptr_width; const extra_bytes = @max(required_space, alignment); @@ -357,7 +356,7 @@ inline fn decref_ptr_to_refcount( element_alignment: u32, elements_refcounted: bool, ) void { - if (RC_TYPE == Refcount.none) return; + if (RC_TYPE == .none) return; if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { std.debug.print("| decrement {*}: ", .{refcount_ptr}); @@ -371,7 +370,7 @@ inline fn decref_ptr_to_refcount( const refcount: isize = refcount_ptr[0]; if (refcount != REFCOUNT_MAX_ISIZE) { switch (RC_TYPE) { - Refcount.normal => { + .normal => { const old = @as(usize, @bitCast(refcount)); refcount_ptr[0] = refcount -% 1; const new = @as(usize, @bitCast(refcount -% 1)); @@ -387,13 +386,13 @@ inline fn decref_ptr_to_refcount( free_ptr_to_refcount(refcount_ptr, alignment, elements_refcounted); } }, - Refcount.atomic => { - var last = @atomicRmw(isize, &refcount_ptr[0], std.builtin.AtomicRmwOp.Sub, 1, Monotonic); + .atomic => { + const last = @atomicRmw(isize, &refcount_ptr[0], .Sub, 1, .monotonic); if (last == REFCOUNT_ONE_ISIZE) { free_ptr_to_refcount(refcount_ptr, alignment, elements_refcounted); } }, - Refcount.none => unreachable, + .none => unreachable, } } } @@ -401,7 +400,7 @@ inline fn decref_ptr_to_refcount( pub fn isUnique( bytes_or_null: ?[*]u8, ) callconv(.C) bool { - var bytes = bytes_or_null orelse return true; + const bytes = bytes_or_null orelse return true; const ptr = @intFromPtr(bytes); const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11; @@ -487,7 +486,7 @@ pub fn allocateWithRefcount( const extra_bytes = @max(required_space, element_alignment); const length = extra_bytes + data_bytes; - var new_bytes: [*]u8 = alloc(length, alignment) orelse unreachable; + const new_bytes: [*]u8 = alloc(length, alignment) orelse unreachable; if (DEBUG_ALLOC and builtin.target.cpu.arch != .wasm32) { std.debug.print("+ allocated {*} ({} bytes with alignment {})\n", .{ new_bytes, data_bytes, alignment }); @@ -495,7 +494,7 @@ pub fn allocateWithRefcount( const data_ptr = new_bytes + extra_bytes; const refcount_ptr = @as([*]usize, @ptrCast(@as([*]align(ptr_width) u8, @alignCast(data_ptr)) - ptr_width)); - refcount_ptr[0] = if (RC_TYPE == Refcount.none) REFCOUNT_MAX_ISIZE else REFCOUNT_ONE; + refcount_ptr[0] = if (RC_TYPE == .none) REFCOUNT_MAX_ISIZE else REFCOUNT_ONE; return data_ptr; } @@ -546,14 +545,14 @@ pub const UpdateMode = enum(u8) { test "increfC, refcounted data" { var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17; - var ptr_to_refcount: *isize = &mock_rc; + const ptr_to_refcount: *isize = &mock_rc; increfRcPtrC(ptr_to_refcount, 2); try std.testing.expectEqual(mock_rc, REFCOUNT_ONE_ISIZE + 19); } test "increfC, static data" { var mock_rc: isize = REFCOUNT_MAX_ISIZE; - var ptr_to_refcount: *isize = &mock_rc; + const ptr_to_refcount: *isize = &mock_rc; increfRcPtrC(ptr_to_refcount, 2); try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE); } diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index d4a3e445aeb..4feaf0b611c 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -44,7 +44,7 @@ pub fn call_bitcode_fn<'ctx>( if ret.get_type() == vec_type.into() { return env .builder - .build_bitcast(ret, env.context.i128_type(), "return_i128") + .build_bit_cast(ret, env.context.i128_type(), "return_i128") .unwrap(); } } else if env.target == roc_target::Target::MacArm64 { @@ -265,7 +265,7 @@ fn build_transform_caller_help<'a, 'ctx>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let arg_type = env.context.i8_type().ptr_type(AddressSpace::default()); + let arg_type = env.context.ptr_type(AddressSpace::default()); let function_value = crate::llvm::refcounting::build_header_help( env, @@ -302,9 +302,7 @@ fn build_transform_caller_help<'a, 'ctx>( bumpalo::collections::Vec::with_capacity_in(arguments.len(), env.arena); for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) { - let basic_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(*layout)) - .ptr_type(AddressSpace::default()); + let basic_type = env.context.ptr_type(AddressSpace::default()); let cast_ptr = env.builder.new_build_pointer_cast( argument_ptr.into_pointer_value(), @@ -333,9 +331,7 @@ fn build_transform_caller_help<'a, 'ctx>( // the function doesn't expect a closure argument, nothing to add } (true, layout) => { - let closure_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)) - .ptr_type(AddressSpace::default()); + let closure_type = env.context.ptr_type(AddressSpace::default()); let closure_cast = env.builder.new_build_pointer_cast( closure_ptr, @@ -442,7 +438,7 @@ fn build_rc_wrapper<'a, 'ctx>( let function_value = match env.module.get_function(fn_name.as_str()) { Some(function_value) => function_value, None => { - let arg_type = env.context.i8_type().ptr_type(AddressSpace::default()); + let arg_type = env.context.ptr_type(AddressSpace::default()); let function_value = match rc_operation { Mode::Inc | Mode::Dec => crate::llvm::refcounting::build_header_help( @@ -479,7 +475,7 @@ fn build_rc_wrapper<'a, 'ctx>( let value_type = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); - let value_ptr_type = value_type.ptr_type(AddressSpace::default()); + let value_ptr_type = env.context.ptr_type(AddressSpace::default()); let value_ptr = env.builder.new_build_pointer_cast( generic_value_ptr, value_ptr_type, @@ -541,7 +537,7 @@ pub fn build_eq_wrapper<'a, 'ctx>( let function_value = match env.module.get_function(fn_name.as_str()) { Some(function_value) => function_value, None => { - let arg_type = env.context.i8_type().ptr_type(AddressSpace::default()); + let arg_type = env.context.ptr_type(AddressSpace::default()); let function_value = crate::llvm::refcounting::build_header_help( env, @@ -570,9 +566,7 @@ pub fn build_eq_wrapper<'a, 'ctx>( value_ptr1.set_name(Symbol::ARG_1.as_str(&env.interns)); value_ptr2.set_name(Symbol::ARG_2.as_str(&env.interns)); - let value_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)) - .ptr_type(AddressSpace::default()); + let value_type = env.context.ptr_type(AddressSpace::default()); let value_cast1 = env.builder @@ -639,7 +633,7 @@ pub fn build_compare_wrapper<'a, 'ctx>( let function_value = match env.module.get_function(fn_name) { Some(function_value) => function_value, None => { - let arg_type = env.context.i8_type().ptr_type(AddressSpace::default()); + let arg_type = env.context.ptr_type(AddressSpace::default()); let function_value = crate::llvm::refcounting::build_header_help( env, @@ -673,9 +667,7 @@ pub fn build_compare_wrapper<'a, 'ctx>( value_ptr1.set_name(Symbol::ARG_2.as_str(&env.interns)); value_ptr2.set_name(Symbol::ARG_3.as_str(&env.interns)); - let value_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); - let value_ptr_type = value_type.ptr_type(AddressSpace::default()); + let value_ptr_type = env.context.ptr_type(AddressSpace::default()); let value_cast1 = env.builder @@ -718,7 +710,7 @@ pub fn build_compare_wrapper<'a, 'ctx>( layout_interner, layout_interner.get_repr(closure_data_repr), ); - let closure_ptr_type = closure_type.ptr_type(AddressSpace::default()); + let closure_ptr_type = env.context.ptr_type(AddressSpace::default()); let closure_cast = env.builder.new_build_pointer_cast( closure_ptr, @@ -781,7 +773,7 @@ pub fn build_copy_wrapper<'a, 'ctx>( let function_value = match env.module.get_function(fn_name.as_str()) { Some(function_value) => function_value, None => { - let arg_type = env.context.i8_type().ptr_type(AddressSpace::default()); + let arg_type = env.context.ptr_type(AddressSpace::default()); let function_value = crate::llvm::refcounting::build_header_help( env, @@ -811,8 +803,7 @@ pub fn build_copy_wrapper<'a, 'ctx>( src_ptr.set_name(Symbol::ARG_2.as_str(&env.interns)); let repr = layout_interner.get_repr(layout); - let value_type = basic_type_from_layout(env, layout_interner, repr) - .ptr_type(AddressSpace::default()); + let value_type = env.context.ptr_type(AddressSpace::default()); let dst_cast = env .builder @@ -986,7 +977,7 @@ fn ptr_len_cap<'ctx>( let ptr = env.builder.new_build_int_to_ptr( lower_word, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "list_ptr", ); diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 023ca5c13e5..241d35c2570 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -23,7 +23,7 @@ use inkwell::debug_info::{ }; use inkwell::memory_buffer::MemoryBuffer; use inkwell::module::{Linkage, Module}; -use inkwell::passes::{PassManager, PassManagerBuilder}; +use inkwell::passes::PassManager; use inkwell::types::{ AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FloatMathType, FunctionType, IntMathType, IntType, PointerMathType, StructType, @@ -33,8 +33,8 @@ use inkwell::values::{ FunctionValue, InstructionOpcode, InstructionValue, IntMathValue, IntValue, PhiValue, PointerMathValue, PointerValue, StructValue, }; +use inkwell::FloatPredicate; use inkwell::{AddressSpace, IntPredicate}; -use inkwell::{FloatPredicate, OptimizationLevel}; use morphic_lib::{ CalleeSpecVar, FuncName, FuncSpec, FuncSpecSolutions, ModSolutions, UpdateMode, UpdateModeVar, }; @@ -370,7 +370,7 @@ impl<'ctx> BuilderExt<'ctx> for Builder<'ctx> { T: BasicType<'ctx>, V: BasicValue<'ctx>, { - self.build_bitcast(val, ty, name).unwrap() + self.build_bit_cast(val, ty, name).unwrap() } fn new_build_pointer_cast>( @@ -1065,6 +1065,7 @@ pub fn module_from_builtins<'ctx>( "__modti3", "__muloti4", "__udivti3", + "__umodti3", // Roc special functions "__roc_force_longjmp", "__roc_force_setjmp", @@ -1083,7 +1084,7 @@ pub fn module_from_builtins<'ctx>( // Note, running DCE here is faster then waiting until full app DCE. let mpm = PassManager::create(()); - mpm.add_global_dce_pass(); + mpm.run_on(&module); // Now that the unused compiler-rt functions have been removed, @@ -1101,80 +1102,6 @@ pub fn module_from_builtins<'ctx>( module } -pub fn construct_optimization_passes<'a>( - module: &'a Module, - opt_level: OptLevel, -) -> (PassManager>, PassManager>) { - let mpm = PassManager::create(()); - let fpm = PassManager::create(module); - - // remove unused global values (e.g. those defined by zig, but unused in user code) - mpm.add_global_dce_pass(); - - mpm.add_always_inliner_pass(); - - // tail-call elimination is always on - fpm.add_instruction_combining_pass(); - fpm.add_tail_call_elimination_pass(); - - let pmb = PassManagerBuilder::create(); - match opt_level { - OptLevel::Development | OptLevel::Normal => { - pmb.set_optimization_level(OptimizationLevel::None); - } - OptLevel::Size => { - pmb.set_optimization_level(OptimizationLevel::Default); - // 2 is equivalent to `-Oz`. - pmb.set_size_level(2); - - // TODO: For some usecase, like embedded, it is useful to expose this and tune it. - // This really depends on if inlining causes enough simplifications to reduce code size. - pmb.set_inliner_with_threshold(50); - } - OptLevel::Optimize => { - pmb.set_optimization_level(OptimizationLevel::Aggressive); - // this threshold seems to do what we want - pmb.set_inliner_with_threshold(750); - } - } - - // Add extra optimization passes for Optimize. - if matches!(opt_level, OptLevel::Optimize) { - // TODO: figure out which of these actually help. - // Note, llvm probably already runs all of these as part of Aggressive. - - // function passes - - fpm.add_cfg_simplification_pass(); - mpm.add_cfg_simplification_pass(); - - fpm.add_jump_threading_pass(); - mpm.add_jump_threading_pass(); - - fpm.add_memcpy_optimize_pass(); // this one is very important - - fpm.add_licm_pass(); - - // turn invoke into call - // TODO: is this pass needed. It theoretically prunes unused exception handling info. - // This seems unrelated to the comment above. It also seems to be missing in llvm-16. - // mpm.add_prune_eh_pass(); - - // remove unused global values (often the `_wrapper` can be removed) - mpm.add_global_dce_pass(); - - mpm.add_function_inlining_pass(); - } - - pmb.populate_module_pass_manager(&mpm); - pmb.populate_function_pass_manager(&fpm); - - fpm.initialize(); - - // For now, we have just one of each - (mpm, fpm) -} - fn promote_to_main_function<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, @@ -1247,8 +1174,8 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx>( let roc_main_fn = function_value_by_func_spec(env, FuncBorrowSpec::Some(*func_spec), symbol); let output_type = match roc_main_fn.get_type().get_return_type() { - Some(return_type) => { - let output_type = return_type.ptr_type(AddressSpace::default()); + Some(..) => { + let output_type = env.context.ptr_type(AddressSpace::default()); output_type.into() } None => { @@ -1441,7 +1368,7 @@ fn small_str_ptr_width_8<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> Po let cap = env.ptr_int().const_int(word3, false); let address_space = AddressSpace::default(); - let ptr_type = env.context.i8_type().ptr_type(address_space); + let ptr_type = env.context.ptr_type(address_space); let ptr = env.builder.new_build_int_to_ptr(ptr, ptr_type, "to_u8_ptr"); const_str_alloca_ptr(env, ptr, len, cap) @@ -1465,7 +1392,7 @@ fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> St let cap = env.ptr_int().const_int(word3 as u64, false); let address_space = AddressSpace::default(); - let ptr_type = env.context.i8_type().ptr_type(address_space); + let ptr_type = env.context.ptr_type(address_space); let ptr = env.builder.new_build_int_to_ptr(ptr, ptr_type, "to_u8_ptr"); struct_from_fields( @@ -1604,7 +1531,7 @@ fn struct_pointer_from_fields<'a, 'ctx, 'env, I>( .builder .new_build_bitcast( input_pointer, - struct_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "struct_ptr", ) .into_pointer_value(); @@ -1941,7 +1868,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let data_ptr = env.builder.new_build_pointer_cast( opaque_data_ptr, - struct_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_data_pointer", ); @@ -2295,7 +2222,7 @@ fn build_tag_field_value<'a, 'ctx>( env.builder .new_build_pointer_cast( value.into_pointer_value(), - env.context.i64_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_recursive_pointer", ) .into() @@ -2468,7 +2395,7 @@ fn build_tag<'a, 'ctx>( RocUnion::untagged_from_slices(layout_interner, env.context, &[other_fields]); if tag_id == *nullable_id as u16 { - let output_type = roc_union.struct_type().ptr_type(AddressSpace::default()); + let output_type = env.context.ptr_type(AddressSpace::default()); return output_type.const_null().into(); } @@ -2518,7 +2445,7 @@ fn tag_pointer_set_tag_id<'ctx>( let cast_pointer = env.builder.new_build_pointer_cast( pointer, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_i8_ptr", ); @@ -2577,7 +2504,7 @@ pub fn tag_pointer_clear_tag_id<'ctx>( let cast_pointer = env.builder.new_build_pointer_cast( pointer, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_i8_ptr", ); @@ -2791,7 +2718,7 @@ fn union_field_ptr_at_index_help<'a, 'ctx>( let data_ptr = env.builder.new_build_pointer_cast( value, - struct_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_lookup_at_index_ptr", ); @@ -2842,17 +2769,11 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>( RocUnion::untagged_from_slices(layout_interner, env.context, fields) }; - reserve_union_with_refcount_help( - env, - roc_union.struct_type(), - roc_union.tag_width(), - roc_union.tag_alignment(), - ) + reserve_union_with_refcount_help(env, roc_union.tag_width(), roc_union.tag_alignment()) } -fn reserve_union_with_refcount_help<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, - basic_type: impl BasicType<'ctx>, +fn reserve_union_with_refcount_help<'ctx>( + env: &Env<'_, 'ctx, '_>, stack_size: u32, alignment_bytes: u32, ) -> PointerValue<'ctx> { @@ -2862,18 +2783,11 @@ fn reserve_union_with_refcount_help<'a, 'ctx, 'env>( // elem_refcounted does not apply to unions, only lists. let elem_refcounted = env.context.bool_type().const_zero().into(); - allocate_with_refcount_help( - env, - basic_type, - alignment_bytes, - value_bytes_intvalue, - elem_refcounted, - ) + allocate_with_refcount_help(env, alignment_bytes, value_bytes_intvalue, elem_refcounted) } -pub fn allocate_with_refcount_help<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, - value_type: impl BasicType<'ctx>, +pub fn allocate_with_refcount_help<'ctx>( + env: &Env<'_, 'ctx, '_>, alignment_bytes: u32, number_of_data_bytes: IntValue<'ctx>, elem_refcounted: BasicValueEnum<'ctx>, @@ -2889,7 +2803,7 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>( ) .into_pointer_value(); - let ptr_type = value_type.ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); env.builder .new_build_pointer_cast(ptr, ptr_type, "alloc_cast_to_desired") @@ -3094,9 +3008,7 @@ pub fn store_roc_value_opaque<'a, 'ctx>( opaque_destination: PointerValue<'ctx>, value: BasicValueEnum<'ctx>, ) { - let target_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)) - .ptr_type(AddressSpace::default()); + let target_type = env.context.ptr_type(AddressSpace::default()); let destination = env.builder.new_build_pointer_cast( opaque_destination, target_type, @@ -3910,7 +3822,7 @@ fn complex_bitcast_from_bigger_than_to<'ctx>( // then read it back as a different type let to_type_pointer = builder.new_build_pointer_cast( argument_pointer, - to_type.ptr_type(inkwell::AddressSpace::default()), + env.context.ptr_type(inkwell::AddressSpace::default()), name, ); @@ -3932,9 +3844,7 @@ fn complex_bitcast_to_bigger_than_from<'ctx>( // then cast the pointer to our desired type let from_type_pointer = builder.new_build_pointer_cast( storage, - from_value - .get_type() - .ptr_type(inkwell::AddressSpace::default()), + env.context.ptr_type(inkwell::AddressSpace::default()), name, ); @@ -4301,8 +4211,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( let output_type = roc_function.get_type().get_param_types().pop().unwrap(); argument_types.insert(0, output_type); } - Some(return_type) => { - let output_type = return_type.ptr_type(AddressSpace::default()); + Some(..) => { + let output_type = env.context.ptr_type(AddressSpace::default()); argument_types.insert(0, output_type.into()); } } @@ -4354,7 +4264,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( // bitcast the ptr let fastcc_ptr = env.builder.new_build_pointer_cast( arg.into_pointer_value(), - fastcc_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "bitcast_arg", ); @@ -4495,7 +4405,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( let return_type = wrapper_return_type; let c_function_spec = { - let output_type = return_type.ptr_type(AddressSpace::default()); + let output_type = env.context.ptr_type(AddressSpace::default()); argument_types.push(output_type.into()); FunctionSpec::cconv(env, CCReturn::Void, None, &argument_types) }; @@ -4671,10 +4581,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>( let c_abi_roc_str_type = env.context.struct_type( &[ - env.context - .i8_type() - .ptr_type(AddressSpace::default()) - .into(), + env.context.ptr_type(AddressSpace::default()).into(), env.ptr_int().into(), env.ptr_int().into(), ], @@ -4815,7 +4722,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>( // bitcast the ptr let fastcc_ptr = env.builder.new_build_pointer_cast( arg.into_pointer_value(), - fastcc_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "bitcast_arg", ); @@ -5007,7 +4914,7 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> { env.builder.new_build_pointer_cast( global.as_pointer_value(), - env.context.i32_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_sjlj_buffer", ) } @@ -5024,15 +4931,11 @@ pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> // Anywhere else, use the LLVM intrinsic. // https://llvm.org/docs/ExceptionHandling.html#llvm-eh-sjlj-setjmp - let buf_type = env - .context - .i8_type() - .ptr_type(AddressSpace::default()) - .array_type(5); + let buf_type = env.context.ptr_type(AddressSpace::default()).array_type(5); let jmp_buf_i8p_arr = env.builder.new_build_pointer_cast( jmp_buf, - buf_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "jmp_buf [5 x i8*]", ); @@ -5073,7 +4976,7 @@ pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> .builder .new_build_pointer_cast( jmp_buf, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "jmp_buf i8*", ) .into(); @@ -5245,7 +5148,7 @@ fn roc_call_result_type<'ctx>( env.context.struct_type( &[ env.context.i64_type().into(), - zig_str_type(env).ptr_type(AddressSpace::default()).into(), + env.context.ptr_type(AddressSpace::default()).into(), return_type, ], false, @@ -5698,8 +5601,6 @@ fn build_procedures_help<'a>( &mut layout_ids, ); - let (_, function_pass) = construct_optimization_passes(env.module, opt_level); - for (proc, fn_vals) in headers { for (func_spec_solutions, fn_val) in fn_vals { let mut current_scope = scope.clone(); @@ -5722,9 +5623,7 @@ fn build_procedures_help<'a>( // call finalize() before any code generation/verification env.dibuilder.finalize(); - if fn_val.verify(true) { - function_pass.run_on(&fn_val); - } else { + if !fn_val.verify(true) { let mode = "NON-OPTIMIZED"; eprintln!( @@ -5977,23 +5876,11 @@ fn build_closure_caller<'a, 'ctx>( ) { let mut argument_types = Vec::with_capacity_in(arguments.len() + 3, env.arena); - for layout in arguments { - let arg_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(*layout)); - let arg_ptr_type = arg_type.ptr_type(AddressSpace::default()); - - argument_types.push(arg_ptr_type.into()); + for _ in arguments { + argument_types.push(env.context.ptr_type(AddressSpace::default()).into()); } - let closure_argument_type = { - let basic_type = basic_type_from_layout( - env, - layout_interner, - layout_interner.get_repr(lambda_set.runtime_representation()), - ); - - basic_type.ptr_type(AddressSpace::default()) - }; + let closure_argument_type = env.context.ptr_type(AddressSpace::default()); argument_types.push(closure_argument_type.into()); let context = &env.context; @@ -6002,7 +5889,7 @@ fn build_closure_caller<'a, 'ctx>( let result_type = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(result)); - let output_type = { result_type.ptr_type(AddressSpace::default()) }; + let output_type = { env.context.ptr_type(AddressSpace::default()) }; argument_types.push(output_type.into()); // STEP 1: build function header @@ -6251,7 +6138,7 @@ fn roc_call_erased_with_args<'a, 'ctx>( ) -> BasicValueEnum<'ctx> { let function_type = fn_ptr::function_type(env, layout_interner, argument_layouts, result_layout); - let function_ptr_type = function_type.ptr_type(AddressSpace::default()); + let function_ptr_type = env.context.ptr_type(AddressSpace::default()); let function_pointer = fn_ptr::cast_to_function_ptr_type(env, pointer, function_ptr_type); @@ -6473,7 +6360,7 @@ fn to_cc_type<'a, 'ctx>( let stack_type = basic_type_from_layout(env, layout_interner, layout_repr); if layout_repr.is_passed_by_reference(layout_interner) { - stack_type.ptr_type(AddressSpace::default()).into() + env.context.ptr_type(AddressSpace::default()).into() } else { stack_type } @@ -6493,18 +6380,7 @@ fn to_cc_type_builtin<'a, 'ctx>( Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal => { basic_type_from_builtin(env, builtin) } - Builtin::Str | Builtin::List(_) => { - let address_space = AddressSpace::default(); - let field_types: [BasicTypeEnum; 3] = [ - env.context.i8_type().ptr_type(address_space).into(), - env.ptr_int().into(), - env.ptr_int().into(), - ]; - - let struct_type = env.context.struct_type(&field_types, false); - - struct_type.ptr_type(address_space).into() - } + Builtin::Str | Builtin::List(_) => env.context.ptr_type(AddressSpace::default()).into(), } } @@ -6584,7 +6460,7 @@ impl<'ctx> FunctionSpec<'ctx> { let (typ, opt_sret_parameter) = match cc_return { CCReturn::ByPointer => { // turn the output type into a pointer type. Make it the first argument to the function - let output_type = return_type.unwrap().ptr_type(AddressSpace::default()); + let output_type = env.context.ptr_type(AddressSpace::default()); let mut arguments: Vec<'_, BasicTypeEnum> = bumpalo::vec![in env.arena; output_type.into()]; @@ -6628,7 +6504,7 @@ impl<'ctx> FunctionSpec<'ctx> { return_type.fn_type(&function_arguments(env, &argument_types), false) } RocReturn::ByPointer => { - argument_types.push(return_type.ptr_type(AddressSpace::default()).into()); + argument_types.push(env.context.ptr_type(AddressSpace::default()).into()); env.context .void_type() .fn_type(&function_arguments(env, &argument_types), false) @@ -6888,7 +6764,7 @@ fn define_global_str_literal_ptr<'ctx>( let ptr = env.builder.new_build_pointer_cast( global.as_pointer_value(), - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_opaque", ); diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index bc50be56f6b..0968a9319bc 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -2,7 +2,7 @@ use crate::llvm::bitcode::build_dec_wrapper; use crate::llvm::build::{allocate_with_refcount_help, cast_basic_basic, Env, RocFunctionCall}; use crate::llvm::convert::basic_type_from_layout; use inkwell::builder::Builder; -use inkwell::types::{BasicType, PointerType}; +use inkwell::types::PointerType; use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue}; use inkwell::{AddressSpace, IntPredicate}; use morphic_lib::UpdateMode; @@ -73,7 +73,7 @@ fn pass_element_as_opaque<'a, 'ctx>( env.builder .new_build_pointer_cast( element_ptr, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "pass_element_as_opaque", ) .into() @@ -110,7 +110,7 @@ pub(crate) fn pass_as_opaque<'ctx>( env.builder .new_build_pointer_cast( ptr, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "pass_as_opaque", ) .into() @@ -155,7 +155,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx>( ); // listGetUnsafe takes a U64, but we need to convert that to usize for index calculation. let elem_index = builder.new_build_int_cast(elem_index, env.ptr_int(), "u64_to_usize"); - let ptr_type = elem_type.ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); // Load the pointer to the array data let array_data_ptr = load_list_ptr(env, wrapper_struct, ptr_type); @@ -728,18 +728,9 @@ pub(crate) fn allocate_list<'a, 'ctx>( let bytes_per_element = len_type.const_int(elem_bytes, false); let number_of_data_bytes = builder.new_build_int_mul(bytes_per_element, number_of_elements, "data_length"); - - let basic_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(elem_layout)); let alignment_bytes = layout_interner.alignment_bytes(elem_layout); let elem_refcounted = layout_refcounted(env, layout_interner, elem_layout); - allocate_with_refcount_help( - env, - basic_type, - alignment_bytes, - number_of_data_bytes, - elem_refcounted, - ) + allocate_with_refcount_help(env, alignment_bytes, number_of_data_bytes, elem_refcounted) } pub(crate) fn store_list<'ctx>( diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 976e50aed6c..5a42203fb0c 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -3,7 +3,6 @@ use crate::llvm::build_list::{list_len_usize, load_list_ptr}; use crate::llvm::build_str::str_equal; use crate::llvm::convert::basic_type_from_layout; use bumpalo::collections::Vec; -use inkwell::types::BasicType; use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue}; use inkwell::{AddressSpace, FloatPredicate, IntPredicate}; use roc_builtins::bitcode; @@ -528,7 +527,7 @@ fn build_list_eq_help<'a, 'ctx>( let builder = env.builder; let element_type = basic_type_from_layout(env, layout_interner, element_layout); - let ptr_type = element_type.ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr1 = load_list_ptr(env, list1, ptr_type); let ptr2 = load_list_ptr(env, list2, ptr_type); @@ -1286,13 +1285,13 @@ fn eq_ptr_to_struct<'a, 'ctx>( // cast the opaque pointer to a pointer of the correct shape let struct1_ptr = env.builder.new_build_pointer_cast( tag1, - wrapper_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "opaque_to_correct", ); let struct2_ptr = env.builder.new_build_pointer_cast( tag2, - wrapper_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "opaque_to_correct", ); diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index 079d5c2b794..9ad8c556302 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -1,7 +1,7 @@ -use crate::llvm::build::{BuilderExt, Env, FunctionSpec, RocReturn}; +use crate::llvm::build::{BuilderExt, Env}; use crate::llvm::erased; use crate::llvm::memcpy::build_memcpy; -use bumpalo::collections::{CollectIn, Vec as AVec}; +use bumpalo::collections::Vec as AVec; use inkwell::context::Context; use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType}; use inkwell::values::PointerValue; @@ -32,37 +32,18 @@ pub fn basic_type_from_layout<'a, 'ctx>( layout_interner.get_repr(lambda_set.runtime_representation()), ), - Ptr(inner_layout) => { - let inner_type = basic_type_from_layout( - env, - layout_interner, - layout_interner.get_repr(inner_layout), - ); - - inner_type.ptr_type(AddressSpace::default()).into() - } + Ptr(..) => env.context.ptr_type(AddressSpace::default()).into(), Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout), RecursivePointer(_) => env .context - .i64_type() .ptr_type(AddressSpace::default()) .as_basic_type_enum(), - FunctionPointer(self::FunctionPointer { args, ret }) => { - let args = args.iter().map(|arg| { - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(*arg)) - }); - - let ret_repr = layout_interner.get_repr(ret); - let ret = basic_type_from_layout(env, layout_interner, ret_repr); - - let roc_return = RocReturn::from_layout(layout_interner, ret_repr); - - let fn_spec = FunctionSpec::fastcc(env, roc_return, ret, args.collect_in(env.arena)); - - fn_spec.typ.ptr_type(AddressSpace::default()).into() + FunctionPointer(self::FunctionPointer { .. }) => { + env.context.ptr_type(AddressSpace::default()).into() } + Erased(_) => erased::basic_type(env).into(), Builtin(builtin) => basic_type_from_builtin(env, &builtin), @@ -136,7 +117,7 @@ fn basic_type_from_union_layout<'a, 'ctx>( Recursive(_) | NonNullableUnwrapped(_) | NullableWrapped { .. } - | NullableUnwrapped { .. } => struct_type.ptr_type(AddressSpace::default()).into(), + | NullableUnwrapped { .. } => env.context.ptr_type(AddressSpace::default()).into(), } } @@ -188,7 +169,7 @@ pub fn argument_type_from_layout<'a, 'ctx>( let base = basic_type_from_layout(env, layout_interner, layout); if layout.is_passed_by_reference(layout_interner) { - base.ptr_type(AddressSpace::default()).into() + env.context.ptr_type(AddressSpace::default()).into() } else { base } @@ -208,7 +189,7 @@ fn argument_type_from_struct_layout<'a, 'ctx>( let stack_type = basic_type_from_layout(env, layout_interner, struct_layout); if struct_layout.is_passed_by_reference(layout_interner) { - stack_type.ptr_type(AddressSpace::default()).into() + env.context.ptr_type(AddressSpace::default()).into() } else { stack_type } @@ -223,7 +204,7 @@ pub fn argument_type_from_union_layout<'a, 'ctx>( let heap_type = basic_type_from_union_layout(env, layout_interner, union_layout); if let UnionLayout::NonRecursive(_) = union_layout { - heap_type.ptr_type(AddressSpace::default()).into() + env.context.ptr_type(AddressSpace::default()).into() } else { heap_type } @@ -415,7 +396,7 @@ impl<'ctx> RocUnion<'ctx> { RocStruct::ByValue(value) => { let cast_pointer = env.builder.new_build_pointer_cast( data_buffer, - value.get_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_data_ptr", ); env.builder.new_build_store(cast_pointer, value); @@ -482,7 +463,7 @@ pub fn zig_dec_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> { } pub fn zig_has_tag_id_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> { - let u8_ptr_t = env.context.i8_type().ptr_type(AddressSpace::default()); + let u8_ptr_t = env.context.ptr_type(AddressSpace::default()); env.context .struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false) diff --git a/crates/compiler/gen_llvm/src/llvm/erased.rs b/crates/compiler/gen_llvm/src/llvm/erased.rs index 375b2b8e598..38e08bffbe9 100644 --- a/crates/compiler/gen_llvm/src/llvm/erased.rs +++ b/crates/compiler/gen_llvm/src/llvm/erased.rs @@ -8,16 +8,11 @@ use roc_mono::ir::ErasedField; use super::build::{BuilderExt, Env}; pub fn opaque_ptr_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerType<'ctx> { - env.context.i8_type().ptr_type(AddressSpace::default()) + env.context.ptr_type(AddressSpace::default()) } fn refcounter_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerType<'ctx> { - let return_void = env.context.void_type(); - let arg_ty = opaque_ptr_type(env); - - return_void - .fn_type(&[arg_ty.into()], false) - .ptr_type(AddressSpace::default()) + env.context.ptr_type(AddressSpace::default()) } /// Erased is laid out like @@ -52,7 +47,7 @@ fn bitcast_to_opaque_ptr<'ctx>( env.builder .new_build_bitcast( value, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_opaque_ptr", ) .into_pointer_value() diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 84b6324776b..9c684ecd67f 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -100,7 +100,7 @@ fn read_state<'ctx>( env: &Env<'_, 'ctx, '_>, ptr: PointerValue<'ctx>, ) -> (IntValue<'ctx>, IntValue<'ctx>) { - let ptr_type = env.ptr_int().ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr = env.builder.new_build_pointer_cast(ptr, ptr_type, ""); let one = env.ptr_int().const_int(1, false); @@ -120,7 +120,7 @@ fn write_state<'ctx>( count: IntValue<'ctx>, offset: IntValue<'ctx>, ) { - let ptr_type = env.ptr_int().ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr = env.builder.new_build_pointer_cast(ptr, ptr_type, ""); let one = env.ptr_int().const_int(1, false); @@ -249,7 +249,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>( ) }; - let u32_ptr = env.context.i32_type().ptr_type(AddressSpace::default()); + let u32_ptr = env.context.ptr_type(AddressSpace::default()); let ptr = env .builder .new_build_pointer_cast(ptr, u32_ptr, "cast_ptr_type"); @@ -321,7 +321,7 @@ fn build_clone<'a, 'ctx>( ) }; - let ptr_type = value.get_type().ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr = env .builder .new_build_pointer_cast(ptr, ptr_type, "cast_ptr_type"); @@ -446,10 +446,7 @@ fn build_clone_tag<'a, 'ctx>( let function_type = env.ptr_int().fn_type( &[ - env.context - .i8_type() - .ptr_type(AddressSpace::default()) - .into(), + env.context.ptr_type(AddressSpace::default()).into(), env.ptr_int().into(), env.ptr_int().into(), BasicMetadataTypeEnum::from(value.get_type()), @@ -523,7 +520,7 @@ fn load_tag_data<'a, 'ctx>( let data_ptr = env.builder.new_build_pointer_cast( raw_data_ptr, - tag_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "data_ptr", ); @@ -545,7 +542,7 @@ fn clone_tag_payload_and_id<'a, 'ctx>( let payload_ptr = env.builder.new_build_pointer_cast( opaque_payload_ptr, - payload_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_payload_ptr", ); @@ -948,7 +945,7 @@ fn build_copy<'ctx>( ) }; - let ptr_type = value.get_type().ptr_type(AddressSpace::default()); + let ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr = env .builder .new_build_pointer_cast(ptr, ptr_type, "cast_ptr_type"); @@ -1016,18 +1013,16 @@ fn build_clone_builtin<'a, 'ctx>( let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, elements_start_offset); let src = bd.new_build_pointer_cast( elements, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_bytes_pointer", ); bd.build_memcpy(dest, 1, src, 1, elements_width).unwrap(); bd.new_build_int_add(elements_start_offset, elements_width, "new_offset") } else { - let element_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(elem)); let elements = bd.new_build_pointer_cast( elements, - element_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "elements", ); diff --git a/crates/compiler/gen_llvm/src/llvm/externs.rs b/crates/compiler/gen_llvm/src/llvm/externs.rs index 8d091b64eae..cbe76980598 100644 --- a/crates/compiler/gen_llvm/src/llvm/externs.rs +++ b/crates/compiler/gen_llvm/src/llvm/externs.rs @@ -19,7 +19,7 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) { let builder = env.builder; let usize_type = env.ptr_int(); - let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::default()); + let i8_ptr_type = env.context.ptr_type(AddressSpace::default()); match env.mode { super::build::LlvmBackendMode::CliTest => { @@ -331,7 +331,7 @@ pub fn build_longjmp_call(env: &Env) { // Call the LLVM-intrinsic longjmp: `void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf)` let jmp_buf_i8p = env.builder.new_build_pointer_cast( jmp_buf, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "jmp_buf i8*", ); let _call = env.build_intrinsic_call(LLVM_LONGJMP, &[jmp_buf_i8p.into()]); diff --git a/crates/compiler/gen_llvm/src/llvm/intrinsics.rs b/crates/compiler/gen_llvm/src/llvm/intrinsics.rs index 728f080c5e4..208c70b521a 100644 --- a/crates/compiler/gen_llvm/src/llvm/intrinsics.rs +++ b/crates/compiler/gen_llvm/src/llvm/intrinsics.rs @@ -75,8 +75,7 @@ pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) { // // https://releases.llvm.org/10.0.0/docs/LangRef.html#standard-c-library-intrinsics let i1_type = ctx.bool_type(); - let i8_type = ctx.i8_type(); - let i8_ptr_type = i8_type.ptr_type(AddressSpace::default()); + let i8_ptr_type = ctx.ptr_type(AddressSpace::default()); let i32_type = ctx.i32_type(); let void_type = ctx.void_type(); @@ -139,7 +138,7 @@ pub static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64"; pub static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32"; pub static LLVM_FRAME_ADDRESS: &str = "llvm.frameaddress.p0"; -pub static LLVM_STACK_SAVE: &str = "llvm.stacksave"; +pub static LLVM_STACK_SAVE: &str = "llvm.stacksave.p0"; pub static LLVM_SETJMP: &str = "llvm.eh.sjlj.setjmp"; pub static LLVM_LONGJMP: &str = "llvm.eh.sjlj.longjmp"; diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 95659e66b68..d414ce8dc3b 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1,7 +1,7 @@ use inkwell::{ attributes::{Attribute, AttributeLoc}, module::Linkage, - types::{BasicType, IntType}, + types::IntType, values::{ BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionOpcode, IntValue, StructValue, @@ -237,12 +237,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( intrinsic, ); - let roc_return_type = basic_type_from_layout( - env, - layout_interner, - layout_interner.get_repr(layout), - ) - .ptr_type(AddressSpace::default()); + let roc_return_type = env.context.ptr_type(AddressSpace::default()); let roc_return_alloca = env.builder.new_build_pointer_cast( zig_return_alloca, @@ -331,12 +326,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( intrinsic, ); - let roc_return_type = basic_type_from_layout( - env, - layout_interner, - layout_interner.get_repr(layout), - ) - .ptr_type(AddressSpace::default()); + let roc_return_type = env.context.ptr_type(AddressSpace::default()); let roc_return_alloca = env.builder.new_build_pointer_cast( zig_return_alloca, @@ -1385,7 +1375,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( let ptr = env.builder.new_build_pointer_cast( data_ptr.into_pointer_value(), - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_i8_ptr", ); @@ -2000,7 +1990,7 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu let ptr = env.builder.new_build_pointer_cast( alloca, - value.get_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_i128_ptr", ); @@ -2021,7 +2011,7 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu instruction.set_alignment(16).unwrap(); let ptr = env.builder.new_build_pointer_cast( alloca, - value.get_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_i128_ptr", ); env.builder.new_build_store(ptr, value); @@ -2510,12 +2500,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>( intrinsic, ); - let roc_return_type = basic_type_from_layout( - env, - layout_interner, - layout_interner.get_repr(return_layout), - ) - .ptr_type(AddressSpace::default()); + let roc_return_type = env.context.ptr_type(AddressSpace::default()); let roc_return_alloca = env.builder.new_build_pointer_cast( zig_return_alloca, diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 2ab51a3e9f0..6353cc7b410 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -11,7 +11,7 @@ use crate::llvm::struct_::RocStruct; use bumpalo::collections::Vec; use inkwell::basic_block::BasicBlock; use inkwell::module::Linkage; -use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum}; +use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicTypeEnum}; use inkwell::values::{BasicValueEnum, FunctionValue, InstructionValue, IntValue, PointerValue}; use inkwell::{AddressSpace, IntPredicate}; use roc_builtins::bitcode; @@ -37,12 +37,9 @@ impl<'ctx> PointerToRefcount<'ctx> { /// not the data, and only is the start of the allocated buffer if the /// alignment works out that way. pub unsafe fn from_ptr<'a, 'env>(env: &Env<'a, 'ctx, 'env>, ptr: PointerValue<'ctx>) -> Self { - // must make sure it's a pointer to usize - let refcount_type = env.ptr_int(); - let value = env.builder.new_build_pointer_cast( ptr, - refcount_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_refcount_ptr", ); @@ -56,7 +53,7 @@ impl<'ctx> PointerToRefcount<'ctx> { let builder = env.builder; // pointer to usize let refcount_type = env.ptr_int(); - let refcount_ptr_type = refcount_type.ptr_type(AddressSpace::default()); + let refcount_ptr_type = env.context.ptr_type(AddressSpace::default()); let ptr_as_usize_ptr = builder.new_build_pointer_cast(data_ptr, refcount_ptr_type, "as_usize_ptr"); @@ -145,7 +142,7 @@ impl<'ctx> PointerToRefcount<'ctx> { None => { // inc and dec return void let fn_type = context.void_type().fn_type( - &[env.ptr_int().ptr_type(AddressSpace::default()).into()], + &[env.context.ptr_type(AddressSpace::default()).into()], false, ); @@ -231,7 +228,7 @@ fn incref_pointer<'ctx>( env.builder .new_build_pointer_cast( pointer, - env.ptr_int().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_isize_ptr", ) .into(), @@ -255,7 +252,7 @@ fn free_pointer<'ctx>( env.builder .new_build_pointer_cast( pointer, - env.ptr_int().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_isize_ptr", ) .into(), @@ -280,7 +277,7 @@ fn decref_pointer<'ctx>( env.builder .new_build_pointer_cast( pointer, - env.ptr_int().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_isize_ptr", ) .into(), @@ -306,7 +303,7 @@ pub fn decref_pointer_check_null<'ctx>( env.builder .new_build_pointer_cast( pointer, - env.context.i8_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "to_i8_ptr", ) .into(), @@ -1320,7 +1317,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>( // cast the opaque pointer to a pointer of the correct shape let struct_ptr = env.builder.new_build_pointer_cast( value_ptr, - wrapper_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "opaque_to_correct_recursive_decrement", ); @@ -1340,7 +1337,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>( ); let ptr_as_i64_ptr = env.builder.new_build_load( - env.context.i64_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), elem_pointer, "load_recursive_pointer", ); @@ -1792,7 +1789,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>( let cast_tag_data_pointer = env.builder.new_build_pointer_cast( opaque_tag_data_ptr, - data_struct_type.ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), "cast_to_concrete_tag", ); @@ -1810,7 +1807,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>( // This is the actual pointer to the recursive data. let field_value = env.builder.new_build_load( - env.context.i64_type().ptr_type(AddressSpace::default()), + env.context.ptr_type(AddressSpace::default()), field_ptr, "load_recursive_pointer", ); diff --git a/crates/compiler/test_gen/src/gen_num.rs b/crates/compiler/test_gen/src/gen_num.rs index 890f3d873c6..5977efcd0ee 100644 --- a/crates/compiler/test_gen/src/gen_num.rs +++ b/crates/compiler/test_gen/src/gen_num.rs @@ -3196,14 +3196,16 @@ fn num_to_str_f32() { assert_evals_to!( r"Num.toStr Num.maxF32", - RocStr::from("340282346638528860000000000000000000000"), - RocStr + f32::MAX, + RocStr, + |roc_str: RocStr| { roc_str.as_str().parse::().unwrap() } ); assert_evals_to!( r"Num.toStr Num.minF32", - RocStr::from("-340282346638528860000000000000000000000"), - RocStr + f32::MIN, + RocStr, + |roc_str: RocStr| { roc_str.as_str().parse::().unwrap() } ); } diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index 32122c085d2..15ea149a647 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -186,8 +186,6 @@ fn create_llvm_module<'a>( let module = roc_gen_llvm::llvm::build::module_from_builtins(target, context, "app"); let module = arena.alloc(module); - let (module_pass, function_pass) = - roc_gen_llvm::llvm::build::construct_optimization_passes(module, config.opt_level); let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module); @@ -256,7 +254,7 @@ fn create_llvm_module<'a>( unreachable!() } }; - let (main_fn_name, main_fn) = match config.mode { + let (main_fn_name, _main_fn) = match config.mode { LlvmBackendMode::Binary => unreachable!(), LlvmBackendMode::BinaryWithExpect => unreachable!(), LlvmBackendMode::BinaryGlue => unreachable!(), @@ -280,37 +278,21 @@ fn create_llvm_module<'a>( env.dibuilder.finalize(); - // Uncomment this to see the module's un-optimized LLVM instruction output: - // env.module.print_to_stderr(); - - let panic_bad_llvm = |errors| { - let path = std::env::temp_dir().join("test.ll"); - env.module.print_to_file(&path).unwrap(); - panic!( - "Errors defining module:\n\n{errors}\n\nI have written the full module to `{path:?}`" - ); - }; - - if main_fn.verify(true) { - function_pass.run_on(&main_fn); - } else { - panic_bad_llvm(main_fn_name); - } - - module_pass.run_on(env.module); - - // Verify the module - if let Err(errors) = env.module.verify() { - panic_bad_llvm(&errors.to_string()); - } + let ll_file_path = std::env::temp_dir().join("test.ll"); + let opt_level = OptLevel::Development; + let emit_debug_info = true; + roc_build::llvm_passes::optimize_llvm_ir( + &env, + target, + opt_level, + emit_debug_info, + &ll_file_path, + ); if let Ok(path) = std::env::var("ROC_DEBUG_LLVM") { env.module.print_to_file(path).unwrap(); } - // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); - let delayed_errors = if config.ignore_problems { String::new() } else { diff --git a/crates/compiler/test_gen/src/wasm_linking.rs b/crates/compiler/test_gen/src/wasm_linking.rs index 5d00f2b6a90..ae65e0490fa 100644 --- a/crates/compiler/test_gen/src/wasm_linking.rs +++ b/crates/compiler/test_gen/src/wasm_linking.rs @@ -293,17 +293,20 @@ fn test_help( fs::write(dump_filename, &buffer).unwrap(); } - let linked_import_names = Vec::from_iter(linked_module.import.imports.iter().map(|i| i.name)); + let mut linked_import_names = + Vec::from_iter(linked_module.import.imports.iter().map(|i| i.name)); + linked_import_names.sort(); assert_eq!(&linked_import_names, expected_linked_import_names); // eliminated imports appear after the non-eliminated ones in the name section let import_count = linked_import_names.len(); let eliminated_count = expected_eliminated_names.len(); - let eliminated_names = Vec::from_iter( + let mut eliminated_names = Vec::from_iter( linked_module.names.function_names[import_count..][..eliminated_count] .iter() .map(|(_, name)| *name), ); + eliminated_names.sort(); assert_eq!(&eliminated_names, expected_eliminated_names); let wasm_result = execute_wasm_module(&arena, linked_module).unwrap(); diff --git a/crates/copy_zig_glue/Cargo.toml b/crates/copy_zig_glue/Cargo.toml new file mode 100644 index 00000000000..20c8176f4e3 --- /dev/null +++ b/crates/copy_zig_glue/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "copy_zig_glue" +description = "This crate Copies the glue source files for zig platforms from the roc builtins this is only temporary, we should create a zig package for the test platforms" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +roc_test_utils_dir = { path = "../test_utils_dir" } diff --git a/crates/copy_zig_glue/src/lib.rs b/crates/copy_zig_glue/src/lib.rs new file mode 100644 index 00000000000..2552b6fb4ab --- /dev/null +++ b/crates/copy_zig_glue/src/lib.rs @@ -0,0 +1,64 @@ +use std::path::Path; +use std::path::PathBuf; +use std::sync::Once; +use std::{fs, io}; + +static ZIG_PLATFORM_COPY_GLUE_ONCE: Once = Once::new(); + +/// Copies the glue source files for zig platforms from the roc builtins +/// this is only temporary, we should create a zig package for the test platforms +pub fn initialize_zig_test_platforms() { + ZIG_PLATFORM_COPY_GLUE_ONCE.call_once(|| { + copy_zig_glue(); + }); +} + +/// Copy the zig builtins source files into each of the test platform folders. +/// +/// This is a simple way to use these files without creating a zig package, +/// to support the upgrade from zig 0.11.0 to 0.13.0, and keep the scope of the change smaller. +/// +/// Once we have zig 0.13.0, we should add a zig package for the test platforms. +pub fn copy_zig_glue() { + let workspace_dir = roc_test_utils_dir::workspace_root(); + let zig_builtins_source_dir = workspace_dir.join("crates/compiler/builtins/bitcode/src"); + + let zig_test_platforms_dirs: Vec = vec![ + workspace_dir.join("crates/cli/tests/test-projects/platform_requires_pkg/platform/glue"), + workspace_dir.join("crates/cli/tests/test-projects/algorithms/fibonacci-platform/glue"), + workspace_dir.join("crates/cli/tests/test-projects/algorithms/quicksort-platform/glue"), + workspace_dir.join("crates/cli/tests/benchmarks/platform/glue"), + workspace_dir.join("crates/valgrind_tests/zig-platform/glue"), + workspace_dir.join("crates/cli/tests/test-projects/test-platform-effects-zig/glue"), + workspace_dir.join("crates/cli/tests/test-projects/test-platform-simple-zig/glue"), + workspace_dir.join("examples/platform-switching/zig-platform/glue"), + workspace_dir.join("crates/cli/tests/test-projects/multiple_exposed/platform/glue"), + workspace_dir.join("crates/cli/tests/test-projects/tui/platform/glue"), + ]; + + for target_dir in zig_test_platforms_dirs { + copy_dir_all(&zig_builtins_source_dir, &target_dir).unwrap_or_else(|e| { + panic!( + "unable to copy zig builtins source files to {}: {}", + target_dir.display(), + e + ) + }); + println!("Copied zig glue source files into {}", target_dir.display()); + } + println!("DONE"); +} + +fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { + fs::create_dir_all(&dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} diff --git a/crates/copy_zig_glue/src/main.rs b/crates/copy_zig_glue/src/main.rs new file mode 100644 index 00000000000..45c54d95d92 --- /dev/null +++ b/crates/copy_zig_glue/src/main.rs @@ -0,0 +1,5 @@ +use copy_zig_glue::copy_zig_glue; + +fn main() { + copy_zig_glue(); +} diff --git a/crates/glue/tests/fixtures/rust/advanced-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/rust/advanced-recursive-union/src/lib.rs index bf300bcb9f3..bb9660783e9 100644 --- a/crates/glue/tests/fixtures/rust/advanced-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/advanced-recursive-union/src/lib.rs @@ -8,6 +8,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -85,3 +87,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/arguments/src/lib.rs b/crates/glue/tests/fixtures/rust/arguments/src/lib.rs index a56170a3cd6..3f8b31edd29 100644 --- a/crates/glue/tests/fixtures/rust/arguments/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/arguments/src/lib.rs @@ -5,6 +5,8 @@ use roc_std::RocStr; pub extern "C" fn rust_main() { let answer = roc_app::mainForHost(42i64); + init(); + println!("Answer was: {:?}", answer); // Debug } @@ -57,3 +59,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/basic-record/src/lib.rs b/crates/glue/tests/fixtures/rust/basic-record/src/lib.rs index 015b37a0373..9ed84a80485 100644 --- a/crates/glue/tests/fixtures/rust/basic-record/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/basic-record/src/lib.rs @@ -6,6 +6,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let record = roc_app::mainForHost(); // Verify that the record has all the expected traits. @@ -79,3 +81,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/basic-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/rust/basic-recursive-union/src/lib.rs index 1c1658e1fc5..2492ef4213a 100644 --- a/crates/glue/tests/fixtures/rust/basic-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/basic-recursive-union/src/lib.rs @@ -7,6 +7,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -90,3 +92,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/closures/src/lib.rs b/crates/glue/tests/fixtures/rust/closures/src/lib.rs index 1d3be6bda5d..7dc784be364 100644 --- a/crates/glue/tests/fixtures/rust/closures/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/closures/src/lib.rs @@ -5,6 +5,8 @@ use roc_std::RocStr; pub extern "C" fn rust_main() { let closure = roc_app::mainForHost(42i64); + init(); + println!("Answer was: {:?}", closure.force_thunk()); // Debug } @@ -57,3 +59,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/enumeration/src/lib.rs b/crates/glue/tests/fixtures/rust/enumeration/src/lib.rs index aec7b403a9f..aee5f45e497 100644 --- a/crates/glue/tests/fixtures/rust/enumeration/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/enumeration/src/lib.rs @@ -6,6 +6,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -83,3 +85,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/list-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/rust/list-recursive-union/src/lib.rs index 89ac109ec24..e18174bfb93 100644 --- a/crates/glue/tests/fixtures/rust/list-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/list-recursive-union/src/lib.rs @@ -9,6 +9,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -85,3 +87,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/multiple-modules/src/lib.rs b/crates/glue/tests/fixtures/rust/multiple-modules/src/lib.rs index 4750a9a64af..89273a00d81 100644 --- a/crates/glue/tests/fixtures/rust/multiple-modules/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/multiple-modules/src/lib.rs @@ -7,6 +7,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -83,3 +85,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/nested-record/src/lib.rs b/crates/glue/tests/fixtures/rust/nested-record/src/lib.rs index d1acc81a346..d92c175ce22 100644 --- a/crates/glue/tests/fixtures/rust/nested-record/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/nested-record/src/lib.rs @@ -5,6 +5,8 @@ use roc_std::RocStr; pub extern "C" fn rust_main() { use std::cmp::Ordering; + init(); + let outer = roc_app::mainForHost(); // Verify that `inner` has all the expected traits. @@ -83,3 +85,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/nonnullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/rust/nonnullable-unwrapped/src/lib.rs index 888ec70c84c..a84fb47ae3f 100644 --- a/crates/glue/tests/fixtures/rust/nonnullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/nonnullable-unwrapped/src/lib.rs @@ -14,6 +14,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = unsafe { let mut ret: core::mem::MaybeUninit = core::mem::MaybeUninit::uninit(); @@ -98,3 +100,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/nullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/rust/nullable-unwrapped/src/lib.rs index 4a5558012a3..93adb3146b9 100644 --- a/crates/glue/tests/fixtures/rust/nullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/nullable-unwrapped/src/lib.rs @@ -9,6 +9,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -90,3 +92,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/nullable-wrapped/src/lib.rs b/crates/glue/tests/fixtures/rust/nullable-wrapped/src/lib.rs index 542aa904a5e..f69df0a4e09 100644 --- a/crates/glue/tests/fixtures/rust/nullable-wrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/nullable-wrapped/src/lib.rs @@ -14,6 +14,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Eq @@ -109,3 +111,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/option/src/lib.rs b/crates/glue/tests/fixtures/rust/option/src/lib.rs index 1cd1ec5c260..788cd675705 100644 --- a/crates/glue/tests/fixtures/rust/option/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/option/src/lib.rs @@ -3,6 +3,8 @@ use roc_std::RocStr; #[no_mangle] pub extern "C" fn rust_main() { + init(); + let string = roc_app::mainForHost(true); println!("Answer was: {:?}", string.unwrap_Some()); // Debug // @@ -59,3 +61,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/rocresult/src/lib.rs b/crates/glue/tests/fixtures/rust/rocresult/src/lib.rs index 8fd4aee837c..c5eb7d0b919 100644 --- a/crates/glue/tests/fixtures/rust/rocresult/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/rocresult/src/lib.rs @@ -3,6 +3,8 @@ use roc_std::RocStr; #[no_mangle] pub extern "C" fn rust_main() { + init(); + let string = roc_app::mainForHost(true); println!("Answer was: {:?}", string); // Debug // @@ -59,3 +61,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/single-tag-union/src/lib.rs b/crates/glue/tests/fixtures/rust/single-tag-union/src/lib.rs index 9d3eeb433d8..8d41e9a9ce6 100644 --- a/crates/glue/tests/fixtures/rust/single-tag-union/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/single-tag-union/src/lib.rs @@ -9,6 +9,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -85,3 +87,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/union-with-padding/src/lib.rs b/crates/glue/tests/fixtures/rust/union-with-padding/src/lib.rs index ee8f92f0ff1..9b04972c17a 100644 --- a/crates/glue/tests/fixtures/rust/union-with-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/union-with-padding/src/lib.rs @@ -13,6 +13,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -90,3 +92,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/glue/tests/fixtures/rust/union-without-padding/src/lib.rs b/crates/glue/tests/fixtures/rust/union-without-padding/src/lib.rs index e5d35357b0f..2c49645bcba 100644 --- a/crates/glue/tests/fixtures/rust/union-without-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/rust/union-without-padding/src/lib.rs @@ -11,6 +11,8 @@ pub extern "C" fn rust_main() { use std::cmp::Ordering; use std::collections::hash_set::HashSet; + init(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -87,3 +89,50 @@ pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut R pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { libc::memset(dst, c, n) } + +pub fn init() { + if cfg!(unix) { + let unix_funcs: &[*const extern "C" fn()] = + &[roc_getppid as _, roc_mmap as _, roc_shm_open as _]; + #[allow(forgetting_references)] + std::mem::forget(std::hint::black_box(unix_funcs)); + } +} + +/// # Safety +/// +/// This function is unsafe. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_getppid() -> libc::pid_t { + libc::getppid() +} + +/// # Safety +/// +/// This function should be called with a valid addr pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_mmap( + addr: *mut libc::c_void, + len: libc::size_t, + prot: libc::c_int, + flags: libc::c_int, + fd: libc::c_int, + offset: libc::off_t, +) -> *mut libc::c_void { + libc::mmap(addr, len, prot, flags, fd, offset) +} + +/// # Safety +/// +/// This function should be called with a valid name pointer. +#[cfg(unix)] +#[no_mangle] +pub unsafe extern "C" fn roc_shm_open( + name: *const libc::c_char, + oflag: libc::c_int, + mode: libc::mode_t, +) -> libc::c_int { + libc::shm_open(name, oflag, mode as libc::c_uint) +} diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index 3669ca62e87..cf5ca105140 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -3,7 +3,7 @@ use inkwell::context::Context; use libloading::Library; use roc_build::link::llvm_module_to_dylib; use roc_collections::all::MutSet; -use roc_error_macros::internal_error; + use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type}; @@ -199,8 +199,6 @@ fn mono_module_to_dylib_llvm<'a>( )); let module = arena.alloc(module); - let (module_pass, function_pass) = - roc_gen_llvm::llvm::build::construct_optimization_passes(module, opt_level); let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module); @@ -243,7 +241,7 @@ fn mono_module_to_dylib_llvm<'a>( } }; - let (main_fn_name, main_fn) = roc_gen_llvm::llvm::build::build_procedures_return_main( + let (main_fn_name, _main_fn) = roc_gen_llvm::llvm::build::build_procedures_return_main( &env, &layout_interner, opt_level, @@ -252,26 +250,15 @@ fn mono_module_to_dylib_llvm<'a>( entry_point, ); - env.dibuilder.finalize(); - - // Uncomment this to see the module's un-optimized LLVM instruction output: - // env.module.print_to_stderr(); - - if main_fn.verify(true) { - function_pass.run_on(&main_fn); - } else { - internal_error!("Main function {main_fn_name} failed LLVM verification in build. Uncomment things nearby to see more details.", ); - } - - module_pass.run_on(env.module); - - // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); - - // Verify the module - if let Err(errors) = env.module.verify() { - internal_error!("Errors defining module:\n{}", errors.to_string()); - } + let emit_debug_info = true; + let ll_file_path = std::env::temp_dir().join("repl.ll"); + roc_build::llvm_passes::optimize_llvm_ir( + &env, + target, + opt_level, + emit_debug_info, + &ll_file_path, + ); llvm_module_to_dylib(env.module, target, opt_level) .map(|lib| (lib, main_fn_name, subs, layout_interner)) diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index a88708fb398..8d273dd12a4 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -480,8 +480,6 @@ pub fn expect_mono_module_to_dylib<'a>( )); let module = arena.alloc(module); - let (module_pass, _function_pass) = - roc_gen_llvm::llvm::build::construct_optimization_passes(module, opt_level); let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module); @@ -544,25 +542,15 @@ pub fn expect_mono_module_to_dylib<'a>( modules_expects.insert(module_id, expect_funs); } - env.dibuilder.finalize(); - - // Uncomment this to see the module's un-optimized LLVM instruction output: - // env.module.print_to_stderr(); - - module_pass.run_on(env.module); - - // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); - - // Verify the module - if let Err(errors) = env.module.verify() { - let path = std::env::temp_dir().join("test.ll"); - env.module.print_to_file(&path).unwrap(); - internal_error!( - "Errors defining module:\n{}\n\nUncomment things nearby to see more details. IR written to `{:?}`", - errors.to_string(), path, - ); - } + let emit_debug_info = true; + let ll_file_path = std::env::temp_dir().join("test.ll"); + roc_build::llvm_passes::optimize_llvm_ir( + &env, + target, + opt_level, + emit_debug_info, + &ll_file_path, + ); if let Ok(path) = std::env::var("ROC_DEBUG_LLVM") { env.module.print_to_file(path).unwrap(); diff --git a/crates/valgrind_tests/Cargo.toml b/crates/valgrind_tests/Cargo.toml index adf562a1f18..2e63fa1a82d 100644 --- a/crates/valgrind_tests/Cargo.toml +++ b/crates/valgrind_tests/Cargo.toml @@ -15,6 +15,7 @@ roc_load.workspace = true roc_mono.workspace = true roc_packaging.workspace = true roc_reporting.workspace = true +copy_zig_glue.workspace = true bumpalo.workspace = true indoc.workspace = true diff --git a/crates/valgrind_tests/src/lib.rs b/crates/valgrind_tests/src/lib.rs index 56cb29a5a76..75a481234a8 100644 --- a/crates/valgrind_tests/src/lib.rs +++ b/crates/valgrind_tests/src/lib.rs @@ -61,6 +61,8 @@ fn build_host() { } fn valgrind_test(source: &str) { + copy_zig_glue::initialize_zig_test_platforms(); + #[cfg(target_os = "linux")] { valgrind_test_linux(source) diff --git a/crates/valgrind_tests/zig-platform/host.zig b/crates/valgrind_tests/zig-platform/host.zig index 27df6519182..26d432aa997 100644 --- a/crates/valgrind_tests/zig-platform/host.zig +++ b/crates/valgrind_tests/zig-platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -17,7 +17,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -89,13 +89,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } @@ -106,7 +106,7 @@ extern fn roc__mainForHost_1_exposed_generic(*RocStr) void; const Unit = extern struct {}; -pub fn main() u8 { +pub export fn main() u8 { const stdout = std.io.getStdOut().writer(); const stderr = std.io.getStdErr().writer(); diff --git a/crates/wasi-libc-sys/build.rs b/crates/wasi-libc-sys/build.rs index 70eddef4f65..da7541ee62b 100644 --- a/crates/wasi-libc-sys/build.rs +++ b/crates/wasi-libc-sys/build.rs @@ -10,7 +10,7 @@ fn main() { // out_dir == "/target/[/]/build/wasi_libc_sys_/" let out_dir = env::var("OUT_DIR").unwrap(); - let zig_cache_dir = PathBuf::from(&out_dir).join("zig-cache"); + let zig_cache_dir = PathBuf::from(&out_dir).join(".zig-cache"); // out_file == "/target/[/]/lib/wasi-libc.a" let mut out_file = PathBuf::from(&out_dir); diff --git a/crates/wasm_interp/src/wasi.rs b/crates/wasm_interp/src/wasi.rs index 5b3d8f285a8..16cc1bfd08e 100644 --- a/crates/wasm_interp/src/wasi.rs +++ b/crates/wasm_interp/src/wasi.rs @@ -122,8 +122,8 @@ impl<'a> WasiDispatcher<'a> { let stat_mut_ptr = arguments[1].expect_i32().unwrap() as usize; match fd { - 1 => { - // Tell WASI that stdout is a tty (no seek or tell) + 1 | 2 => { + // Tell WASI that stdout and stderr are a tty (no seek or tell) // https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/sources/isatty.c // *Not* a tty if: // (statbuf.fs_filetype != __WASI_FILETYPE_CHARACTER_DEVICE || diff --git a/examples/cli/effects-platform/Effect.roc b/examples/cli/effects-platform/Effect.roc deleted file mode 100644 index 8b1ab6d69fa..00000000000 --- a/examples/cli/effects-platform/Effect.roc +++ /dev/null @@ -1,7 +0,0 @@ -hosted Effect - exposes [putLine!, getLine!] - imports [] - -putLine! : Str => {} - -getLine! : {} => Str diff --git a/examples/nodejs-interop/wasm/platform/host.zig b/examples/nodejs-interop/wasm/platform/host.zig index d6da990e7e8..5f830fabdd9 100644 --- a/examples/nodejs-interop/wasm/platform/host.zig +++ b/examples/nodejs-interop/wasm/platform/host.zig @@ -39,7 +39,7 @@ extern fn roc__mainForHost_1_exposed(*RocStr) void; extern fn js_display_roc_string(str_bytes: ?[*]u8, str_len: usize) void; -pub fn main() u8 { +pub export fn main() u8 { // actually call roc to populate the callresult var callresult = RocStr.empty(); roc__mainForHost_1_exposed(&callresult); diff --git a/examples/platform-switching/web-assembly-platform/host.zig b/examples/platform-switching/web-assembly-platform/host.zig index b6babf362f0..04c8eb716b8 100644 --- a/examples/platform-switching/web-assembly-platform/host.zig +++ b/examples/platform-switching/web-assembly-platform/host.zig @@ -39,7 +39,7 @@ extern fn roc__mainForHost_1_exposed(*RocStr) void; extern fn js_display_roc_string(str_bytes: ?[*]u8, str_len: usize) void; -pub fn main() u8 { +pub export fn main() u8 { // actually call roc to populate the callresult var callresult = RocStr.empty(); roc__mainForHost_1_exposed(&callresult); diff --git a/examples/platform-switching/zig-platform/host.zig b/examples/platform-switching/zig-platform/host.zig index 3c349d09624..ce8fdd1e2b5 100644 --- a/examples/platform-switching/zig-platform/host.zig +++ b/examples/platform-switching/zig-platform/host.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const str = @import("glue").str; +const str = @import("glue/str.zig"); const RocStr = str.RocStr; const testing = std.testing; const expectEqual = testing.expectEqual; @@ -17,7 +17,7 @@ const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { - var ptr = malloc(size); + const ptr = malloc(size); const stdout = std.io.getStdOut().writer(); stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; return ptr; @@ -89,13 +89,13 @@ fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_ comptime { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); + @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .strong }); + @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .strong }); + @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .strong }); } if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); + @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .strong }); } } @@ -106,7 +106,7 @@ extern fn roc__mainForHost_1_exposed_generic(*RocStr) void; const Unit = extern struct {}; -pub fn main() u8 { +pub export fn main() u8 { const stdout = std.io.getStdOut().writer(); // actually call roc to populate the callresult diff --git a/examples/virtual-dom-wip/platform/src/server-side/host.zig b/examples/virtual-dom-wip/platform/src/server-side/host.zig index f2dcc9b756c..4bef351ea2d 100644 --- a/examples/virtual-dom-wip/platform/src/server-side/host.zig +++ b/examples/virtual-dom-wip/platform/src/server-side/host.zig @@ -56,7 +56,7 @@ extern fn roc__main_1_exposed(RocStr, RocStr) callconv(.C) ResultStrStr; const hostJavaScriptBytes = @embedFile("../client-side/host.js"); -pub fn main() u8 { +pub export fn main() u8 { const json = RocStr.fromSlice("42"); defer json.decref(); diff --git a/flake.lock b/flake.lock index dbaac0648a6..a9daebbed08 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1732722421, + "narHash": "sha256-HRJ/18p+WoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac", "type": "github" }, "original": { @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -59,17 +59,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1712163089, - "narHash": "sha256-Um+8kTIrC19vD4/lUCN9/cU9kcOsD1O1m+axJqQPyMM=", + "lastModified": 1722403750, + "narHash": "sha256-tRmn6UiFAPX0m9G1AVcEPjWEOc9BtGsxGcs7Bz3MpsM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "fd281bd6b7d3e32ddfa399853946f782553163b5", + "rev": "184957277e885c06a505db112b35dfbec7c60494", "type": "github" }, "original": { "owner": "nixos", "repo": "nixpkgs", - "rev": "fd281bd6b7d3e32ddfa399853946f782553163b5", + "rev": "184957277e885c06a505db112b35dfbec7c60494", "type": "github" } }, @@ -89,11 +89,11 @@ ] }, "locked": { - "lastModified": 1727490462, - "narHash": "sha256-OrrPiNBiikv9BR464XTT75FzOq7tKAvMbMi7YOKVIeg=", + "lastModified": 1732802692, + "narHash": "sha256-kFrxb45qj52TT/OFUFyTdmvXkn/KXDUL0/DOtjHEQvs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "11a13e50debafae4ae802f1d6b8585101516dd93", + "rev": "34971069ec33755b2adf2481851f66d8ec9a6bfa", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2f640de5d2e..e211ff8d00f 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Roc flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs?rev=fd281bd6b7d3e32ddfa399853946f782553163b5"; + nixpkgs.url = "github:nixos/nixpkgs?rev=184957277e885c06a505db112b35dfbec7c60494"; # rust from nixpkgs has some libc problems, this is patched in the rust-overlay rust-overlay = { @@ -34,6 +34,7 @@ { inherit templates; } // flake-utils.lib.eachSystem supportedSystems (system: let + overlays = [ (import rust-overlay) ] ++ (if system == "x86_64-linux" then [ nixgl.overlay ] else [ ]); pkgs = import nixpkgs { inherit system overlays; }; @@ -72,17 +73,23 @@ sharedInputs = (with pkgs; [ # build libraries cmake - llvmPkgs.llvm.dev - llvmPkgs.clang + # provides llvm + llvmPkgs.dev + # faster builds - see https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker + # provides lld + pkgs.lld_18 + # provides clang + pkgs.clang_18 + pkg-config + zigPkg # roc builtins are implemented in zig, see compiler/builtins/bitcode/ + # lib deps libffi libxml2 ncurses zlib - # faster builds - see https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker - llvmPkgs.lld rocBuild.rust-shell perl # ./ci/update_basic_cli_url.sh ]); @@ -133,7 +140,7 @@ 1; # to run the GUI examples with NVIDIA's closed source drivers shellHook = '' - export LLVM_SYS_${llvmMajorMinorStr}_PREFIX="${llvmPkgs.llvm.dev}" + export LLVM_SYS_180_PREFIX="${llvmPkgs.dev}" ${aliases} ''; }; diff --git a/nix/builder.nix b/nix/builder.nix index 48782e54c5a..ad93963eb3e 100644 --- a/nix/builder.nix +++ b/nix/builder.nix @@ -1,6 +1,6 @@ { pkgs, lib, rustPlatform, compile-deps, subPackage ? null }: let - inherit (compile-deps) zigPkg llvmPkgs llvmVersion llvmMajorMinorStr glibcPath libGccSPath; + inherit (compile-deps) zigPkg llvmPkgs glibcPath libGccSPath; subPackagePath = if subPackage != null then "crates/${subPackage}" else null; mainBin = if subPackage == "language_server" then "roc_language_server" else "roc"; @@ -19,14 +19,14 @@ let lockFile = ../Cargo.lock; outputHashes = { "criterion-0.3.5" = "sha256-+FibPQGiR45g28xCHcM0pMN+C+Q8gO8206Wb5fiTy+k="; - "inkwell-0.2.0" = "sha256-VhTapYGonoSQ4hnDoLl4AAgj0BppAhPNA+UPuAJSuAU="; + "inkwell-0.4.0" = "sha256-J2mdwf167GhEadEL2XJ39FXeY8roV9aYdhOBfIwbPbE="; "plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw="; "rustyline-9.1.1" = "sha256-aqQqz6nSp+Qn44gm3jXmmQUO6/fYTx7iLph2tbA24Bs="; }; }; shellHook = '' - export LLVM_SYS_${llvmMajorMinorStr}_PREFIX="${llvmPkgs.llvm.dev}" + export LLVM_SYS_180_PREFIX="${llvmPkgs.dev}" ''; # required for zig @@ -46,9 +46,8 @@ let git pkg-config python3 - llvmPkgs.clang - llvmPkgs.llvm.dev - llvmPkgs.bintools-unwrapped # contains lld + llvmPkgs.dev + llvmPkgs.lib zigPkg ]); @@ -70,6 +69,9 @@ let Security ])); + LLVM_SYS_180_PREFIX = lib.optionalString (llvmPkgs.dev != null) "${llvmPkgs.dev}"; + + # cp: to copy str.zig,list.zig... # wrapProgram pkgs.stdenv.cc: to make ld available for compiler/build/src/link.rs postInstall = diff --git a/nix/compile-deps.nix b/nix/compile-deps.nix index 59bf6b20863..8f8adb56d0b 100644 --- a/nix/compile-deps.nix +++ b/nix/compile-deps.nix @@ -1,7 +1,7 @@ { pkgs }: let - zigPkg = pkgs.zig_0_11; - llvmPkgs = pkgs.llvmPackages_16; + zigPkg = pkgs.zig; + llvmPkgs = pkgs.llvm_18; llvmVersion = builtins.splitVersion llvmPkgs.release_version; llvmMajorMinorStr = builtins.elemAt llvmVersion 0 + builtins.elemAt llvmVersion 1; # nix does not store libs in /usr/lib or /lib diff --git a/www/content/install/linux_x86_64.md b/www/content/install/linux_x86_64.md index 76ad52cbc3d..d37d77d9700 100644 --- a/www/content/install/linux_x86_64.md +++ b/www/content/install/linux_x86_64.md @@ -53,14 +53,14 @@ you'll need to install one or more of these platform languages too. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -1. For Zig-based platforms: [download zig 0.11.0](https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz), extract the archive and add export PATH=$PATH:~/path/to/zig to your shell startup script (.profile, .zshrc, …). +1. For Zig-based platforms: [download zig 0.13.0](https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz), extract the archive and add export PATH=$PATH:~/path/to/zig to your shell startup script (.profile, .zshrc, …). 1. Install a C compiler, for apps with C-based platforms: ```sh # On a Debian-based distro like Ubuntu sudo apt update && sudo apt install build-essential clang - + # On an RPM-based distro like Fedora sudo dnf check-update && sudo dnf install clang ``` diff --git a/www/content/install/macos_apple_silicon.md b/www/content/install/macos_apple_silicon.md index 4b7670bd44b..71fed371949 100644 --- a/www/content/install/macos_apple_silicon.md +++ b/www/content/install/macos_apple_silicon.md @@ -18,10 +18,10 @@ which includes the Roc compiler and some helpful utilities. cd roc_night ``` -1. Install llvm 16: +1. Install llvm 18: ```sh - brew install llvm@16 + brew install llvm@18 ``` 1. To be able to run the `roc` command anywhere on your system; add the line below to your shell startup script (.profile, .zshrc, ...): @@ -44,7 +44,7 @@ you'll need to install one or more of these platform languages too. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -1. If you'd like to use Zig-based platforms: download [zig 0.11.0](https://ziglang.org/download/0.11.0/zig-macos-aarch64-0.11.0.tar.xz), extract the archive and add `export PATH=$PATH:~/path/to/zig` to your shell startup script (.profile, .zshrc, …). Note: zig 0.11.0 is currently available on homebrew, but future update may remove it. +1. If you'd like to use Zig-based platforms: download [zig 0.13.0](https://ziglang.org/download/0.13.0/zig-macos-aarch64-0.13.0.tar.xz), extract the archive and add `export PATH=$PATH:~/path/to/zig` to your shell startup script (.profile, .zshrc, …). Note: zig 0.13.0 is currently available on homebrew, but future update may remove it. 1. Run examples: diff --git a/www/content/install/macos_x86_64.md b/www/content/install/macos_x86_64.md index 9b7c19bf165..71a56ef9597 100644 --- a/www/content/install/macos_x86_64.md +++ b/www/content/install/macos_x86_64.md @@ -38,7 +38,7 @@ you'll need to install one or more of these platform languages too. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -1. If you'd like to use Zig-based platforms: download [zig 0.11.0](https://ziglang.org/download/0.11.0/zig-macos-x86_64-0.11.0.tar.xz), extract the archive and add `export PATH=$PATH:~/path/to/zig` to your shell startup script (.profile, .zshrc, …). Note: zig 0.11.0 is not available on homebrew. +1. If you'd like to use Zig-based platforms: download [zig 0.13.0](https://ziglang.org/download/0.13.0/zig-macos-x86_64-0.13.0.tar.xz), extract the archive and add `export PATH=$PATH:~/path/to/zig` to your shell startup script (.profile, .zshrc, …). Note: zig 0.13.0 is not available on homebrew. 1. Run examples: