Merge commit '6ba33f5e11' into subtree-update_cg_gcc_2025-05-14
This commit is contained in:
parent
c7740d2f17
commit
d52b5e6df5
29 changed files with 909 additions and 247 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Cargo.lock linguist-generated=false
|
||||
3
.github/workflows/stdarch.yml
vendored
3
.github/workflows/stdarch.yml
vendored
|
|
@ -101,9 +101,8 @@ jobs:
|
|||
if: ${{ matrix.cargo_runner }}
|
||||
run: |
|
||||
# FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro.
|
||||
# TODO: remove --skip test_mm512_stream_ps when stdarch is updated in rustc.
|
||||
# TODO: remove --skip test_tile_ when it's implemented.
|
||||
STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features --cfg stdarch_intel_sde" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_mm512_stream_ps --skip test_tile_
|
||||
STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_
|
||||
|
||||
# Summary job for the merge queue.
|
||||
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
|
||||
|
|
|
|||
101
CONTRIBUTING.md
Normal file
101
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# Contributing to rustc_codegen_gcc
|
||||
|
||||
Welcome to the `rustc_codegen_gcc` project! This guide will help you get started as a contributor. The project aims to provide a GCC codegen backend for rustc, allowing Rust compilation on platforms unsupported by LLVM and potentially improving runtime performance through GCC's optimizations.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Setting Up Your Development Environment
|
||||
|
||||
For detailed setup instructions including dependencies, build steps, and initial testing, please refer to our [README](Readme.md). The README contains the most up-to-date information on:
|
||||
|
||||
- Required dependencies and system packages
|
||||
- Repository setup and configuration
|
||||
- Build process
|
||||
- Basic test verification
|
||||
|
||||
Once you've completed the setup process outlined in the README, you can proceed with the contributor-specific information below.
|
||||
|
||||
## Communication Channels
|
||||
|
||||
- Matrix: Join our [Matrix channel](https://matrix.to/#/#rustc_codegen_gcc:matrix.org)
|
||||
- IRC: Join us on [IRC](https://web.libera.chat/#rustc_codegen_gcc)
|
||||
- [GitHub Issues](https://github.com/rust-lang/rustc_codegen_gcc/issues): For bug reports and feature discussions
|
||||
|
||||
We encourage new contributors to join our communication channels and introduce themselves. Feel free to ask questions about where to start or discuss potential contributions.
|
||||
|
||||
## Understanding Core Concepts
|
||||
|
||||
### Common Development Tasks
|
||||
|
||||
#### Running Specific Tests
|
||||
|
||||
To run specific tests, use appropriate flags such as:
|
||||
|
||||
- `./y.sh test --test-libcore`
|
||||
- `./y.sh test --std-tests`
|
||||
- `cargo test -- <name of test>`
|
||||
|
||||
Additionally, you can run the tests of `libgccjit`:
|
||||
|
||||
```bash
|
||||
# libgccjit tests
|
||||
cd gcc-build/gcc
|
||||
make check-jit
|
||||
# For a specific test:
|
||||
make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
|
||||
```
|
||||
|
||||
#### Debugging Tools
|
||||
|
||||
The project provides several environment variables for debugging:
|
||||
|
||||
- `CG_GCCJIT_DUMP_GIMPLE`: Dumps the GIMPLE IR
|
||||
- `CG_RUSTFLAGS`: Additional Rust flags
|
||||
- `CG_GCCJIT_DUMP_MODULE`: Dumps a specific module
|
||||
- `CG_GCCJIT_DUMP_TO_FILE`: Creates C-like representation
|
||||
|
||||
Full list of debugging options can be found in the [README](Readme.md#env-vars).
|
||||
|
||||
## Making Contributions
|
||||
|
||||
### Finding Issues to Work On
|
||||
|
||||
1. Look for issues labeled with [`good first issue`](https://github.com/rust-lang/rustc_codegen_gcc/issues?q=is%3Aissue%20state%3Aopen%20label%3A"good%20first%20issue") or [`help wanted`](https://github.com/rust-lang/rustc_codegen_gcc/issues?q=is%3Aissue%20state%3Aopen%20label%3A"help%20wanted")
|
||||
2. Check the [progress report](https://blog.antoyo.xyz/rustc_codegen_gcc-progress-report-34#state_of_rustc_codegen_gcc) for larger initiatives
|
||||
3. Consider improving documentation or investigating [failing tests](https://github.com/rust-lang/rustc_codegen_gcc/tree/master/tests) (except `failing-ui-tests12.txt`)
|
||||
|
||||
### Pull Request Process
|
||||
|
||||
1. Fork the repository and create a new branch
|
||||
2. Make your changes with clear commit messages
|
||||
3. Add tests for new functionality
|
||||
4. Update documentation as needed
|
||||
5. Submit a PR with a description of your changes
|
||||
|
||||
### Code Style Guidelines
|
||||
|
||||
- Follow Rust standard coding conventions
|
||||
- Ensure your code passes `rustfmt` and `clippy`
|
||||
- Add comments explaining complex logic, especially in GCC interface code
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Rustc Dev Guide](https://rustc-dev-guide.rust-lang.org/)
|
||||
- [GCC Internals Documentation](https://gcc.gnu.org/onlinedocs/gccint/)
|
||||
- Project-specific documentation in the `doc/` directory:
|
||||
- [Common errors](doc/errors.md)
|
||||
- [Debugging](doc/debugging.md)
|
||||
- [Debugging libgccjit](doc/debugging-libgccjit.md)
|
||||
- [Git subtree sync](doc/subtree.md)
|
||||
- [List of useful commands](doc/tips.md)
|
||||
- [Send a patch to GCC](doc/sending-gcc-patch.md)
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you're stuck or unsure about anything:
|
||||
1. Check the existing documentation in the `doc/` directory
|
||||
2. Ask in the IRC or Matrix channels
|
||||
3. Open a GitHub issue for technical problems
|
||||
4. Comment on the issue you're working on if you need guidance
|
||||
|
||||
Remember that all contributions, including documentation improvements, bug reports, and feature requests, are valuable to the project.
|
||||
|
|
@ -56,18 +56,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "2.5.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2895ddec764de7ac76fe6c056050c4801a80109c066f177a00a9cc8dee02b29b"
|
||||
checksum = "ae99a89184220d967dd300139f2d2ae7d52c1a69d632b24aacc57c54625254ce"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac133db68db8a6a8b2c51ef4b18d8ea16682d5814c4641272fe37bbbc223d5f3"
|
||||
checksum = "24edb7bfe2b7b27c6d09ed23eebfcab0b359c8fe978433f902943e6f127a0f1b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
name = "rustc_codegen_gcc"
|
||||
version = "0.1.0"
|
||||
authors = ["Antoni Boucher <bouanto@zoho.com>"]
|
||||
edition = "2018"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[lib]
|
||||
|
|
@ -22,7 +22,7 @@ master = ["gccjit/master"]
|
|||
default = ["master"]
|
||||
|
||||
[dependencies]
|
||||
gccjit = "2.5"
|
||||
gccjit = "2.7"
|
||||
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
|
||||
|
||||
# Local copy.
|
||||
|
|
|
|||
42
Readme.md
42
Readme.md
|
|
@ -12,22 +12,38 @@ This is a GCC codegen for rustc, which means it can be loaded by the existing ru
|
|||
The primary goal of this project is to be able to compile Rust code on platforms unsupported by LLVM.
|
||||
A secondary goal is to check if using the gcc backend will provide any run-time speed improvement for the programs compiled using rustc.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Note: **This requires a patched libgccjit in order to work.
|
||||
You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.**
|
||||
The default configuration (see below in the [Quick start](#quick-start) section) will download a `libgccjit` built in the CI that already contains these patches, so you don't need to build this fork yourself if you use the default configuration.
|
||||
|
||||
### Dependencies
|
||||
|
||||
**rustup:** Follow the instructions on the official [website](https://www.rust-lang.org/tools/install)
|
||||
- rustup: follow instructions on the [official website](https://rustup.rs)
|
||||
- consider to install DejaGnu which is necessary for running the libgccjit test suite. [website](https://www.gnu.org/software/dejagnu/#downloading)
|
||||
- additional packages: `flex`, `libmpfr-dev`, `libgmp-dev`, `libmpc3`, `libmpc-dev`
|
||||
|
||||
### Quick start
|
||||
|
||||
**DejaGnu:** Consider to install DejaGnu which is necessary for running the libgccjit test suite. [website](https://www.gnu.org/software/dejagnu/#downloading)
|
||||
1. Clone and configure the repository:
|
||||
```bash
|
||||
git clone https://github.com/rust-lang/rustc_codegen_gcc
|
||||
cd rustc_codegen_gcc
|
||||
cp config.example.toml config.toml
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
**This requires a patched libgccjit in order to work.
|
||||
You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.**
|
||||
|
||||
```bash
|
||||
$ cp config.example.toml config.toml
|
||||
```
|
||||
2. Build and test:
|
||||
```bash
|
||||
./y.sh prepare # downloads and patches sysroot
|
||||
./y.sh build --sysroot --release
|
||||
|
||||
# Verify setup with a simple test
|
||||
./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml
|
||||
|
||||
# Run full test suite (expect ~100 failing UI tests)
|
||||
./y.sh test --release
|
||||
```
|
||||
|
||||
If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should
|
||||
be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC.
|
||||
|
|
@ -143,7 +159,7 @@ You can do the same manually (although we don't recommend it):
|
|||
$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
|
||||
```
|
||||
|
||||
## Env vars
|
||||
## Environment variables
|
||||
|
||||
* _**CG_GCCJIT_DUMP_ALL_MODULES**_: Enables dumping of all compilation modules. When set to "1", a dump is created for each module during compilation and stored in `/tmp/reproducers/`.
|
||||
* _**CG_GCCJIT_DUMP_MODULE**_: Enables dumping of a specific module. When set with the module name, e.g., `CG_GCCJIT_DUMP_MODULE=module_name`, a dump of that specific module is created in `/tmp/reproducers/`.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "y"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
boml = "0.3.1"
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ pub enum Command {
|
|||
|
||||
fn main() {
|
||||
if env::var("RUST_BACKTRACE").is_err() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
unsafe {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
}
|
||||
}
|
||||
|
||||
let command = match env::args().nth(1).as_deref() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::{Command, ExitStatus, Output};
|
||||
|
||||
#[cfg(unix)]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn raise(signal: c_int) -> c_int;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
#![feature(
|
||||
no_core, lang_items, intrinsics, unboxed_closures, extern_types,
|
||||
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
|
||||
no_core,
|
||||
lang_items,
|
||||
intrinsics,
|
||||
unboxed_closures,
|
||||
extern_types,
|
||||
decl_macro,
|
||||
rustc_attrs,
|
||||
transparent_unions,
|
||||
auto_traits,
|
||||
freeze_impls,
|
||||
thread_local
|
||||
)]
|
||||
#![no_core]
|
||||
|
|
@ -35,13 +43,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
|||
pub trait DispatchFromDyn<T> {}
|
||||
|
||||
// &T -> &U
|
||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
// &mut T -> &mut U
|
||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
// *const T -> *const U
|
||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
// *mut T -> *mut U
|
||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
|
|
@ -52,8 +60,7 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
|
|||
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
trait Receiver {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
|
|
@ -67,10 +74,13 @@ impl Copy for u16 {}
|
|||
impl Copy for u32 {}
|
||||
impl Copy for u64 {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for u128 {}
|
||||
impl Copy for i8 {}
|
||||
impl Copy for i16 {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for i64 {}
|
||||
impl Copy for isize {}
|
||||
impl Copy for i128 {}
|
||||
impl Copy for f32 {}
|
||||
impl Copy for f64 {}
|
||||
impl Copy for char {}
|
||||
|
|
@ -336,7 +346,6 @@ impl PartialEq for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl PartialEq for u64 {
|
||||
fn eq(&self, other: &u64) -> bool {
|
||||
(*self) == (*other)
|
||||
|
|
@ -523,7 +532,11 @@ fn panic_in_cleanup() -> ! {
|
|||
#[track_caller]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
libc::printf(
|
||||
"index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8,
|
||||
len,
|
||||
index,
|
||||
);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
|
@ -551,8 +564,7 @@ pub trait Deref {
|
|||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
pub trait Allocator {
|
||||
}
|
||||
pub trait Allocator {}
|
||||
|
||||
impl Allocator for () {}
|
||||
|
||||
|
|
@ -634,6 +646,8 @@ pub union MaybeUninit<T> {
|
|||
}
|
||||
|
||||
pub mod intrinsics {
|
||||
#[rustc_intrinsic]
|
||||
pub const fn black_box<T>(_dummy: T) -> T;
|
||||
#[rustc_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
#[rustc_intrinsic]
|
||||
|
|
@ -711,19 +725,27 @@ pub struct VaList<'a>(&'a mut VaListImpl);
|
|||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro stringify($($t:tt)*) { /* compiler built-in */ }
|
||||
pub macro stringify($($t:tt)*) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro file() { /* compiler built-in */ }
|
||||
pub macro file() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro line() { /* compiler built-in */ }
|
||||
pub macro line() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro cfg() { /* compiler built-in */ }
|
||||
pub macro cfg() {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
pub static A_STATIC: u8 = 42;
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0ea98a1365b81f7488073512c850e8ee951a4afd
|
||||
8b194529188f9d3a98cc211caa805a5355bfa8f0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-04-25"
|
||||
channel = "nightly-2025-05-12"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
65
src/abi.rs
65
src/abi.rs
|
|
@ -9,9 +9,9 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_session::config;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::callconv::Conv;
|
||||
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::callconv::{Conv, RiscvInterruptKind};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
|
|
@ -240,38 +240,57 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
|
||||
// TODO: handle the calling conventions returning None.
|
||||
let attribute = match conv {
|
||||
Conv::C
|
||||
| Conv::Rust
|
||||
| Conv::CCmseNonSecureCall
|
||||
| Conv::CCmseNonSecureEntry
|
||||
| Conv::RiscvInterrupt { .. } => return None,
|
||||
Conv::Cold => return None,
|
||||
Conv::C | Conv::Rust => return None,
|
||||
Conv::CCmseNonSecureCall => {
|
||||
if arch == "arm" {
|
||||
FnAttribute::ArmCmseNonsecureCall
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Conv::CCmseNonSecureEntry => {
|
||||
if arch == "arm" {
|
||||
FnAttribute::ArmCmseNonsecureEntry
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Conv::Cold => FnAttribute::Cold,
|
||||
// NOTE: the preserve attributes are not yet implemented in GCC:
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110899
|
||||
Conv::PreserveMost => return None,
|
||||
Conv::PreserveAll => return None,
|
||||
Conv::GpuKernel => {
|
||||
// TODO(antoyo): remove clippy allow attribute when this is implemented.
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
if arch == "amdgpu" {
|
||||
return None;
|
||||
FnAttribute::GcnAmdGpuHsaKernel
|
||||
} else if arch == "nvptx64" {
|
||||
return None;
|
||||
FnAttribute::NvptxKernel
|
||||
} else {
|
||||
panic!("Architecture {} does not support GpuKernel calling convention", arch);
|
||||
}
|
||||
}
|
||||
Conv::AvrInterrupt => return None,
|
||||
Conv::AvrNonBlockingInterrupt => return None,
|
||||
Conv::ArmAapcs => return None,
|
||||
Conv::Msp430Intr => return None,
|
||||
Conv::X86Fastcall => return None,
|
||||
Conv::X86Intr => return None,
|
||||
Conv::X86Stdcall => return None,
|
||||
Conv::X86ThisCall => return None,
|
||||
// TODO(antoyo): check if those AVR attributes are mapped correctly.
|
||||
Conv::AvrInterrupt => FnAttribute::AvrSignal,
|
||||
Conv::AvrNonBlockingInterrupt => FnAttribute::AvrInterrupt,
|
||||
Conv::ArmAapcs => FnAttribute::ArmPcs("aapcs"),
|
||||
Conv::Msp430Intr => FnAttribute::Msp430Interrupt,
|
||||
Conv::RiscvInterrupt { kind } => {
|
||||
let kind = match kind {
|
||||
RiscvInterruptKind::Machine => "machine",
|
||||
RiscvInterruptKind::Supervisor => "supervisor",
|
||||
};
|
||||
FnAttribute::RiscvInterrupt(kind)
|
||||
}
|
||||
Conv::X86Fastcall => FnAttribute::X86FastCall,
|
||||
Conv::X86Intr => FnAttribute::X86Interrupt,
|
||||
Conv::X86Stdcall => FnAttribute::X86Stdcall,
|
||||
Conv::X86ThisCall => FnAttribute::X86ThisCall,
|
||||
// NOTE: the vectorcall calling convention is not yet implemented in GCC:
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
|
||||
Conv::X86VectorCall => return None,
|
||||
Conv::X86_64SysV => FnAttribute::SysvAbi,
|
||||
Conv::X86_64Win64 => FnAttribute::MsAbi,
|
||||
Conv::X86_64SysV => FnAttribute::X86SysvAbi,
|
||||
Conv::X86_64Win64 => FnAttribute::X86MsAbi,
|
||||
};
|
||||
Some(attribute)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,21 +6,69 @@ use rustc_attr_parsing::InlineAttr;
|
|||
use rustc_attr_parsing::InstructionSetAttr;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_middle::mir::TerminatorKind;
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::context::CodegenCx;
|
||||
use crate::gcc_util::to_gcc_features;
|
||||
|
||||
/// Get GCC attribute for the provided inline heuristic.
|
||||
/// Checks if the function `instance` is recursively inline.
|
||||
/// Returns `false` if a functions is guaranteed to be non-recursive, and `true` if it *might* be recursive.
|
||||
#[cfg(feature = "master")]
|
||||
fn resursively_inline<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> bool {
|
||||
// No body, so we can't check if this is recursively inline, so we assume it is.
|
||||
if !cx.tcx.is_mir_available(instance.def_id()) {
|
||||
return true;
|
||||
}
|
||||
// `expect_local` ought to never fail: we should be checking a function within this codegen unit.
|
||||
let body = cx.tcx.optimized_mir(instance.def_id());
|
||||
for block in body.basic_blocks.iter() {
|
||||
let Some(ref terminator) = block.terminator else { continue };
|
||||
// I assume that the recursive-inline issue applies only to functions, and not to drops.
|
||||
// In principle, a recursive, `#[inline(always)]` drop could(?) exist, but I don't think it does.
|
||||
let TerminatorKind::Call { ref func, .. } = terminator.kind else { continue };
|
||||
let Some((def, _args)) = func.const_fn_def() else { continue };
|
||||
// Check if the called function is recursively inline.
|
||||
if matches!(
|
||||
cx.tcx.codegen_fn_attrs(def).inline,
|
||||
InlineAttr::Always | InlineAttr::Force { .. }
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Get GCC attribute for the provided inline heuristic, attached to `instance`.
|
||||
#[cfg(feature = "master")]
|
||||
#[inline]
|
||||
fn inline_attr<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
inline: InlineAttr,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> Option<FnAttribute<'gcc>> {
|
||||
match inline {
|
||||
InlineAttr::Always => {
|
||||
// We can't simply always return `always_inline` unconditionally.
|
||||
// It is *NOT A HINT* and does not work for recursive functions.
|
||||
//
|
||||
// So, it can only be applied *if*:
|
||||
// The current function does not call any functions marked `#[inline(always)]`.
|
||||
//
|
||||
// That prevents issues steming from recursive `#[inline(always)]` at a *relatively* small cost.
|
||||
// We *only* need to check all the terminators of a function marked with this attribute.
|
||||
if resursively_inline(cx, instance) {
|
||||
Some(FnAttribute::Inline)
|
||||
} else {
|
||||
Some(FnAttribute::AlwaysInline)
|
||||
}
|
||||
}
|
||||
InlineAttr::Hint => Some(FnAttribute::Inline),
|
||||
InlineAttr::Always | InlineAttr::Force { .. } => Some(FnAttribute::AlwaysInline),
|
||||
InlineAttr::Force { .. } => Some(FnAttribute::AlwaysInline),
|
||||
InlineAttr::Never => {
|
||||
if cx.sess().target.arch != "amdgpu" {
|
||||
Some(FnAttribute::NoInline)
|
||||
|
|
@ -52,7 +100,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
} else {
|
||||
codegen_fn_attrs.inline
|
||||
};
|
||||
if let Some(attr) = inline_attr(cx, inline) {
|
||||
if let Some(attr) = inline_attr(cx, inline, instance) {
|
||||
if let FnAttribute::AlwaysInline = attr {
|
||||
func.add_attribute(FnAttribute::Inline);
|
||||
}
|
||||
|
|
@ -88,14 +136,8 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
let target_features = function_features
|
||||
.iter()
|
||||
.filter_map(|feature| {
|
||||
// FIXME(antoyo): for some reasons, disabling SSE results in the following error when
|
||||
// compiling Rust for Linux:
|
||||
// SSE register return with SSE disabled
|
||||
// TODO(antoyo): support soft-float and retpoline-external-thunk.
|
||||
if feature.contains("soft-float")
|
||||
|| feature.contains("retpoline-external-thunk")
|
||||
|| *feature == "-sse"
|
||||
{
|
||||
// TODO(antoyo): support soft-float.
|
||||
if feature.contains("soft-float") {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ fn thin_lto(
|
|||
Ok((opt_jobs, copy_jobs))
|
||||
}
|
||||
|
||||
pub unsafe fn optimize_thin_module(
|
||||
pub fn optimize_thin_module(
|
||||
thin_module: ThinModule<GccCodegenBackend>,
|
||||
_cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
) -> Result<ModuleCodegen<GccContext>, FatalError> {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::base::add_pic_option;
|
|||
use crate::errors::CopyBitcode;
|
||||
use crate::{GccCodegenBackend, GccContext};
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
pub(crate) fn codegen(
|
||||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
module: ModuleCodegen<GccContext>,
|
||||
|
|
|
|||
|
|
@ -568,11 +568,28 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
) {
|
||||
let mut gcc_cases = vec![];
|
||||
let typ = self.val_ty(value);
|
||||
for (on_val, dest) in cases {
|
||||
let on_val = self.const_uint_big(typ, on_val);
|
||||
gcc_cases.push(self.context.new_case(on_val, on_val, dest));
|
||||
// FIXME(FractalFir): This is a workaround for a libgccjit limitation.
|
||||
// Currently, libgccjit can't directly create 128 bit integers.
|
||||
// Since switch cases must be values, and casts are not constant, we can't use 128 bit switch cases.
|
||||
// In such a case, we will simply fall back to an if-ladder.
|
||||
// This *may* be slower than a native switch, but a slow working solution is better than none at all.
|
||||
if typ.is_i128(self) || typ.is_u128(self) {
|
||||
for (on_val, dest) in cases {
|
||||
let on_val = self.const_uint_big(typ, on_val);
|
||||
let is_case =
|
||||
self.context.new_comparison(self.location, ComparisonOp::Equals, value, on_val);
|
||||
let next_block = self.current_func().new_block("case");
|
||||
self.block.end_with_conditional(self.location, is_case, dest, next_block);
|
||||
self.block = next_block;
|
||||
}
|
||||
self.block.end_with_jump(self.location, default_block);
|
||||
} else {
|
||||
for (on_val, dest) in cases {
|
||||
let on_val = self.const_uint_big(typ, on_val);
|
||||
gcc_cases.push(self.context.new_case(on_val, on_val, dest));
|
||||
}
|
||||
self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
|
||||
}
|
||||
self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
|
|
|
|||
|
|
@ -191,13 +191,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
// TODO(antoyo): check if it's okay that no link_section is set.
|
||||
|
||||
let typ = self.val_ty(cv).get_aligned(align.bytes());
|
||||
let global = self.declare_private_global(&name[..], typ);
|
||||
global
|
||||
self.declare_private_global(&name[..], typ)
|
||||
}
|
||||
_ => {
|
||||
let typ = self.val_ty(cv).get_aligned(align.bytes());
|
||||
let global = self.declare_unnamed_global(typ);
|
||||
global
|
||||
self.declare_unnamed_global(typ)
|
||||
}
|
||||
};
|
||||
global.global_set_initializer_rvalue(cv);
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
) -> Self::DILocation {
|
||||
let pos = span.lo();
|
||||
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
|
||||
let loc = match file.name {
|
||||
match file.name {
|
||||
rustc_span::FileName::Real(ref name) => match *name {
|
||||
rustc_span::RealFileName::LocalPath(ref name) => {
|
||||
if let Some(name) = name.to_str() {
|
||||
|
|
@ -314,7 +314,6 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
},
|
||||
_ => Location::null(),
|
||||
};
|
||||
loc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
#[allow(clippy::let_and_return)]
|
||||
fn declare_raw_fn<'gcc>(
|
||||
cx: &CodegenCx<'gcc, '_>,
|
||||
name: &str,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,9 +4,7 @@ mod simd;
|
|||
#[cfg(feature = "master")]
|
||||
use std::iter;
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::FunctionType;
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
|
||||
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_abi::{BackendRepr, HasDataLayout};
|
||||
|
|
@ -132,6 +130,72 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
|
|||
Some(cx.context.get_builtin_function(gcc_name))
|
||||
}
|
||||
|
||||
// TODO(antoyo): We can probably remove these and use the fallback intrinsic implementation.
|
||||
fn get_simple_function<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
name: Symbol,
|
||||
) -> Option<Function<'gcc>> {
|
||||
let (return_type, parameters, func_name) = match name {
|
||||
sym::minimumf32 => {
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, cx.float_type, "a"),
|
||||
cx.context.new_parameter(None, cx.float_type, "b"),
|
||||
];
|
||||
(cx.float_type, parameters, "fminimumf")
|
||||
}
|
||||
sym::minimumf64 => {
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, cx.double_type, "a"),
|
||||
cx.context.new_parameter(None, cx.double_type, "b"),
|
||||
];
|
||||
(cx.double_type, parameters, "fminimum")
|
||||
}
|
||||
sym::minimumf128 => {
|
||||
let f128_type = cx.type_f128();
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
];
|
||||
(f128_type, parameters, "fminimumf128")
|
||||
}
|
||||
sym::maximumf32 => {
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, cx.float_type, "a"),
|
||||
cx.context.new_parameter(None, cx.float_type, "b"),
|
||||
];
|
||||
(cx.float_type, parameters, "fmaximumf")
|
||||
}
|
||||
sym::maximumf64 => {
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, cx.double_type, "a"),
|
||||
cx.context.new_parameter(None, cx.double_type, "b"),
|
||||
];
|
||||
(cx.double_type, parameters, "fmaximum")
|
||||
}
|
||||
sym::maximumf128 => {
|
||||
let f128_type = cx.type_f128();
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html
|
||||
let parameters = [
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
];
|
||||
(f128_type, parameters, "fmaximumf128")
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
Some(cx.context.new_function(
|
||||
None,
|
||||
FunctionType::Extern,
|
||||
return_type,
|
||||
¶meters,
|
||||
func_name,
|
||||
false,
|
||||
))
|
||||
}
|
||||
|
||||
impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
fn codegen_intrinsic_call(
|
||||
&mut self,
|
||||
|
|
@ -160,6 +224,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
|
||||
|
||||
let simple = get_simple_intrinsic(self, name);
|
||||
let simple_func = get_simple_function(self, name);
|
||||
|
||||
// FIXME(tempdragon): Re-enable `clippy::suspicious_else_formatting` if the following issue is solved:
|
||||
// https://github.com/rust-lang/rust-clippy/issues/12497
|
||||
|
|
@ -167,7 +232,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
#[allow(clippy::suspicious_else_formatting)]
|
||||
let value = match name {
|
||||
_ if simple.is_some() => {
|
||||
let func = simple.expect("simple function");
|
||||
let func = simple.expect("simple intrinsic function");
|
||||
self.cx.context.new_call(
|
||||
self.location,
|
||||
func,
|
||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
_ if simple_func.is_some() => {
|
||||
let func = simple_func.expect("simple function");
|
||||
self.cx.context.new_call(
|
||||
self.location,
|
||||
func,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)]
|
||||
#![feature(rustc_private, decl_macro, never_type, trusted_len)]
|
||||
#![allow(broken_intra_doc_links)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
|
@ -454,7 +454,7 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
}
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
||||
#[cfg(feature = "master")]
|
||||
let info = {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ tests/ui/sepcomp/sepcomp-fns-backwards.rs
|
|||
tests/ui/sepcomp/sepcomp-fns.rs
|
||||
tests/ui/sepcomp/sepcomp-statics.rs
|
||||
tests/ui/asm/x86_64/may_unwind.rs
|
||||
tests/ui/catch-unwind-bang.rs
|
||||
tests/ui/panics/catch-unwind-bang.rs
|
||||
tests/ui/drop/dynamic-drop-async.rs
|
||||
tests/ui/cfg/cfg-panic-abort.rs
|
||||
tests/ui/drop/repeat-drop.rs
|
||||
|
|
@ -94,23 +94,14 @@ tests/ui/simd/intrinsic/generic-as.rs
|
|||
tests/ui/backtrace/backtrace.rs
|
||||
tests/ui/lifetimes/tail-expr-lock-poisoning.rs
|
||||
tests/ui/runtime/rt-explody-panic-payloads.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ pub fn main_inner(profile: Profile) {
|
|||
.expect("failed to get absolute path of `gcc-path`")
|
||||
.display()
|
||||
.to_string();
|
||||
env::set_var("LD_LIBRARY_PATH", gcc_path);
|
||||
unsafe {
|
||||
env::set_var("LD_LIBRARY_PATH", gcc_path);
|
||||
}
|
||||
|
||||
fn rust_filter(path: &Path) -> bool {
|
||||
path.is_file() && path.extension().expect("extension").to_str().expect("to_str") == "rs"
|
||||
|
|
@ -67,15 +69,14 @@ pub fn main_inner(profile: Profile) {
|
|||
.test_dir("tests/run")
|
||||
.test_path_filter(filter)
|
||||
.test_extract(|path| {
|
||||
let lines = std::fs::read_to_string(path)
|
||||
std::fs::read_to_string(path)
|
||||
.expect("read file")
|
||||
.lines()
|
||||
.skip_while(|l| !l.starts_with("//"))
|
||||
.take_while(|l| l.starts_with("//"))
|
||||
.map(|l| &l[2..])
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
lines
|
||||
.join("\n")
|
||||
})
|
||||
.test_cmds(move |path| {
|
||||
// Test command 1: Compile `x.rs` into `tempdir/x`.
|
||||
|
|
|
|||
53
tests/run/always_inline.rs
Normal file
53
tests/run/always_inline.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[inline(always)]
|
||||
fn fib(n: u8) -> u8 {
|
||||
if n == 0 {
|
||||
return 1;
|
||||
}
|
||||
if n == 1 {
|
||||
return 1;
|
||||
}
|
||||
fib(n - 1) + fib(n - 2)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn fib_b(n: u8) -> u8 {
|
||||
if n == 0 {
|
||||
return 1;
|
||||
}
|
||||
if n == 1 {
|
||||
return 1;
|
||||
}
|
||||
fib_a(n - 1) + fib_a(n - 2)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn fib_a(n: u8) -> u8 {
|
||||
if n == 0 {
|
||||
return 1;
|
||||
}
|
||||
if n == 1 {
|
||||
return 1;
|
||||
}
|
||||
fib_b(n - 1) + fib_b(n - 2)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
if fib(2) != fib_a(2) {
|
||||
intrinsics::abort();
|
||||
}
|
||||
0
|
||||
}
|
||||
37
tests/run/switchint_128bit.rs
Normal file
37
tests/run/switchint_128bit.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use intrinsics::black_box;
|
||||
use mini_core::*;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
// 1st. Check that small 128 bit values work.
|
||||
let val = black_box(64_u128);
|
||||
match val {
|
||||
0 => return 1,
|
||||
1 => return 2,
|
||||
64 => (),
|
||||
_ => return 3,
|
||||
}
|
||||
// 2nd check that *large* values work.
|
||||
const BIG: u128 = 0xDEAD_C0FE_BEEF_DECAF_BADD_DECAF_BEEF_u128;
|
||||
let val = black_box(BIG);
|
||||
match val {
|
||||
0 => return 4,
|
||||
1 => return 5,
|
||||
// Check that we will not match on the lower u64, if the upper qword is different!
|
||||
0xcafbadddecafbeef => return 6,
|
||||
0xDEAD_C0FE_BEEF_DECAF_BADD_DECAF_BEEF_u128 => (),
|
||||
_ => return 7,
|
||||
}
|
||||
0
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ def run_command(command, cwd=None):
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def clone_repository(repo_name, path, repo_url, sub_paths=None):
|
||||
def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None):
|
||||
if os.path.exists(path):
|
||||
while True:
|
||||
choice = input("There is already a `{}` folder, do you want to update it? [y/N]".format(path))
|
||||
|
|
@ -21,7 +21,7 @@ def clone_repository(repo_name, path, repo_url, sub_paths=None):
|
|||
return
|
||||
elif choice.lower() == "y":
|
||||
print("Updating repository...")
|
||||
run_command(["git", "pull", "origin"], cwd=path)
|
||||
run_command(["git", "pull", "origin", branch], cwd=path)
|
||||
return
|
||||
else:
|
||||
print("Didn't understand answer...")
|
||||
|
|
@ -209,6 +209,7 @@ def main():
|
|||
"llvm-project",
|
||||
llvm_path,
|
||||
"https://github.com/llvm/llvm-project",
|
||||
branch="main",
|
||||
sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"],
|
||||
)
|
||||
clone_repository(
|
||||
|
|
|
|||
7
triagebot.toml
Normal file
7
triagebot.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Documentation at https://forge.rust-lang.org/triagebot/index.html
|
||||
|
||||
# Prevents un-canonicalized issue links (to avoid wrong issues being linked in r-l/rust)
|
||||
[issue-links]
|
||||
|
||||
# Prevents mentions in commits to avoid users being spammed
|
||||
[no-mentions]
|
||||
Loading…
Add table
Add a link
Reference in a new issue