Merge commit '55171cfa8b' into subtree-update_cg_gcc_2025-11-26

This commit is contained in:
Guillaume Gomez 2025-11-26 19:41:43 +01:00
commit 9fce61b21b
28 changed files with 315 additions and 133 deletions

View file

@ -54,8 +54,6 @@ jobs:
if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
run: |
echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml
echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
- name: Download artifact
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'

View file

@ -51,12 +51,6 @@ jobs:
- name: Setup path to libgccjit
run: echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml
- name: Set env
run: |
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
#- name: Cache rust repository
## We only clone the rust repository for rustc tests
#if: ${{ contains(matrix.commands, 'rustc') }}

View file

@ -72,6 +72,9 @@ jobs:
git config --global user.name "User"
./y.sh prepare
- name: Add more failing tests (some panic and debuginfo tests fail)
run: cat tests/failing-lto-tests.txt >> tests/failing-ui-tests.txt
- name: Run tests
run: |
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.

View file

@ -59,9 +59,8 @@ jobs:
sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde
sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64
- name: Set env
- name: Set config
run: |
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
echo 'download-gccjit = true' > config.toml
- name: Build
@ -69,12 +68,6 @@ jobs:
./y.sh prepare --only-libcore
./y.sh build --sysroot --release --release-sysroot
- name: Set env (part 2)
run: |
# Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables...
echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
- name: Clean
if: ${{ !matrix.cargo_runner }}
run: |

View file

@ -56,18 +56,18 @@ dependencies = [
[[package]]
name = "gccjit"
version = "2.10.0"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60362e038e71e4bdc1a5b23fb45e1aba587b5947fe0db58f4871d95608f89eca"
checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
version = "0.9.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd542c8414e122217551c6af6b7d33acf51a227aee85276f218c087525e01bb"
checksum = "263da4f60b7bb5d6a5b21efda961741051ebdbf0e380a09118b03cce66a8c77e"
dependencies = [
"libc",
]

View file

@ -24,11 +24,11 @@ default = ["master"]
[dependencies]
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
tempfile = "3.20"
gccjit = "2.10"
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
gccjit = { version = "3.1.1", features = ["dlopen"] }
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] }
# Local copy.
#gccjit = { path = "../gccjit.rs" }
#gccjit = { path = "../gccjit.rs", features = ["dlopen"] }
[dev-dependencies]
boml = "0.3.1"

View file

