diff options
| author | Antoni Boucher <bouanto@zoho.com> | 2024-07-02 12:40:16 -0400 |
|---|---|---|
| committer | Antoni Boucher <bouanto@zoho.com> | 2024-07-02 12:40:16 -0400 |
| commit | 05a41b88a90b1a9775e565a1551df49042f6affc (patch) | |
| tree | 7cd581baca66ca46a4fb955ef6dafcb505185fa3 /src | |
| parent | ee41c1904a39d485b11672064f67ffe0236105fc (diff) | |
| parent | 173773e4b473e6d0ec583328e37a6148fa0bb9fa (diff) | |
Merge branch 'master' into sync_from_rust_2024_07_02
Diffstat (limited to 'src')
| -rw-r--r-- | src/abi.rs | 15 | ||||
| -rw-r--r-- | src/asm.rs | 56 | ||||
| -rw-r--r-- | src/attributes.rs | 14 | ||||
| -rw-r--r-- | src/back/lto.rs | 3 | ||||
| -rw-r--r-- | src/back/write.rs | 2 | ||||
| -rw-r--r-- | src/base.rs | 23 | ||||
| -rw-r--r-- | src/builder.rs | 62 | ||||
| -rw-r--r-- | src/callee.rs | 4 | ||||
| -rw-r--r-- | src/common.rs | 11 | ||||
| -rw-r--r-- | src/consts.rs | 11 | ||||
| -rw-r--r-- | src/context.rs | 25 | ||||
| -rw-r--r-- | src/debuginfo.rs | 29 | ||||
| -rw-r--r-- | src/declare.rs | 16 | ||||
| -rw-r--r-- | src/int.rs | 58 | ||||
| -rw-r--r-- | src/intrinsic/archs.rs | 33 | ||||
| -rw-r--r-- | src/intrinsic/llvm.rs | 17 | ||||
| -rw-r--r-- | src/intrinsic/mod.rs | 31 | ||||
| -rw-r--r-- | src/intrinsic/simd.rs | 45 | ||||
| -rw-r--r-- | src/lib.rs | 22 | ||||
| -rw-r--r-- | src/type_.rs | 82 | ||||
| -rw-r--r-- | src/type_of.rs | 4 |
21 files changed, 389 insertions, 174 deletions
diff --git a/src/abi.rs b/src/abi.rs index b098594dbcc..166dd080cf2 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -4,6 +4,7 @@ use gccjit::{ToLValue, ToRValue, Type}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::Ty; #[cfg(feature = "master")] use rustc_session::config; @@ -184,9 +185,17 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { assert!(!on_stack); - let ty = - apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len()); - apply_attrs(ty, &meta_attrs, argument_tys.len()) + // Construct the type of a (wide) pointer to `ty`, and pass its two fields. + // Any two ABI-compatible unsized types have the same metadata type and + // moreover the same metadata value leads to the same dynamic size and + // alignment, so this respects ABI compatibility. + let ptr_ty = Ty::new_mut_ptr(cx.tcx, arg.layout.ty); + let ptr_layout = cx.layout_of(ptr_ty); + let typ1 = ptr_layout.scalar_pair_element_gcc_type(cx, 0); + let typ2 = ptr_layout.scalar_pair_element_gcc_type(cx, 1); + argument_tys.push(apply_attrs(typ1, &attrs, argument_tys.len())); + argument_tys.push(apply_attrs(typ2, &meta_attrs, argument_tys.len())); + continue; } }; argument_tys.push(arg_ty); diff --git a/src/asm.rs b/src/asm.rs index 60e63efe57b..aa485846cd4 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -115,7 +115,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { span: &[Span], instance: Instance<'_>, dest: Option<Self::BasicBlock>, - _catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, + _dest_catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, ) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess().dcx().create_err(UnwindingInlineAsm { span: span[0] }).emit(); @@ -485,9 +485,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } InlineAsmOperandRef::Label { label } => { - let label_gcc_index = labels.iter() - .position(|&l| l == label) - .expect("wrong rust index"); + let label_gcc_index = + labels.iter().position(|&l| l == label).expect("wrong rust index"); let gcc_index = label_gcc_index + outputs.len() + inputs.len(); push_to_template(Some('l'), gcc_index); } @@ -695,10 +694,12 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegClass) -> Type<'gcc> { match reg { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(), - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { - unimplemented!() + cx.type_vector(cx.type_i64(), 2) + } + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) @@ -709,21 +710,13 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { - unimplemented!() + cx.type_vector(cx.type_i64(), 2) } - InlineAsmRegClass::Avr(_) => unimplemented!(), - InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::Msp430(_) => unimplemented!(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), @@ -736,26 +729,43 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => cx.type_f32(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(), - InlineAsmRegClass::X86(X86InlineAsmRegClass::mmx_reg) => unimplemented!(), InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), - InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), - InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(), - InlineAsmRegClass::X86(X86InlineAsmRegClass::tmm_reg) => unimplemented!(), - InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("LLVM backend does not support SPIR-V") + InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::mmx_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::tmm_reg) => { + unreachable!("clobber-only") } + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), InlineAsmRegClass::S390x( S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr, ) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("GCC backend does not support SPIR-V") + } InlineAsmRegClass::Err => unreachable!(), } } diff --git a/src/attributes.rs b/src/attributes.rs index 8602566ab8f..27f21107eda 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -92,7 +92,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( let mut function_features = function_features .iter() .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter()) - .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { + .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match *x { InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature. InstructionSetAttr::ArmT32 => "thumb-mode", })) @@ -118,8 +118,8 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if feature.starts_with('-') { Some(format!("no{}", feature)) - } else if feature.starts_with('+') { - Some(feature[1..].to_string()) + } else if let Some(stripped) = feature.strip_prefix('+') { + Some(stripped.to_string()) } else { Some(feature.to_string()) } @@ -128,6 +128,12 @@ pub fn from_fn_attrs<'gcc, 'tcx>( .join(","); if !target_features.is_empty() { #[cfg(feature = "master")] - func.add_attribute(FnAttribute::Target(&target_features)); + match cx.sess().target.arch.as_ref() { + "x86" | "x86_64" | "powerpc" => { + func.add_attribute(FnAttribute::Target(&target_features)) + } + // The target attribute is not supported on other targets in GCC. + _ => (), + } } } diff --git a/src/back/lto.rs b/src/back/lto.rs index 19964176bcb..19573628b1b 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -130,8 +130,7 @@ fn prepare_lto( } let archive_data = unsafe { - Mmap::map(File::open(&path).expect("couldn't open rlib")) - .expect("couldn't map rlib") + Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib") }; let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); let obj_files = archive diff --git a/src/back/write.rs b/src/back/write.rs index 09d7e692a44..b9bb62a0351 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -105,7 +105,7 @@ pub(crate) unsafe fn codegen( // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by // transmuting an rvalue to an lvalue. // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue - context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); + context.dump_reproducer_to_file(format!("/tmp/reproducers/{}.c", module.name)); println!("Dumped reproducer {}", module.name); } if env::var("CG_GCCJIT_DUMP_TO_FILE").as_deref() == Ok("1") { diff --git a/src/base.rs b/src/base.rs index 488757c4484..be149ffe5a1 100644 --- a/src/base.rs +++ b/src/base.rs @@ -3,7 +3,7 @@ use std::env; use std::sync::Arc; use std::time::Instant; -use gccjit::{FunctionType, GlobalKind}; +use gccjit::{CType, FunctionType, GlobalKind}; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoMethods; @@ -136,7 +136,7 @@ pub fn compile_codegen_unit( let target_cpu = gcc_util::target_cpu(tcx.sess); if target_cpu != "generic" { - context.add_command_line_option(&format!("-march={}", target_cpu)); + context.add_command_line_option(format!("-march={}", target_cpu)); } if tcx @@ -182,7 +182,24 @@ pub fn compile_codegen_unit( context.set_allow_unreachable_blocks(true); { - let cx = CodegenCx::new(&context, cgu, tcx, target_info.supports_128bit_int()); + // TODO: to make it less error-prone (calling get_target_info() will add the flag + // -fsyntax-only), forbid the compilation when get_target_info() is called on a + // context. + let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16); + let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32); + let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64); + let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128); + // TODO: improve this to avoid passing that many arguments. + let cx = CodegenCx::new( + &context, + cgu, + tcx, + target_info.supports_128bit_int(), + f16_type_supported, + f32_type_supported, + f64_type_supported, + f128_type_supported, + ); let mono_items = cgu.items_in_deterministic_order(tcx); for &(mono_item, data) in &mono_items { diff --git a/src/builder.rs b/src/builder.rs index 4cbc8175aa0..1a3509bfca5 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -224,7 +224,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let mut on_stack_param_indices = FxHashSet::default(); if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) { - on_stack_param_indices = indices.clone(); + on_stack_param_indices.clone_from(indices); } if all_args_match { @@ -270,8 +270,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } } else { assert!( - !((actual_ty.is_vector() && !expected_ty.is_vector()) - || (!actual_ty.is_vector() && expected_ty.is_vector())), + (!expected_ty.is_vector() || actual_ty.is_vector()) + && (expected_ty.is_vector() || !actual_ty.is_vector()), "{:?} ({}) -> {:?} ({}), index: {:?}[{}]", actual_ty, actual_ty.is_vector(), @@ -291,8 +291,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { .collect(); // NOTE: to take into account variadic functions. - for i in casted_args.len()..args.len() { - casted_args.push(args[i]); + for arg in args.iter().skip(casted_args.len()) { + casted_args.push(*arg); } Cow::Owned(casted_args) @@ -367,7 +367,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let function_address_names = self.function_address_names.borrow(); let original_function_name = function_address_names.get(&func_ptr); llvm::adjust_intrinsic_arguments( - &self, + self, gcc_func, args.into(), &func_name, @@ -375,7 +375,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ) }; let args_adjusted = args.len() != previous_arg_count; - let args = self.check_ptr_call("call", func_ptr, &*args); + let args = self.check_ptr_call("call", func_ptr, &args); // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). @@ -387,7 +387,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { unsafe { RETURN_VALUE_COUNT += 1 }; let return_value = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); let return_value = llvm::adjust_intrinsic_return_value( - &self, + self, return_value, &func_name, &args, @@ -455,7 +455,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.add_assignment( self.location, result, - self.cx.context.new_call(self.location, func, &args), + self.cx.context.new_call(self.location, func, args), ); result.to_rvalue() } @@ -610,7 +610,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ) -> RValue<'gcc> { let try_block = self.current_func().new_block("try"); - let current_block = self.block.clone(); + let current_block = self.block; self.block = try_block; let call = self.call(typ, fn_attrs, None, func, args, None, instance); // TODO(antoyo): use funclet here? self.block = current_block; @@ -764,6 +764,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): this seems to produce the wrong result. return self.context.new_call(self.location, fmodf, &[a, b]); } + + #[cfg(feature = "master")] + match self.cx.type_kind(a_type) { + TypeKind::Half | TypeKind::Float => { + let fmodf = self.context.get_builtin_function("fmodf"); + return self.context.new_call(self.location, fmodf, &[a, b]); + } + TypeKind::Double => { + let fmod = self.context.get_builtin_function("fmod"); + return self.context.new_call(self.location, fmod, &[a, b]); + } + TypeKind::FP128 => { + let fmodl = self.context.get_builtin_function("fmodl"); + return self.context.new_call(self.location, fmodl, &[a, b]); + } + _ => (), + } + if let Some(vector_type) = a_type_unqualified.dyncast_vector() { assert_eq!(a_type_unqualified, b.get_type().unqualified()); @@ -1136,7 +1154,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the following cast is required to avoid this error: // gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int __attribute__((aligned(4)))) let int_type = atomic_store.get_param(1).to_rvalue().get_type(); - let value = self.context.new_cast(self.location, value, int_type); + let value = self.context.new_bitcast(self.location, value, int_type); self.llbb().add_eval( self.location, self.context.new_call(self.location, atomic_store, &[ptr, value, ordering]), @@ -1183,7 +1201,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: due to opaque pointers now being used, we need to cast here. let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer()); // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified). - let mut indices = indices.into_iter(); + let mut indices = indices.iter(); let index = indices.next().expect("first index in inbounds_gep"); let mut result = self.context.new_array_access(self.location, ptr, *index); for index in indices { @@ -1687,6 +1705,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { // FIXME(antoyo): this does not zero-extend. +<<<<<<< HEAD +======= + if value.get_type().is_bool() && dest_typ.is_i8(self.cx) { + // FIXME(antoyo): hack because base::from_immediate converts i1 to i8. + // Fix the code in codegen_ssa::base::from_immediate. + return value; + } +>>>>>>> master self.gcc_int_cast(value, dest_typ) } @@ -2055,7 +2081,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements); let shifted = self.context.new_rvalue_vector_perm(self.location, res, res, mask); shift *= 2; - res = op(res, shifted, &self.context); + res = op(res, shifted, self.context); } self.context .new_vector_access(self.location, res, self.context.new_rvalue_zero(self.int_type)) @@ -2071,7 +2097,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn vector_reduce_op(&mut self, src: RValue<'gcc>, op: BinaryOp) -> RValue<'gcc> { - let loc = self.location.clone(); + let loc = self.location; self.vector_reduce(src, |a, b, context| context.new_binary_op(loc, op, a.get_type(), a, b)) } @@ -2088,7 +2114,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); let element_count = vector_type.get_num_units(); (0..element_count) - .into_iter() .map(|i| { self.context .new_vector_access( @@ -2119,7 +2144,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); let element_count = vector_type.get_num_units(); (0..element_count) - .into_iter() .map(|i| { self.context .new_vector_access( @@ -2139,7 +2163,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Inspired by Hacker's Delight min implementation. pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { - let loc = self.location.clone(); + let loc = self.location; self.vector_reduce(src, |a, b, context| { let differences_or_zeros = difference_or_zero(loc, a, b, context); context.new_binary_op(loc, BinaryOp::Plus, b.get_type(), b, differences_or_zeros) @@ -2148,7 +2172,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Inspired by Hacker's Delight max implementation. pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { - let loc = self.location.clone(); + let loc = self.location; self.vector_reduce(src, |a, b, context| { let differences_or_zeros = difference_or_zero(loc, a, b, context); context.new_binary_op(loc, BinaryOp::Minus, a.get_type(), a, differences_or_zeros) @@ -2343,7 +2367,7 @@ impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> { fn target_spec(&self) -> &Target { - &self.cx.target_spec() + self.cx.target_spec() } } diff --git a/src/callee.rs b/src/callee.rs index 84f49b6856d..9ad2e90122f 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -28,7 +28,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); - let func = if let Some(_func) = cx.get_declared_value(&sym) { + let func = if let Some(_func) = cx.get_declared_value(sym) { // FIXME(antoyo): we never reach this because get_declared_value only returns global variables // and here we try to get a function. unreachable!(); @@ -68,7 +68,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) }*/ } else { cx.linkage.set(FunctionType::Extern); - let func = cx.declare_fn(&sym, &fn_abi); + let func = cx.declare_fn(sym, fn_abi); attributes::from_fn_attrs(cx, func, instance); diff --git a/src/common.rs b/src/common.rs index 230fe4f5871..35699346b29 100644 --- a/src/common.rs +++ b/src/common.rs @@ -21,7 +21,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn global_string(&self, string: &str) -> LValue<'gcc> { // TODO(antoyo): handle non-null-terminated strings. - let string = self.context.new_string_literal(&*string); + let string = self.context.new_string_literal(string); let sym = self.generate_local_symbol_name("str"); let global = self.declare_private_global(&sym, self.val_ty(string)); global.global_set_initializer_rvalue(string); @@ -187,7 +187,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { return self .context .new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64); - } else if ty == self.double_type { + } + if ty == self.double_type { return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64)); } @@ -297,7 +298,7 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { } else if self.is_ulonglong(cx) { cx.longlong_type } else { - self.clone() + *self } } @@ -323,7 +324,7 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { } else if self.is_longlong(cx) { cx.ulonglong_type } else { - self.clone() + *self } } } @@ -436,7 +437,7 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { } fn is_vector(&self) -> bool { - let mut typ = self.clone(); + let mut typ = *self; loop { if typ.dyncast_vector().is_some() { return true; diff --git a/src/consts.rs b/src/consts.rs index 50f3a4e0402..ba7e08e33ef 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -382,11 +382,8 @@ fn check_and_apply_linkage<'gcc, 'tcx>( let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); if let Some(linkage) = attrs.import_linkage { // Declare a symbol `foo` with the desired linkage. - let global1 = cx.declare_global_with_linkage( - &sym, - cx.type_i8(), - base::global_linkage_to_gcc(linkage), - ); + let global1 = + cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); // Declare an internal global `extern_with_linkage_foo` which // is initialized with the address of `foo`. If `foo` is @@ -395,7 +392,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>( // `extern_with_linkage_foo` will instead be initialized to // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&sym); + real_name.push_str(sym); let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section); // TODO(antoyo): set linkage. let value = cx.const_ptrcast(global1.get_address(None), gcc_type); @@ -412,6 +409,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>( // don't do this then linker errors can be generated where the linker // complains that one object files has a thread local version of the // symbol and another one doesn't. - cx.declare_global(&sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section) + cx.declare_global(sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section) } } diff --git a/src/context.rs b/src/context.rs index c5d5c6bc846..4458ca84bbb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -68,6 +68,10 @@ pub struct CodegenCx<'gcc, 'tcx> { pub sizet_type: Type<'gcc>, pub supports_128bit_integers: bool, + pub supports_f16_type: bool, + pub supports_f32_type: bool, + pub supports_f64_type: bool, + pub supports_f128_type: bool, pub float_type: Type<'gcc>, pub double_type: Type<'gcc>, @@ -127,11 +131,16 @@ pub struct CodegenCx<'gcc, 'tcx> { } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + #[allow(clippy::too_many_arguments)] pub fn new( context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool, + supports_f16_type: bool, + supports_f32_type: bool, + supports_f64_type: bool, + supports_f128_type: bool, ) -> Self { let create_type = |ctype, rust_type| { let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap(); @@ -304,6 +313,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { sizet_type, supports_128bit_integers, + supports_f16_type, + supports_f32_type, + supports_f64_type, + supports_f128_type, float_type, double_type, @@ -385,7 +398,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn sess(&self) -> &'tcx Session { - &self.tcx.sess + self.tcx.sess } pub fn bitcast_if_needed( @@ -432,7 +445,9 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let func_name = self.tcx.symbol_name(instance).name; let func = if self.intrinsics.borrow().contains_key(func_name) { - self.intrinsics.borrow()[func_name].clone() + self.intrinsics.borrow()[func_name] + } else if let Some(variable) = self.get_declared_value(func_name) { + return variable; } else { get_fn(self, instance) }; @@ -484,7 +499,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let symbol_name = tcx.symbol_name(instance).name; let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(FunctionType::Extern); - let func = self.declare_fn(symbol_name, &fn_abi); + let func = self.declare_fn(symbol_name, fn_abi); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; func } @@ -504,7 +519,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn sess(&self) -> &Session { - &self.tcx.sess + self.tcx.sess } fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { @@ -521,7 +536,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> { let entry_name = self.sess().target.entry_name.as_ref(); - if self.get_declared_value(entry_name).is_none() { + if !self.functions.borrow().contains_key(entry_name) { Some(self.declare_entry_fn(entry_name, fn_type, ())) } else { // If the symbol already exists, it is an error: for example, the user wrote diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 1d0a6d9f09b..3d9ea278a63 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -90,7 +90,7 @@ fn compute_mir_scopes<'gcc, 'tcx>( /// FIXME(tempdragon/?): Add Scope Support Here. fn make_mir_scope<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, - instance: Instance<'tcx>, + _instance: Instance<'tcx>, mir: &Body<'tcx>, variables: &Option<BitSet<SourceScope>>, debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, @@ -103,7 +103,7 @@ fn make_mir_scope<'gcc, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent); + make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); debug_context.scopes[parent] } else { // The root is the function itself. @@ -117,7 +117,7 @@ fn make_mir_scope<'gcc, 'tcx>( return; }; - if let Some(vars) = variables { + if let Some(ref vars) = *variables { if !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. @@ -135,8 +135,14 @@ fn make_mir_scope<'gcc, 'tcx>( let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { // FIXME(eddyb) this doesn't account for the macro-related // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. - let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); - cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) + + // TODO(tempdragon): Add scope support and then revert to cg_llvm version of this closure + // NOTE: These variables passed () here. + // Changed to comply to clippy. + + /* let callsite_scope = */ + parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); + cx.dbg_loc(/* callsite_scope */ (), parent_scope.inlined_at, callsite_span) }); let p_inlined_at = parent_scope.inlined_at; // TODO(tempdragon): dbg_scope: Add support for scope extension here. @@ -224,7 +230,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { file_end_pos: BytePos(0), }; let mut fn_debug_context = FunctionDebugContext { - scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes.as_slice()), + scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), inlined_function_scopes: Default::default(), }; @@ -273,16 +279,19 @@ impl<'gcc, 'tcx> DebugInfoMethods<'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 { - rustc_span::FileName::Real(name) => match name { - rustc_span::RealFileName::LocalPath(name) => { + let loc = match file.name { + rustc_span::FileName::Real(ref name) => match *name { + rustc_span::RealFileName::LocalPath(ref name) => { if let Some(name) = name.to_str() { self.context.new_location(name, line as i32, col as i32) } else { Location::null() } } - rustc_span::RealFileName::Remapped { local_path, virtual_name: _ } => { + rustc_span::RealFileName::Remapped { + ref local_path, + virtual_name: ref _unused, + } => { if let Some(name) = local_path.as_ref() { if let Some(name) = name.to_str() { self.context.new_location(name, line as i32, col as i32) diff --git a/src/declare.rs b/src/declare.rs index db6edbab12d..a2b158ee0a7 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -35,7 +35,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> { let name = self.generate_local_symbol_name("global"); - self.context.new_global(None, GlobalKind::Internal, ty, &name) + self.context.new_global(None, GlobalKind::Internal, ty, name) } pub fn declare_global_with_linkage( @@ -176,16 +176,14 @@ fn declare_raw_fn<'gcc>( cx.functions.borrow()[name] } else { let params: Vec<_> = param_types - .into_iter() + .iter() .enumerate() - .map(|(index, param)| { - cx.context.new_parameter(None, *param, &format!("param{}", index)) - }) // TODO(antoyo): set name. + .map(|(index, param)| cx.context.new_parameter(None, *param, format!("param{}", index))) // TODO(antoyo): set name. .collect(); #[cfg(not(feature = "master"))] - let name = mangle_name(name); + let name = &mangle_name(name); let func = - cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, &name, variadic); + cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic); cx.functions.borrow_mut().insert(name.to_string(), func); #[cfg(feature = "master")] @@ -200,10 +198,10 @@ fn declare_raw_fn<'gcc>( // create a wrapper function that calls rust_eh_personality. let params: Vec<_> = param_types - .into_iter() + .iter() .enumerate() .map(|(index, param)| { - cx.context.new_parameter(None, *param, &format!("param{}", index)) + cx.context.new_parameter(None, *param, format!("param{}", index)) }) // TODO(antoyo): set name. .collect(); let gcc_func = cx.context.new_function( diff --git a/src/int.rs b/src/int.rs index a095dd39539..e4c5eb91373 100644 --- a/src/int.rs +++ b/src/int.rs @@ -2,8 +2,6 @@ //! This module exists because some integer types are not supported on some gcc platforms, e.g. //! 128-bit integers on 32-bit platforms and thus require to be handled manually. -use std::convert::TryFrom; - use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp}; @@ -40,7 +38,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.cx.context.new_unary_op(self.location, operation, typ, a) } else { let element_type = typ.dyncast_array().expect("element type"); - self.from_low_high_rvalues( + self.concat_low_high_rvalues( typ, self.cx.context.new_unary_op( self.location, @@ -126,7 +124,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let shift_value = self.gcc_sub(b, sixty_four); let high = self.high(a); let sign = if a_type.is_signed(self) { high >> sixty_three } else { zero }; - let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign); + let array_value = self.concat_low_high_rvalues(a_type, high >> shift_value, sign); then_block.add_assignment(self.location, result, array_value); then_block.end_with_jump(self.location, after_block); @@ -138,12 +136,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let shift_value = self.gcc_sub(sixty_four, b); // NOTE: cast low to its unsigned type in order to perform a logical right shift. - let unsigned_type = native_int_type.to_unsigned(&self.cx); + let unsigned_type = native_int_type.to_unsigned(self.cx); let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type); let shifted_low = casted_low >> self.context.new_cast(self.location, b, unsigned_type); let shifted_low = self.context.new_cast(self.location, shifted_low, native_int_type); - let array_value = - self.from_low_high_rvalues(a_type, (high << shift_value) | shifted_low, high >> b); + let array_value = self.concat_low_high_rvalues( + a_type, + (high << shift_value) | shifted_low, + high >> b, + ); actual_else_block.add_assignment(self.location, result, array_value); actual_else_block.end_with_jump(self.location, after_block); @@ -267,10 +268,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) { use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*}; - let new_kind = match typ.kind() { + let new_kind = match *typ.kind() { Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)), Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)), - t @ (Uint(_) | Int(_)) => t.clone(), + t @ (Uint(_) | Int(_)) => t, _ => panic!("tried to get overflow intrinsic for op applied to non-int type"), }; @@ -356,7 +357,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } }; - let intrinsic = self.context.get_builtin_function(&name); + let intrinsic = self.context.get_builtin_function(name); let res = self .current_func() // TODO(antoyo): is it correct to use rhs type instead of the parameter typ? @@ -466,7 +467,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let native_int_type = a_type.dyncast_array().expect("get element type"); // NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g. // the sign is only on high). - let unsigned_type = native_int_type.to_unsigned(&self.cx); + let unsigned_type = native_int_type.to_unsigned(self.cx); let lhs_low = self.context.new_cast(self.location, self.low(lhs), unsigned_type); let rhs_low = self.context.new_cast(self.location, self.low(rhs), unsigned_type); @@ -601,7 +602,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { | IntPredicate::IntULT | IntPredicate::IntULE => { if !a_type.is_vector() { - let unsigned_type = a_type.to_unsigned(&self.cx); + let unsigned_type = a_type.to_unsigned(self.cx); lhs = self.context.new_cast(self.location, lhs, unsigned_type); rhs = self.context.new_cast(self.location, rhs, unsigned_type); } @@ -624,7 +625,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { { a ^ b } else { - self.from_low_high_rvalues( + self.concat_low_high_rvalues( a_type, self.low(a) ^ self.low(b), self.high(a) ^ self.high(b), @@ -685,7 +686,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.llbb().end_with_conditional(self.location, condition, then_block, else_block); let array_value = - self.from_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four)); + self.concat_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four)); then_block.add_assignment(self.location, result, array_value); then_block.end_with_jump(self.location, after_block); @@ -697,13 +698,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // NOTE: cast low to its unsigned type in order to perform a logical right shift. // TODO(antoyo): adjust this ^ comment. - let unsigned_type = native_int_type.to_unsigned(&self.cx); + let unsigned_type = native_int_type.to_unsigned(self.cx); let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type); let shift_value = self.context.new_cast(self.location, sixty_four - b, unsigned_type); let high_low = self.context.new_cast(self.location, casted_low >> shift_value, native_int_type); - let array_value = self.from_low_high_rvalues( + let array_value = self.concat_low_high_rvalues( a_type, self.low(a) << b, (self.high(a) << b) | high_low, @@ -732,7 +733,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // NOTE: we also need to swap the two elements here, in addition to swapping inside // the elements themselves like done above. - return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb); + return self.concat_low_high_rvalues(arg_type, swapped_msb, swapped_lsb); } // TODO(antoyo): check if it's faster to use string literals and a @@ -751,10 +752,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> { if self.is_native_int_type_or_bool(typ) { - self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from")) + self.context.new_rvalue_from_long(typ, int) } else { // NOTE: set the sign in high. - self.from_low_high(typ, int, -(int.is_negative() as i64)) + self.concat_low_high(typ, int, -(int.is_negative() as i64)) } } @@ -764,10 +765,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let num = self.context.new_rvalue_from_long(self.u64_type, int as i64); self.gcc_int_cast(num, typ) } else if self.is_native_int_type_or_bool(typ) { - self.context - .new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64) + self.context.new_rvalue_from_long(typ, int as i64) } else { - self.from_low_high(typ, int as i64, 0) + self.concat_low_high(typ, int as i64, 0) } } @@ -784,7 +784,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let shift = high << sixty_four; shift | self.context.new_cast(None, low, typ) } else { - self.from_low_high(typ, low as i64, high as i64) + self.concat_low_high(typ, low as i64, high as i64) } } else if typ.is_i128(self) { // FIXME(antoyo): libgccjit cannot create 128-bit values yet. @@ -799,7 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { if self.is_native_int_type_or_bool(typ) { self.context.new_rvalue_zero(typ) } else { - self.from_low_high(typ, 0, 0) + self.concat_low_high(typ, 0, 0) } } @@ -837,7 +837,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { "both types should either be native or non-native for or operation" ); let native_int_type = a_type.dyncast_array().expect("get element type"); - self.from_low_high_rvalues( + self.concat_low_high_rvalues( a_type, self.context.new_binary_op( loc, @@ -882,7 +882,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero); let is_negative = self.gcc_int_cast(is_negative, dest_element_type); - self.from_low_high_rvalues( + self.concat_low_high_rvalues( dest_typ, self.context.new_cast(None, value, dest_element_type), self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative), @@ -950,7 +950,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return self.context.new_cast(None, value, dest_typ); } - debug_assert!(value_type.dyncast_array().is_some()); + debug_assert!(dest_typ.dyncast_array().is_some()); let name_suffix = match self.type_kind(value_type) { TypeKind::Float => "sfti", TypeKind::Double => "dfti", @@ -1002,7 +1002,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { .to_rvalue() } - fn from_low_high_rvalues( + fn concat_low_high_rvalues( &self, typ: Type<'gcc>, low: RValue<'gcc>, @@ -1017,7 +1017,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.context.new_array_constructor(None, typ, &values) } - fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> { + fn concat_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> { let (first, last) = match self.sess().target.options.endian { Endian::Little => (low, high), Endian::Big => (high, low), diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index c4ae1751fa0..f7500933789 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -74,6 +74,10 @@ match name { "llvm.amdgcn.cvt.sr.bf8.f32" => "__builtin_amdgcn_cvt_sr_bf8_f32", "llvm.amdgcn.cvt.sr.fp8.f32" => "__builtin_amdgcn_cvt_sr_fp8_f32", "llvm.amdgcn.dispatch.id" => "__builtin_amdgcn_dispatch_id", + "llvm.amdgcn.dot4.f32.bf8.bf8" => "__builtin_amdgcn_dot4_f32_bf8_bf8", + "llvm.amdgcn.dot4.f32.bf8.fp8" => "__builtin_amdgcn_dot4_f32_bf8_fp8", + "llvm.amdgcn.dot4.f32.fp8.bf8" => "__builtin_amdgcn_dot4_f32_fp8_bf8", + "llvm.amdgcn.dot4.f32.fp8.fp8" => "__builtin_amdgcn_dot4_f32_fp8_fp8", "llvm.amdgcn.ds.add.gs.reg.rtn" => "__builtin_amdgcn_ds_add_gs_reg_rtn", "llvm.amdgcn.ds.bpermute" => "__builtin_amdgcn_ds_bpermute", "llvm.amdgcn.ds.fadd.v2bf16" => "__builtin_amdgcn_ds_atomic_fadd_v2bf16", @@ -2291,6 +2295,10 @@ match name { "llvm.loongarch.csrxchg.d" => "__builtin_loongarch_csrxchg_d", "llvm.loongarch.csrxchg.w" => "__builtin_loongarch_csrxchg_w", "llvm.loongarch.dbar" => "__builtin_loongarch_dbar", + "llvm.loongarch.frecipe.d" => "__builtin_loongarch_frecipe_d", + "llvm.loongarch.frecipe.s" => "__builtin_loongarch_frecipe_s", + "llvm.loongarch.frsqrte.d" => "__builtin_loongarch_frsqrte_d", + "llvm.loongarch.frsqrte.s" => "__builtin_loongarch_frsqrte_s", "llvm.loongarch.ibar" => "__builtin_loongarch_ibar", "llvm.loongarch.iocsrrd.b" => "__builtin_loongarch_iocsrrd_b", "llvm.loongarch.iocsrrd.d" => "__builtin_loongarch_iocsrrd_d", @@ -2529,6 +2537,8 @@ match name { "llvm.loongarch.lasx.xvfnmsub.s" => "__builtin_lasx_xvfnmsub_s", "llvm.loongarch.lasx.xvfrecip.d" => "__builtin_lasx_xvfrecip_d", "llvm.loongarch.lasx.xvfrecip.s" => "__builtin_lasx_xvfrecip_s", + "llvm.loongarch.lasx.xvfrecipe.d" => "__builtin_lasx_xvfrecipe_d", + "llvm.loongarch.lasx.xvfrecipe.s" => "__builtin_lasx_xvfrecipe_s", "llvm.loongarch.lasx.xvfrint.d" => "__builtin_lasx_xvfrint_d", "llvm.loongarch.lasx.xvfrint.s" => "__builtin_lasx_xvfrint_s", "llvm.loongarch.lasx.xvfrintrm.d" => "__builtin_lasx_xvfrintrm_d", @@ -2541,6 +2551,8 @@ match name { "llvm.loongarch.lasx.xvfrintrz.s" => "__builtin_lasx_xvfrintrz_s", "llvm.loongarch.lasx.xvfrsqrt.d" => "__builtin_lasx_xvfrsqrt_d", "llvm.loongarch.lasx.xvfrsqrt.s" => "__builtin_lasx_xvfrsqrt_s", + "llvm.loongarch.lasx.xvfrsqrte.d" => "__builtin_lasx_xvfrsqrte_d", + "llvm.loongarch.lasx.xvfrsqrte.s" => "__builtin_lasx_xvfrsqrte_s", "llvm.loongarch.lasx.xvfrstp.b" => "__builtin_lasx_xvfrstp_b", "llvm.loongarch.lasx.xvfrstp.h" => "__builtin_lasx_xvfrstp_h", "llvm.loongarch.lasx.xvfrstpi.b" => "__builtin_lasx_xvfrstpi_b", @@ -3255,6 +3267,8 @@ match name { "llvm.loongarch.lsx.vfnmsub.s" => "__builtin_lsx_vfnmsub_s", "llvm.loongarch.lsx.vfrecip.d" => "__builtin_lsx_vfrecip_d", "llvm.loongarch.lsx.vfrecip.s" => "__builtin_lsx_vfrecip_s", + "llvm.loongarch.lsx.vfrecipe.d" => "__builtin_lsx_vfrecipe_d", + "llvm.loongarch.lsx.vfrecipe.s" => "__builtin_lsx_vfrecipe_s", "llvm.loongarch.lsx.vfrint.d" => "__builtin_lsx_vfrint_d", "llvm.loongarch.lsx.vfrint.s" => "__builtin_lsx_vfrint_s", "llvm.loongarch.lsx.vfrintrm.d" => "__builtin_lsx_vfrintrm_d", @@ -3267,6 +3281,8 @@ match name { "llvm.loongarch.lsx.vfrintrz.s" => "__builtin_lsx_vfrintrz_s", "llvm.loongarch.lsx.vfrsqrt.d" => "__builtin_lsx_vfrsqrt_d", "llvm.loongarch.lsx.vfrsqrt.s" => "__builtin_lsx_vfrsqrt_s", + "llvm.loongarch.lsx.vfrsqrte.d" => "__builtin_lsx_vfrsqrte_d", + "llvm.loongarch.lsx.vfrsqrte.s" => "__builtin_lsx_vfrsqrte_s", "llvm.loongarch.lsx.vfrstp.b" => "__builtin_lsx_vfrstp_b", "llvm.loongarch.lsx.vfrstp.h" => "__builtin_lsx_vfrstp_h", "llvm.loongarch.lsx.vfrstpi.b" => "__builtin_lsx_vfrstpi_b", @@ -4434,6 +4450,7 @@ match name { "llvm.nvvm.abs.bf16x2" => "__nvvm_abs_bf16x2", "llvm.nvvm.abs.i" => "__nvvm_abs_i", "llvm.nvvm.abs.ll" => "__nvvm_abs_ll", + "llvm.nvvm.activemask" => "__nvvm_activemask", "llvm.nvvm.add.rm.d" => "__nvvm_add_rm_d", "llvm.nvvm.add.rm.f" => "__nvvm_add_rm_f", "llvm.nvvm.add.rm.ftz.f" => "__nvvm_add_rm_ftz_f", @@ -4522,6 +4539,7 @@ match name { "llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d", "llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f", "llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", + "llvm.nvvm.exit" => "__nvvm_exit", "llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn", "llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu", "llvm.nvvm.f2bf16.rz" => "__nvvm_f2bf16_rz", @@ -4722,8 +4740,11 @@ match name { "llvm.nvvm.mul24.ui" => "__nvvm_mul24_ui", "llvm.nvvm.mulhi.i" => "__nvvm_mulhi_i", "llvm.nvvm.mulhi.ll" => "__nvvm_mulhi_ll", + "llvm.nvvm.mulhi.s" => "__nvvm_mulhi_s", "llvm.nvvm.mulhi.ui" => "__nvvm_mulhi_ui", "llvm.nvvm.mulhi.ull" => "__nvvm_mulhi_ull", + "llvm.nvvm.mulhi.us" => "__nvvm_mulhi_us", + "llvm.nvvm.nanosleep" => "__nvvm_nanosleep", "llvm.nvvm.neg.bf16" => "__nvvm_neg_bf16", "llvm.nvvm.neg.bf16x2" => "__nvvm_neg_bf16x2", "llvm.nvvm.popc.i" => "__nvvm_popc_i", @@ -4783,6 +4804,7 @@ match name { "llvm.nvvm.read.ptx.sreg.envreg7" => "__nvvm_read_ptx_sreg_envreg7", "llvm.nvvm.read.ptx.sreg.envreg8" => "__nvvm_read_ptx_sreg_envreg8", "llvm.nvvm.read.ptx.sreg.envreg9" => "__nvvm_read_ptx_sreg_envreg9", + "llvm.nvvm.read.ptx.sreg.globaltimer" => "__nvvm_read_ptx_sreg_globaltimer", "llvm.nvvm.read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_gridid", // [DUPLICATE]: "llvm.nvvm.read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_", "llvm.nvvm.read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_laneid", @@ -4835,6 +4857,7 @@ match name { "llvm.nvvm.redux.sync.umax" => "__nvvm_redux_sync_umax", "llvm.nvvm.redux.sync.umin" => "__nvvm_redux_sync_umin", "llvm.nvvm.redux.sync.xor" => "__nvvm_redux_sync_xor", + "llvm.nvvm.reflect" => "__nvvm_reflect", "llvm.nvvm.rotate.b32" => "__nvvm_rotate_b32", "llvm.nvvm.rotate.b64" => "__nvvm_rotate_b64", "llvm.nvvm.rotate.right.b64" => "__nvvm_rotate_right_b64", @@ -4845,7 +4868,11 @@ match name { "llvm.nvvm.rsqrt.approx.f" => "__nvvm_rsqrt_approx_f", "llvm.nvvm.rsqrt.approx.ftz.f" => "__nvvm_rsqrt_approx_ftz_f", "llvm.nvvm.sad.i" => "__nvvm_sad_i", + "llvm.nvvm.sad.ll" => "__nvvm_sad_ll", + "llvm.nvvm.sad.s" => "__nvvm_sad_s", "llvm.nvvm.sad.ui" => "__nvvm_sad_ui", + "llvm.nvvm.sad.ull" => "__nvvm_sad_ull", + "llvm.nvvm.sad.us" => "__nvvm_sad_us", "llvm.nvvm.saturate.d" => "__nvvm_saturate_d", "llvm.nvvm.saturate.f" => "__nvvm_saturate_f", "llvm.nvvm.saturate.ftz.f" => "__nvvm_saturate_ftz_f", @@ -5471,6 +5498,7 @@ match name { "llvm.ppc.fctiwz" => "__builtin_ppc_fctiwz", "llvm.ppc.fctudz" => "__builtin_ppc_fctudz", "llvm.ppc.fctuwz" => "__builtin_ppc_fctuwz", + "llvm.ppc.fence" => "__builtin_ppc_fence", "llvm.ppc.fmaf128.round.to.odd" => "__builtin_fmaf128_round_to_odd", "llvm.ppc.fmsub" => "__builtin_ppc_fmsub", "llvm.ppc.fmsubs" => "__builtin_ppc_fmsubs", @@ -5599,6 +5627,9 @@ match name { "llvm.ppc.qpx.qvstfs" => "__builtin_qpx_qvstfs", "llvm.ppc.qpx.qvstfsa" => "__builtin_qpx_qvstfsa", "llvm.ppc.readflm" => "__builtin_readflm", + "llvm.ppc.rldimi" => "__builtin_ppc_rldimi", + "llvm.ppc.rlwimi" => "__builtin_ppc_rlwimi", + "llvm.ppc.rlwnm" => "__builtin_ppc_rlwnm", "llvm.ppc.scalar.extract.expq" => "__builtin_vsx_scalar_extract_expq", "llvm.ppc.scalar.insert.exp.qp" => "__builtin_vsx_scalar_insert_exp_qp", "llvm.ppc.set.texasr" => "__builtin_set_texasr", @@ -5912,6 +5943,8 @@ match name { "llvm.s390.vupllb" => "__builtin_s390_vupllb", "llvm.s390.vupllf" => "__builtin_s390_vupllf", "llvm.s390.vupllh" => "__builtin_s390_vupllh", + // spv + "llvm.spv.create.handle" => "__builtin_hlsl_create_handle", // ve "llvm.ve.vl.andm.MMM" => "__builtin_ve_vl_andm_MMM", "llvm.ve.vl.andm.mmm" => "__builtin_ve_vl_andm_mmm", diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index ce8dee69a98..a1270482219 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -15,7 +15,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( // Some LLVM intrinsics do not map 1-to-1 to GCC intrinsics, so we add the missing // arguments here. if gcc_func.get_param_count() != args.len() { - match &*func_name { + match func_name { // NOTE: the following intrinsics have a different number of parameters in LLVM and GCC. "__builtin_ia32_prold512_mask" | "__builtin_ia32_pmuldq512_mask" @@ -380,7 +380,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( _ => (), } } else { - match &*func_name { + match func_name { "__builtin_ia32_rndscaless_mask_round" | "__builtin_ia32_rndscalesd_mask_round" => { let new_args = args.to_vec(); let arg3_type = gcc_func.get_param_type(2); @@ -629,17 +629,22 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function #[cfg(feature = "master")] pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> { - match name { + let gcc_name = match name { "llvm.prefetch" => { let gcc_name = "__builtin_prefetch"; let func = cx.context.get_builtin_function(gcc_name); cx.functions.borrow_mut().insert(gcc_name.to_string(), func); return func; } - _ => (), - } - let gcc_name = match name { + "llvm.aarch64.isb" => { + // FIXME: GCC doesn't support __builtin_arm_isb yet, check if this builtin is OK. + let gcc_name = "__atomic_thread_fence"; + let func = cx.context.get_builtin_function(gcc_name); + cx.functions.borrow_mut().insert(gcc_name.to_string(), func); + return func; + } + "llvm.x86.xgetbv" => "__builtin_ia32_xgetbv", // NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html "llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd", diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 1e09572e612..864bc98a4b7 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -91,7 +91,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::abort => "abort", _ => return None, }; - Some(cx.context.get_builtin_function(&gcc_name)) + Some(cx.context.get_builtin_function(gcc_name)) } impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { @@ -122,6 +122,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let simple = get_simple_intrinsic(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 + // and leave `else if use_integer_compare` to be placed "as is". + #[allow(clippy::suspicious_else_formatting)] let llval = match name { _ if simple.is_some() => { // FIXME(antoyo): remove this cast when the API supports function. @@ -169,7 +174,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = fn_args.type_at(0); let ptr = args[0].immediate(); - let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode { + let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode { let gcc_ty = ty.gcc_type(self); self.volatile_load(gcc_ty, ptr) } else { @@ -388,7 +393,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { }; if !fn_abi.ret.is_ignore() { - if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode { + if let PassMode::Cast { cast: ref ty, .. } = fn_abi.ret.mode { let ptr_llty = self.type_ptr_to(ty.gcc_type(self)); let ptr = self.pointercast(result.val.llval, ptr_llty); self.store(llval, ptr, result.val.align); @@ -594,7 +599,7 @@ fn int_type_width_signed<'gcc, 'tcx>( ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>, ) -> Option<(u64, bool)> { - match ty.kind() { + match *ty.kind() { ty::Int(t) => Some(( match t { rustc_middle::ty::IntTy::Isize => u64::from(cx.tcx.sess.target.pointer_width), @@ -707,13 +712,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let count_leading_zeroes = // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here // instead of using is_uint(). - if arg_type.is_uint(&self.cx) { + if arg_type.is_uint(self.cx) { "__builtin_clz" } - else if arg_type.is_ulong(&self.cx) { + else if arg_type.is_ulong(self.cx) { "__builtin_clzl" } - else if arg_type.is_ulonglong(&self.cx) { + else if arg_type.is_ulonglong(self.cx) { "__builtin_clzll" } else if width == 128 { @@ -788,17 +793,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let (count_trailing_zeroes, expected_type) = // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here // instead of using is_uint(). - if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) { + if arg_type.is_uchar(self.cx) || arg_type.is_ushort(self.cx) || arg_type.is_uint(self.cx) { // NOTE: we don't need to & 0xFF for uchar because the result is undefined on zero. ("__builtin_ctz", self.cx.uint_type) } - else if arg_type.is_ulong(&self.cx) { + else if arg_type.is_ulong(self.cx) { ("__builtin_ctzl", self.cx.ulong_type) } - else if arg_type.is_ulonglong(&self.cx) { + else if arg_type.is_ulonglong(self.cx) { ("__builtin_ctzll", self.cx.ulonglong_type) } - else if arg_type.is_u128(&self.cx) { + else if arg_type.is_u128(self.cx) { // Adapted from the algorithm to count leading zeroes from: https://stackoverflow.com/a/28433850/389119 let array_type = self.context.new_array_type(None, arg_type, 3); let result = self.current_func() @@ -880,7 +885,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // only break apart 128-bit ints if they're not natively supported // TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit - if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers { + if value_type.is_u128(self.cx) && !self.cx.supports_128bit_integers { let sixty_four = self.gcc_int(value_type, 64); let right_shift = self.gcc_lshr(value, sixty_four); let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type); @@ -1003,7 +1008,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Return `result_type`'s maximum or minimum value on overflow // NOTE: convert the type to unsigned to have an unsigned shift. - let unsigned_type = result_type.to_unsigned(&self.cx); + let unsigned_type = result_type.to_unsigned(self.cx); let shifted = self.gcc_lshr( self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1), diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 01f207368e8..ba214a9c24c 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -73,11 +73,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let expected_bytes = len / 8 + ((len % 8 > 0) as u64); let mask_ty = arg_tys[0]; - let mut mask = match mask_ty.kind() { + let mut mask = match *mask_ty.kind() { ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), ty::Array(elem, len) - if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + if matches!(*elem.kind(), ty::Uint(ty::UintTy::U8)) && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all()) == Some(expected_bytes) => { @@ -310,10 +310,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }) .collect(); return Ok(bx.context.new_rvalue_from_vector(None, v_type, &elems)); - } else { - // avoid the unnecessary truncation as an optimization. - return Ok(bx.context.new_bitcast(None, result, v_type)); } + // avoid the unnecessary truncation as an optimization. + return Ok(bx.context.new_bitcast(None, result, v_type)); } // since gcc doesn't have vector shuffle methods available in non-patched builds, fallback to // component-wise bitreverses if they're not available. @@ -358,8 +357,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_shuffle { // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. - let n: u64 = match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + let n: u64 = match *args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( || span_bug!(span, "could not evaluate shuffle index array length"), ) @@ -432,7 +431,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( m_len == v_len, InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } ); - match m_elem_ty.kind() { + match *m_elem_ty.kind() { ty::Int(_) => {} _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), } @@ -600,13 +599,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Unsupported, } - let in_style = match in_elem.kind() { + let in_style = match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => Style::Int, ty::Float(_) => Style::Float, _ => Style::Unsupported, }; - let out_style = match out_elem.kind() { + let out_style = match *out_elem.kind() { ty::Int(_) | ty::Uint(_) => Style::Int, ty::Float(_) => Style::Float, _ => Style::Unsupported, @@ -633,7 +632,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( macro_rules! arith_binary { ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { $(if name == sym::$name { - match in_elem.kind() { + match *in_elem.kind() { $($(ty::$p(_))|* => { return Ok(bx.$call(args[0].immediate(), args[1].immediate())) })* @@ -671,7 +670,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let sign_shift = bx.context.new_rvalue_from_int(elem_type, elem_size as i32 - 1); let one = bx.context.new_rvalue_one(elem_type); - let mut shift = 0; for i in 0..in_len { let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); @@ -679,17 +677,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let masked = shifted & one; result = result | (bx.context.new_cast(None, masked, result_type) - << bx.context.new_rvalue_from_int(result_type, shift)); - shift += 1; + << bx.context.new_rvalue_from_int(result_type, i as i32)); } - match ret_ty.kind() { + match *ret_ty.kind() { ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => { // Zero-extend iN to the bitmask type: return Ok(result); } ty::Array(elem, len) - if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + if matches!(*elem.kind(), ty::Uint(ty::UintTy::U8)) && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all()) == Some(expected_bytes) => { @@ -728,7 +725,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Err(()); }}; } - let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { + let (elem_ty_str, elem_ty) = if let ty::Float(ref f) = *in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { 32 => ("f", elem_ty), @@ -979,7 +976,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // The element type of the third argument must be a signed integer type of any width: let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx()); - match element_ty2.kind() { + match *element_ty2.kind() { ty::Int(_) => (), _ => { require!( @@ -1095,7 +1092,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( assert_eq!(underlying_ty, non_ptr(element_ty0)); // The element type of the third argument must be a signed integer type of any width: - match element_ty2.kind() { + match *element_ty2.kind() { ty::Int(_) => (), _ => { require!( @@ -1153,7 +1150,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( macro_rules! arith_unary { ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { $(if name == sym::$name { - match in_elem.kind() { + match *in_elem.kind() { $($(ty::$p(_))|* => { return Ok(bx.$call(args[0].immediate())) })* @@ -1277,7 +1274,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); - return match in_elem.kind() { + return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(args[0].immediate(), $vec_op); if $ordered { @@ -1346,7 +1343,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); - return match in_elem.kind() { + return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { @@ -1375,7 +1372,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ); args[0].immediate() } else { - match in_elem.kind() { + match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, @@ -1389,7 +1386,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( args[0].immediate() }; - return match in_elem.kind() { + return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(input, $op); Ok(if !$boolean { diff --git a/src/lib.rs b/src/lib.rs index ce781b3f3ff..1132b0cd2f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![deny(clippy::pattern_type_mismatch)] +#![allow(clippy::needless_lifetimes)] extern crate rustc_apfloat; extern crate rustc_ast; @@ -84,7 +85,6 @@ use std::sync::Mutex; use back::lto::ThinBuffer; use back::lto::ThinData; use errors::LTONotSupported; -#[cfg(not(feature = "master"))] use gccjit::CType; use gccjit::{Context, OptimizationLevel}; #[cfg(feature = "master")] @@ -140,6 +140,10 @@ impl TargetInfo { fn supports_128bit_int(&self) -> bool { self.supports_128bit_integers.load(Ordering::SeqCst) } + + fn supports_target_dependent_type(&self, _typ: CType) -> bool { + false + } } #[derive(Clone)] @@ -161,6 +165,10 @@ impl LockedTargetInfo { fn supports_128bit_int(&self) -> bool { self.info.lock().expect("lock").supports_128bit_int() } + + fn supports_target_dependent_type(&self, typ: CType) -> bool { + self.info.lock().expect("lock").supports_target_dependent_type(typ) + } } #[derive(Clone)] @@ -446,7 +454,8 @@ impl WriteBackendMethods for GccCodegenBackend { pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { #[cfg(feature = "master")] let info = { - // Check whether the target supports 128-bit integers. + // 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()))) }; @@ -476,6 +485,7 @@ pub fn target_features( allow_unstable: bool, target_info: &LockedTargetInfo, ) -> Vec<Symbol> { + // TODO(antoyo): use global_gcc_features. sess.target .supported_target_features() .iter() @@ -486,8 +496,12 @@ pub fn target_features( None } }) - .filter(|_feature| { - target_info.cpu_supports(_feature) + .filter(|feature| { + // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. + if *feature == "neon" { + return false; + } + target_info.cpu_supports(feature) /* adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, diff --git a/src/type_.rs b/src/type_.rs index 4caff2e6310..e20234c5ce7 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -1,3 +1,8 @@ +#[cfg(feature = "master")] +use std::convert::TryInto; + +#[cfg(feature = "master")] +use gccjit::CType; use gccjit::{RValue, Struct, Type}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods}; @@ -142,25 +147,76 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn type_f16(&self) -> Type<'gcc> { - unimplemented!("f16_f128") + #[cfg(feature = "master")] + if self.supports_f16_type { + return self.context.new_c_type(CType::Float16); + } + bug!("unsupported float width 16") } fn type_f32(&self) -> Type<'gcc> { + #[cfg(feature = "master")] + if self.supports_f32_type { + return self.context.new_c_type(CType::Float32); + } self.float_type } fn type_f64(&self) -> Type<'gcc> { + #[cfg(feature = "master")] + if self.supports_f64_type { + return self.context.new_c_type(CType::Float64); + } self.double_type } fn type_f128(&self) -> Type<'gcc> { - unimplemented!("f16_f128") + #[cfg(feature = "master")] + if self.supports_f128_type { + return self.context.new_c_type(CType::Float128); + } + bug!("unsupported float width 128") } fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { self.context.new_function_pointer_type(None, return_type, params, false) } + #[cfg(feature = "master")] + fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { + if self.is_int_type_or_bool(typ) { + TypeKind::Integer + } else if typ.get_pointee().is_some() { + TypeKind::Pointer + } else if typ.is_vector() { + TypeKind::Vector + } else if typ.dyncast_array().is_some() { + TypeKind::Array + } else if typ.is_struct().is_some() { + TypeKind::Struct + } else if typ.dyncast_function_ptr_type().is_some() { + TypeKind::Function + } else if typ.is_compatible_with(self.float_type) { + TypeKind::Float + } else if typ.is_compatible_with(self.double_type) { + TypeKind::Double + } else if typ.is_floating_point() { + match typ.get_size() { + 2 => TypeKind::Half, + 4 => TypeKind::Float, + 8 => TypeKind::Double, + 16 => TypeKind::FP128, + size => unreachable!("Floating-point type of size {}", size), + } + } else if typ == self.type_void() { + TypeKind::Void + } else { + // TODO(antoyo): support other types. + unimplemented!(); + } + } + + #[cfg(not(feature = "master"))] fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { if self.is_int_type_or_bool(typ) { TypeKind::Integer @@ -170,9 +226,19 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { TypeKind::Double } else if typ.is_vector() { TypeKind::Vector + } else if typ.get_pointee().is_some() { + TypeKind::Pointer + } else if typ.dyncast_array().is_some() { + TypeKind::Array + } else if typ.is_struct().is_some() { + TypeKind::Struct + } else if typ.dyncast_function_ptr_type().is_some() { + TypeKind::Function + } else if typ == self.type_void() { + TypeKind::Void } else { // TODO(antoyo): support other types. - TypeKind::Void + unimplemented!(); } } @@ -200,6 +266,16 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { unimplemented!(); } + #[cfg(feature = "master")] + fn float_width(&self, typ: Type<'gcc>) -> usize { + if typ.is_floating_point() { + (typ.get_size() * u8::BITS).try_into().unwrap() + } else { + panic!("Cannot get width of float type {:?}", typ); + } + } + + #[cfg(not(feature = "master"))] fn float_width(&self, typ: Type<'gcc>) -> usize { let f32 = self.context.new_type::<f32>(); let f64 = self.context.new_type::<f64>(); diff --git a/src/type_of.rs b/src/type_of.rs index 24eab8e9a1e..d85ed4f12ff 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( Abi::Uninhabited | Abi::Aggregate { .. } => {} } - let name = match layout.ty.kind() { + let name = match *layout.ty.kind() { // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | @@ -214,7 +214,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // to fn_ptr_backend_type handle the on-stack attribute. // TODO(antoyo): find a less hackish way to hande the on-stack attribute. ty::FnPtr(sig) => { - cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) + cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) } _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), }; |