@ -1,7 +1,8 @@
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
use std::os::unix::fs::symlink;
use std::path::{Path, PathBuf};
use crate::config::{Channel, ConfigInfo};
use crate::utils::{
@ -100,6 +101,18 @@ fn cleanup_sysroot_previous_build(library_dir: &Path) {
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
let start_dir = get_sysroot_dir();
// Symlink libgccjit.so to sysroot.
let lib_path = start_dir.join("sysroot").join("lib");
let libgccjit_path =
PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point"))
.join("libgccjit.so");
let libgccjit_in_sysroot_path = lib_path.join("libgccjit.so");
// First remove the file to be able to create the symlink even when the file already exists.
let _ = fs::remove_file(&libgccjit_in_sysroot_path);
create_dir(&lib_path)?;
symlink(libgccjit_path, libgccjit_in_sysroot_path)
.map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?;
let library_dir = start_dir.join("sysroot_src").join("library");
cleanup_sysroot_previous_build(&library_dir);
@ -148,7 +161,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
// Copy files to sysroot
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
let sysroot_path = lib_path.join(format!("rustlib/{}/lib/", config.target_triple));
// To avoid errors like "multiple candidates for `rmeta` dependency `core` found", we clean the
// sysroot directory before copying the sysroot build artifacts.
let _ = fs::remove_dir_all(&sysroot_path);
@ -175,13 +188,6 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
let mut env = HashMap::new();
let gcc_path =
args.config_info.gcc_path.clone().expect(
"The config module should have emitted an error if the GCC path wasn't provided",
);
env.insert("LD_LIBRARY_PATH".to_string(), gcc_path.clone());
env.insert("LIBRARY_PATH".to_string(), gcc_path);
if args.config_info.no_default_features {
env.insert("RUSTFLAGS".to_string(), "-Csymbol-mangling-version=v0".to_string());
}

View file

@ -429,19 +429,6 @@ impl ConfigInfo {
// display metadata load errors
env.insert("RUSTC_LOG".to_string(), "warn".to_string());
let sysroot = current_dir
.join(get_sysroot_dir())
.join(format!("sysroot/lib/rustlib/{}/lib", self.target_triple));
let ld_library_path = format!(
"{target}:{sysroot}:{gcc_path}",
target = self.cargo_target_dir,
sysroot = sysroot.display(),
gcc_path = gcc_path,
);
env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
// NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
// To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
// Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc

View file

@ -214,14 +214,6 @@ fn cargo_tests(test_env: &Env, test_args: &TestArg) -> Result<(), String> {
// We don't want to pass things like `RUSTFLAGS`, since they contain the -Zcodegen-backend flag.
// That would force `cg_gcc` to *rebuild itself* and only then run tests, which is undesirable.
let mut env = HashMap::new();
env.insert(
"LD_LIBRARY_PATH".into(),
test_env.get("LD_LIBRARY_PATH").expect("LD_LIBRARY_PATH missing!").to_string(),
);
env.insert(
"LIBRARY_PATH".into(),
test_env.get("LIBRARY_PATH").expect("LIBRARY_PATH missing!").to_string(),
);
env.insert(
"CG_RUSTFLAGS".into(),
test_env.get("CG_RUSTFLAGS").map(|s| s.as_str()).unwrap_or("").to_string(),
@ -1065,6 +1057,7 @@ where
&test_dir,
&"--compiletest-rustc-args",
&rustc_args,
&"--bypass-ignore-backends",
];
if run_ignored_tests {
@ -1275,11 +1268,6 @@ pub fn run() -> Result<(), String> {
if !args.use_system_gcc {
args.config_info.setup_gcc_path()?;
let gcc_path = args.config_info.gcc_path.clone().expect(
"The config module should have emitted an error if the GCC path wasn't provided",
);
env.insert("LIBRARY_PATH".to_string(), gcc_path.clone());
env.insert("LD_LIBRARY_PATH".to_string(), gcc_path);
}
build_if_no_backend(&env, &args)?;

View file

@ -9,6 +9,14 @@ be useful.
CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build
```
### How to send arguments to GCC
The `-Cllvm-args` `rustc` flag is repurposed by `rustc_codegen_gcc` to pass arguments directly to the GCC backend. You can use it via the `CG_RUSTFLAGS` environment variable. For example, to pass a `-f` flag to GCC:
```
CG_RUSTFLAGS="-Cllvm-args=-fflag-name" ../y.sh cargo build
```
### How to see the personality functions in the asm dump
```

View file

@ -1 +1 @@
28b84db392ac0a572f1a2a2a1317aa5f2bc742cb
0081ca6631abdfa02bf42bc85aaf507b8a0e6beb

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-11-04"
channel = "nightly-2025-11-24"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -86,7 +86,7 @@ fn inline_attr<'gcc, 'tcx>(
/// attributes.
pub fn from_fn_attrs<'gcc, 'tcx>(
cx: &CodegenCx<'gcc, 'tcx>,
#[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
#[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>,
instance: ty::Instance<'tcx>,
) {
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);

View file

@ -633,6 +633,7 @@ pub fn optimize_thin_module(
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
}
}*/
// FIXME: switch to #[expect] when the clippy bug is fixed.
#[allow(clippy::let_and_return)]
module
}

View file

@ -1481,7 +1481,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
variable.to_rvalue()
}
#[allow(dead_code)]
fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> {
unimplemented!();
}
@ -2517,7 +2516,7 @@ impl ToGccComp for RealPredicate {
}
#[repr(C)]
#[allow(non_camel_case_types)]
#[expect(non_camel_case_types)]
enum MemOrdering {
__ATOMIC_RELAXED,
__ATOMIC_CONSUME,

View file

@ -58,7 +58,6 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
global_value
}
#[cfg_attr(not(feature = "master"), allow(unused_mut))]
fn codegen_static(&mut self, def_id: DefId) {
let attrs = self.tcx.codegen_fn_attrs(def_id);
@ -162,7 +161,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
// TODO(antoyo)
}
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
#[cfg_attr(not(feature = "master"), expect(unused_variables))]
pub fn add_used_function(&self, function: Function<'gcc>) {
#[cfg(feature = "master")]
function.add_attribute(FnAttribute::Used);

View file

@ -28,7 +28,7 @@ use crate::abi::conv_to_fn_attribute;
use crate::callee::get_fn;
use crate::common::SignType;
#[cfg_attr(not(feature = "master"), allow(dead_code))]
#[cfg_attr(not(feature = "master"), expect(dead_code))]
pub struct CodegenCx<'gcc, 'tcx> {
/// A cache of converted ConstAllocs
pub const_cache: RefCell<HashMap<Allocation, RValue<'gcc>>>,
@ -132,7 +132,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
}
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
pub fn new(
context: &'gcc Context<'gcc>,
codegen_unit: &'tcx CodegenUnit<'tcx>,

View file

@ -156,7 +156,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
///
/// If theres a value with the same name already declared, the function will
/// update the declaration and return existing Value instead.
#[allow(clippy::let_and_return)]
#[expect(clippy::let_and_return)]
fn declare_raw_fn<'gcc>(
cx: &CodegenCx<'gcc, '_>,
name: &str,

View file

@ -10,7 +10,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
};
match arch {
"AMDGPU" => {
#[allow(non_snake_case)]
#[expect(non_snake_case)]
fn AMDGPU(name: &str, full_name: &str) -> &'static str {
match name {
// AMDGPU
@ -48,7 +48,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
AMDGPU(name, full_name)
}
"aarch64" => {
#[allow(non_snake_case)]
fn aarch64(name: &str, full_name: &str) -> &'static str {
match name {
// aarch64
@ -81,7 +80,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
aarch64(name, full_name)
}
"amdgcn" => {
#[allow(non_snake_case)]
fn amdgcn(name: &str, full_name: &str) -> &'static str {
match name {
// amdgcn
@ -524,7 +522,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
amdgcn(name, full_name)
}
"arm" => {
#[allow(non_snake_case)]
fn arm(name: &str, full_name: &str) -> &'static str {
match name {
// arm
@ -633,7 +630,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
arm(name, full_name)
}
"bpf" => {
#[allow(non_snake_case)]
fn bpf(name: &str, full_name: &str) -> &'static str {
match name {
// bpf
@ -655,7 +651,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
bpf(name, full_name)
}
"cuda" => {
#[allow(non_snake_case)]
fn cuda(name: &str, full_name: &str) -> &'static str {
match name {
// cuda
@ -666,7 +661,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
cuda(name, full_name)
}
"hexagon" => {
#[allow(non_snake_case)]
fn hexagon(name: &str, full_name: &str) -> &'static str {
match name {
// hexagon
@ -2653,7 +2647,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
hexagon(name, full_name)
}
"loongarch" => {
#[allow(non_snake_case)]
fn loongarch(name: &str, full_name: &str) -> &'static str {
match name {
// loongarch
@ -4162,7 +4155,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
loongarch(name, full_name)
}
"mips" => {
#[allow(non_snake_case)]
fn mips(name: &str, full_name: &str) -> &'static str {
match name {
// mips
@ -4843,7 +4835,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
mips(name, full_name)
}
"nvvm" => {
#[allow(non_snake_case)]
fn nvvm(name: &str, full_name: &str) -> &'static str {
match name {
// nvvm
@ -5652,7 +5643,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
nvvm(name, full_name)
}
"ppc" => {
#[allow(non_snake_case)]
fn ppc(name: &str, full_name: &str) -> &'static str {
match name {
// ppc
@ -6245,7 +6235,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
ppc(name, full_name)
}
"ptx" => {
#[allow(non_snake_case)]
fn ptx(name: &str, full_name: &str) -> &'static str {
match name {
// ptx
@ -6273,7 +6262,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
ptx(name, full_name)
}
"r600" => {
#[allow(non_snake_case)]
fn r600(name: &str, full_name: &str) -> &'static str {
match name {
// r600
@ -6298,7 +6286,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
r600(name, full_name)
}
"riscv" => {
#[allow(non_snake_case)]
fn riscv(name: &str, full_name: &str) -> &'static str {
match name {
// riscv
@ -6332,7 +6319,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
riscv(name, full_name)
}
"s390" => {
#[allow(non_snake_case)]
fn s390(name: &str, full_name: &str) -> &'static str {
match name {
// s390
@ -6526,7 +6512,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
s390(name, full_name)
}
"spv" => {
#[allow(non_snake_case)]
fn spv(name: &str, full_name: &str) -> &'static str {
match name {
// spv
@ -6543,7 +6528,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
spv(name, full_name)
}
"ve" => {
#[allow(non_snake_case)]
fn ve(name: &str, full_name: &str) -> &'static str {
match name {
// ve
@ -7816,7 +7800,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
ve(name, full_name)
}
"x86" => {
#[allow(non_snake_case)]
fn x86(name: &str, full_name: &str) -> &'static str {
match name {
// x86
@ -10384,7 +10367,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str {
x86(name, full_name)
}
"xcore" => {
#[allow(non_snake_case)]
fn xcore(name: &str, full_name: &str) -> &'static str {
match name {
// xcore

View file

@ -85,7 +85,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>(
(aes_output_type.as_type(), field1, field2)
}
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
#[cfg_attr(not(feature = "master"), expect(unused_variables))]
pub fn adjust_function<'gcc>(
context: &'gcc Context<'gcc>,
func_name: &str,
@ -1573,14 +1573,25 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.x86.tileloadd64" => "__builtin_trap",
"llvm.x86.tilerelease" => "__builtin_trap",
"llvm.x86.tilestored64" => "__builtin_trap",
"llvm.x86.tileloaddrs64" => "__builtin_trap",
"llvm.x86.tileloaddt164" => "__builtin_trap",
"llvm.x86.tileloaddrst164" => "__builtin_trap",
"llvm.x86.tilezero" => "__builtin_trap",
"llvm.x86.tilemovrow" => "__builtin_trap",
"llvm.x86.tdpbhf8ps" => "__builtin_trap",
"llvm.x86.tdphbf8ps" => "__builtin_trap",
"llvm.x86.tdpbf8ps" => "__builtin_trap",
"llvm.x86.tdphf8ps" => "__builtin_trap",
"llvm.x86.tdpbf16ps" => "__builtin_trap",
"llvm.x86.tdpbssd" => "__builtin_trap",
"llvm.x86.tdpbsud" => "__builtin_trap",
"llvm.x86.tdpbusd" => "__builtin_trap",
"llvm.x86.tdpbuud" => "__builtin_trap",
"llvm.x86.tdpfp16ps" => "__builtin_trap",
"llvm.x86.tmmultf32ps" => "__builtin_trap",
"llvm.x86.tcvtrowps2phh" => "__builtin_trap",
"llvm.x86.tcvtrowps2phl" => "__builtin_trap",
"llvm.x86.tcvtrowd2ps" => "__builtin_trap",
"llvm.x86.tcmmimfp16ps" => "__builtin_trap",
"llvm.x86.tcmmrlfp16ps" => "__builtin_trap",

View file

@ -53,6 +53,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
};
}
// TODO(antoyo): refactor with the above require_simd macro that was changed in cg_llvm.
#[cfg(feature = "master")]
macro_rules! require_simd2 {
($ty: expr, $variant:ident) => {{
require!($ty.is_simd(), InvalidMonomorphization::$variant { span, name, ty: $ty });
$ty.simd_size_and_type(bx.tcx())
}};
}
if name == sym::simd_select_bitmask {
require_simd!(
args[1].layout.ty,
@ -464,9 +473,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
m_len == v_len,
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
);
// TODO: also support unsigned integers.
match *m_elem_ty.kind() {
ty::Int(_) => {}
ty::Int(_) | ty::Uint(_) => {}
_ => return_error!(InvalidMonomorphization::MaskWrongElementType {
span,
name,
@ -1454,6 +1462,184 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
bitwise_red!(simd_reduce_all: BinaryOp::BitwiseAnd, true);
bitwise_red!(simd_reduce_any: BinaryOp::BitwiseOr, true);
#[cfg(feature = "master")]
if name == sym::simd_masked_load {
// simd_masked_load<_, _, _, const ALIGN: SimdAlign>(mask: <N x i{M}>, pointer: *_ T, values: <N x T>) -> <N x T>
// * N: number of elements in the input vectors
// * T: type of the element to load
// * M: any integer width is supported, will be truncated to i1
// Loads contiguous elements from memory behind `pointer`, but only for
// those lanes whose `mask` bit is enabled.
// The memory addresses corresponding to the “off” lanes are not accessed.
// TODO: handle the alignment.
// The element type of the "mask" argument must be a signed integer type of any width
let mask_ty = in_ty;
let mask_len = in_len;
// The second argument must be a pointer matching the element type
let pointer_ty = args[1].layout.ty;
// The last argument is a passthrough vector providing values for disabled lanes
let values_ty = args[2].layout.ty;
let (values_len, values_elem) = require_simd2!(values_ty, SimdThird);
require_simd2!(ret_ty, SimdReturn);
// Of the same length:
require!(
values_len == mask_len,
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len: mask_len,
in_ty: mask_ty,
arg_ty: values_ty,
out_len: values_len
}
);
// The return type must match the last argument type
require!(
ret_ty == values_ty,
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty: values_ty, ret_ty }
);
require!(
matches!(
*pointer_ty.kind(),
ty::RawPtr(p_ty, _) if p_ty == values_elem && p_ty.kind() == values_elem.kind()
),
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: values_elem,
second_arg: pointer_ty,
in_elem: values_elem,
in_ty: values_ty,
mutability: ExpectedPointerMutability::Not,
}
);
let mask = args[0].immediate();
let pointer = args[1].immediate();
let default = args[2].immediate();
let default_type = default.get_type();
let vector_type = default_type.unqualified().dyncast_vector().expect("vector type");
let value_type = vector_type.get_element_type();
let new_pointer_type = value_type.make_pointer();
let pointer = bx.context.new_cast(None, pointer, new_pointer_type);
let mask_vector_type = mask.get_type().unqualified().dyncast_vector().expect("vector type");
let elem_type = mask_vector_type.get_element_type();
let zero = bx.context.new_rvalue_zero(elem_type);
let mut elements = vec![];
for i in 0..mask_len {
let i = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
let mask = bx.context.new_vector_access(None, mask, i).to_rvalue();
let mask = bx.context.new_comparison(None, ComparisonOp::NotEquals, mask, zero);
let then_val = bx.context.new_array_access(None, pointer, i).to_rvalue();
let else_val = bx.context.new_vector_access(None, default, i).to_rvalue();
let element = bx.select(mask, then_val, else_val);
elements.push(element);
}
let result = bx.context.new_rvalue_from_vector(None, default_type, &elements);
return Ok(result);
}
#[cfg(feature = "master")]
if name == sym::simd_masked_store {
// simd_masked_store<_, _, _, const ALIGN: SimdAlign>(mask: <N x i{M}>, pointer: *mut T, values: <N x T>) -> ()
// * N: number of elements in the input vectors
// * T: type of the element to load
// * M: any integer width is supported, will be truncated to i1
// Stores contiguous elements to memory behind `pointer`, but only for
// those lanes whose `mask` bit is enabled.
// The memory addresses corresponding to the “off” lanes are not accessed.
// TODO: handle the alignment.
// The element type of the "mask" argument must be a signed integer type of any width
let mask_ty = in_ty;
let mask_len = in_len;
// The second argument must be a pointer matching the element type
let pointer_ty = args[1].layout.ty;
// The last argument specifies the values to store to memory
let values_ty = args[2].layout.ty;
let (values_len, values_elem) = require_simd2!(values_ty, SimdThird);
// Of the same length:
require!(
values_len == mask_len,
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len: mask_len,
in_ty: mask_ty,
arg_ty: values_ty,
out_len: values_len
}
);
// The second argument must be a mutable pointer type matching the element type
require!(
matches!(
*pointer_ty.kind(),
ty::RawPtr(p_ty, p_mutbl)
if p_ty == values_elem && p_ty.kind() == values_elem.kind() && p_mutbl.is_mut()
),
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: values_elem,
second_arg: pointer_ty,
in_elem: values_elem,
in_ty: values_ty,
mutability: ExpectedPointerMutability::Mut,
}
);
let mask = args[0].immediate();
let pointer = args[1].immediate();
let values = args[2].immediate();
let values_type = values.get_type();
let vector_type = values_type.unqualified().dyncast_vector().expect("vector type");
let value_type = vector_type.get_element_type();
let new_pointer_type = value_type.make_pointer();
let pointer = bx.context.new_cast(None, pointer, new_pointer_type);
let vector_type = mask.get_type().unqualified().dyncast_vector().expect("vector type");
let elem_type = vector_type.get_element_type();
let zero = bx.context.new_rvalue_zero(elem_type);
for i in 0..mask_len {
let i = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
let mask = bx.context.new_vector_access(None, mask, i).to_rvalue();
let mask = bx.context.new_comparison(None, ComparisonOp::NotEquals, mask, zero);
let after_block = bx.current_func().new_block("after");
let then_block = bx.current_func().new_block("then");
bx.llbb().end_with_conditional(None, mask, then_block, after_block);
bx.switch_to_block(then_block);
let lvalue = bx.context.new_array_access(None, pointer, i);
let value = bx.context.new_vector_access(None, values, i).to_rvalue();
bx.llbb().add_assignment(None, lvalue, value);
bx.llbb().end_with_jump(None, after_block);
bx.switch_to_block(after_block);
}
let dummy_value = bx.context.new_rvalue_zero(bx.int_type);
return Ok(dummy_value);
}
unimplemented!("simd {}", name);
}

View file

@ -18,7 +18,7 @@
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![deny(clippy::pattern_type_mismatch)]
#![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]
#![expect(clippy::uninlined_format_args)]
// The rustc crates we need
extern crate rustc_abi;
@ -43,7 +43,7 @@ extern crate rustc_target;
extern crate rustc_type_ir;
// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
#[expect(unused_extern_crates)]
extern crate rustc_driver;
mod abi;
@ -69,9 +69,10 @@ mod type_;
mod type_of;
use std::any::Any;
use std::ffi::CString;
use std::fmt::Debug;
use std::ops::Deref;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
@ -142,7 +143,7 @@ impl TargetInfo {
#[derive(Clone)]
pub struct LockedTargetInfo {
info: Arc<Mutex<IntoDynSyncSend<TargetInfo>>>,
info: Arc<Mutex<IntoDynSyncSend<Option<TargetInfo>>>>,
}
impl Debug for LockedTargetInfo {
@ -153,11 +154,21 @@ impl Debug for LockedTargetInfo {
impl LockedTargetInfo {
fn cpu_supports(&self, feature: &str) -> bool {
self.info.lock().expect("lock").cpu_supports(feature)
self.info
.lock()
.expect("lock")
.as_ref()
.expect("target info not initialized")
.cpu_supports(feature)
}
fn supports_target_dependent_type(&self, typ: CType) -> bool {
self.info.lock().expect("lock").supports_target_dependent_type(typ)
self.info
.lock()
.expect("lock")
.as_ref()
.expect("target info not initialized")
.supports_target_dependent_type(typ)
}
}
@ -169,6 +180,23 @@ pub struct GccCodegenBackend {
static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false);
fn load_libgccjit_if_needed(sysroot_path: &Path) {
if gccjit::is_loaded() {
// Do not load a libgccjit second time.
return;
}
let sysroot_lib_dir = sysroot_path.join("lib");
let libgccjit_target_lib_file = sysroot_lib_dir.join("libgccjit.so");
let path = libgccjit_target_lib_file.to_str().expect("libgccjit path");
let string = CString::new(path).expect("string to libgccjit path");
if let Err(error) = gccjit::load(&string) {
panic!("Cannot load libgccjit.so: {}", error);
}
}
impl CodegenBackend for GccCodegenBackend {
fn locale_resource(&self) -> &'static str {
crate::DEFAULT_LOCALE_RESOURCE
@ -178,10 +206,12 @@ impl CodegenBackend for GccCodegenBackend {
"gcc"
}
fn init(&self, _sess: &Session) {
fn init(&self, sess: &Session) {
load_libgccjit_if_needed(sess.opts.sysroot.path());
#[cfg(feature = "master")]
{
let target_cpu = target_cpu(_sess);
let target_cpu = target_cpu(sess);
// Get the second TargetInfo with the correct CPU features by setting the arch.
let context = Context::default();
@ -189,7 +219,8 @@ impl CodegenBackend for GccCodegenBackend {
context.add_command_line_option(format!("-march={}", target_cpu));
}
**self.target_info.info.lock().expect("lock") = context.get_target_info();
*self.target_info.info.lock().expect("lock") =
IntoDynSyncSend(Some(context.get_target_info()));
}
#[cfg(feature = "master")]
@ -217,6 +248,9 @@ impl CodegenBackend for GccCodegenBackend {
.info
.lock()
.expect("lock")
.0
.as_ref()
.expect("target info not initialized")
.supports_128bit_integers
.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
}
@ -438,13 +472,12 @@ pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
let info = {
// Check whether the target supports 128-bit integers, and sized floating point types (like
// Float16).
let context = Context::default();
Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
Arc::new(Mutex::new(IntoDynSyncSend(None)))
};
#[cfg(not(feature = "master"))]
let info = Arc::new(Mutex::new(IntoDynSyncSend(TargetInfo {
let info = Arc::new(Mutex::new(IntoDynSyncSend(Some(TargetInfo {
supports_128bit_integers: AtomicBool::new(false),
})));
}))));
Box::new(GccCodegenBackend {
lto_supported: Arc::new(AtomicBool::new(false)),

View file

@ -15,7 +15,7 @@ use crate::type_of::LayoutGccExt;
use crate::{attributes, base};
impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
#[cfg_attr(not(feature = "master"), expect(unused_variables))]
fn predefine_static(
&mut self,
def_id: DefId,
@ -41,7 +41,6 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.instances.borrow_mut().insert(instance, global);
}
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
fn predefine_fn(
&mut self,
instance: Instance<'tcx>,

View file

@ -299,7 +299,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
value.get_type()
}
#[cfg_attr(feature = "master", allow(unused_mut))]
#[cfg_attr(feature = "master", expect(unused_mut))]
fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
#[cfg(not(feature = "master"))]
if let Some(struct_type) = ty.is_struct()

View file

@ -0,0 +1,7 @@
tests/ui/lto/all-crates.rs
tests/ui/lto/debuginfo-lto-alloc.rs
tests/ui/panic-runtime/lto-unwind.rs
tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
tests/ui/coroutine/panic-drops-resume.rs
tests/ui/coroutine/panic-drops.rs
tests/ui/coroutine/panic-safe.rs

View file

@ -8,7 +8,6 @@ tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
tests/ui/mir/mir_drop_order.rs
tests/ui/mir/mir_let_chains_drop_order.rs
tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
tests/ui/panics/oom-panic-unwind.rs
tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
tests/ui/panic-runtime/abort.rs
tests/ui/panic-runtime/link-to-abort.rs
@ -77,3 +76,15 @@ tests/ui/explicit-tail-calls/recursion-etc.rs
tests/ui/explicit-tail-calls/indexer.rs
tests/ui/explicit-tail-calls/drop-order.rs
tests/ui/c-variadic/valid.rs
tests/ui/c-variadic/inherent-method.rs
tests/ui/c-variadic/trait-method.rs
tests/ui/explicit-tail-calls/become-cast-return.rs
tests/ui/explicit-tail-calls/become-indirect-return.rs
tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs
tests/ui/sanitizer/kcfi-c-variadic.rs
tests/ui/sanitizer/kcfi/fn-trait-objects.rs
tests/ui/statics/const_generics.rs
tests/ui/test-attrs/test-panic-while-printing.rs
tests/ui/thir-print/offset_of.rs
tests/ui/iterators/rangefrom-overflow-debug.rs
tests/ui/iterators/rangefrom-overflow-overflow-checks.rs

View file

@ -2,11 +2,10 @@
#![allow(clippy::uninlined_format_args)]
use std::env::{self, current_dir};
use std::env::current_dir;
use std::path::{Path, PathBuf};
use std::process::Command;
use boml::Toml;
use lang_tester::LangTester;
use tempfile::TempDir;
@ -23,29 +22,6 @@ pub fn main_inner(profile: Profile) {
let current_dir = current_dir().expect("current dir");
let current_dir = current_dir.to_str().expect("current dir").to_string();
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let gcc_path = std::fs::read_to_string(manifest_dir.join("config.toml"))
.ok()
.and_then(|v| {
let toml = Toml::parse(&v).expect("Failed to parse `config.toml`");
toml.get_string("gcc-path").map(PathBuf::from).ok()
})
.unwrap_or_else(|| {
// then we try to retrieve it from the `target` folder.
let commit = include_str!("../libgccjit.version").trim();
Path::new("build/libgccjit").join(commit)
});
let gcc_path = Path::new(&gcc_path)
.canonicalize()
.expect("failed to get absolute path of `gcc-path`")
.display()
.to_string();
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"
}

View file

@ -183,7 +183,8 @@ def update_intrinsics(llvm_path, llvmint, llvmint2):
for arch in archs:
if len(intrinsics[arch]) == 0:
continue
out.write("\"{}\" => {{ #[allow(non_snake_case)] fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch,arch))
attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else ""
out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch))
intrinsics[arch].sort(key=lambda x: (x[0], x[2]))
out.write(' // {}\n'.format(arch))
for entry in intrinsics[arch]: