diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 4a779e22870f6..8565e152b6e1e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -322,16 +322,6 @@ fn codegen_float_intrinsic_call<'tcx>( ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { - sym::expf16 => return false, // has a fallback via f32 - sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), - sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), - sym::expf128 => ("expf128", 1, fx.tcx.types.f128, types::F128), - - sym::exp2f16 => return false, // has a fallback via f32 - sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), - sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), - sym::exp2f128 => ("exp2f128", 1, fx.tcx.types.f128, types::F128), - sym::sqrtf16 => return false, // has a fallback via f32 sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), @@ -347,21 +337,6 @@ fn codegen_float_intrinsic_call<'tcx>( sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), sym::powf128 => ("powf128", 2, fx.tcx.types.f128, types::F128), - sym::logf16 => return false, // has a fallback via f32 - sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), - sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), - sym::logf128 => ("logf128", 1, fx.tcx.types.f128, types::F128), - - sym::log2f16 => return false, // has a fallback via f32 - sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), - sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), - sym::log2f128 => ("log2f128", 1, fx.tcx.types.f128, types::F128), - - sym::log10f16 => return false, // has a fallback via f32 - sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), - sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), - sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128), - sym::fmaf16 => return false, // has a fallback via f32 sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), @@ -404,16 +379,6 @@ fn codegen_float_intrinsic_call<'tcx>( sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), sym::roundf128 => ("roundf128", 1, fx.tcx.types.f128, types::F128), - sym::sinf16 => return false, // has a fallback via f32 - sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), - sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), - sym::sinf128 => ("sinf128", 1, fx.tcx.types.f128, types::F128), - - sym::cosf16 => return false, // has a fallback via f32 - sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), - sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), - sym::cosf128 => ("cosf128", 1, fx.tcx.types.f128, types::F128), - _ => return false, }; @@ -448,36 +413,16 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift operations // for `f16` and `f128` once the lowerings have been implemented in Cranelift. - let res = match intrinsic { + let val = match intrinsic { sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { - CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) - } - sym::copysignf32 | sym::copysignf64 => { - CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) - } - sym::floorf32 - | sym::floorf64 - | sym::ceilf32 - | sym::ceilf64 - | sym::truncf32 - | sym::truncf64 - | sym::round_ties_even_f32 - | sym::round_ties_even_f64 - | sym::sqrtf32 - | sym::sqrtf64 => { - let val = match intrinsic { - sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), - sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), - sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::round_ties_even_f32 | sym::round_ties_even_f64 => { - fx.bcx.ins().nearest(args[0]) - } - sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), - _ => unreachable!(), - }; - - CValue::by_val(val, layout) + fx.bcx.ins().fma(args[0], args[1], args[2]) } + sym::copysignf32 | sym::copysignf64 => fx.bcx.ins().fcopysign(args[0], args[1]), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => fx.bcx.ins().nearest(args[0]), + sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. @@ -492,20 +437,19 @@ fn codegen_float_intrinsic_call<'tcx>( let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)]; let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - let ret_val = if intrinsic == sym::powif16 { + if intrinsic == sym::powif16 { codegen_f16_f128::f32_to_f16(fx, ret_val) } else { ret_val - }; - CValue::by_val(ret_val, fx.layout_of(ty)) + } } _ => { let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); - let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - CValue::by_val(ret_val, fx.layout_of(ty)) + fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0] } }; + let res = CValue::by_val(val, layout); ret.write_cvalue(fx, res); true @@ -1199,7 +1143,14 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } - sym::fabs => { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log2 + | sym::log10 + | sym::sin + | sym::cos => { intrinsic_args!(fx, args => (arg); intrinsic); let layout = arg.layout(); let ty::Float(float_ty) = layout.ty.kind() else { @@ -1209,13 +1160,61 @@ fn codegen_regular_intrinsic_call<'tcx>( layout.ty ); }; + enum IntrinsicFallback { + Fallback(&'static str), + Codegen(Value), + } + use FloatTy::*; + use IntrinsicFallback::*; let x = arg.load_scalar(fx); - let val = match float_ty { - FloatTy::F32 | FloatTy::F64 => fx.bcx.ins().fabs(x), + let res = match (intrinsic, float_ty) { + (sym::fabs, F32 | F64) => Codegen(fx.bcx.ins().fabs(x)), // FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift // backend lowerings are implemented. - FloatTy::F16 => codegen_f16_f128::abs_f16(fx, x), - FloatTy::F128 => codegen_f16_f128::abs_f128(fx, x), + (sym::fabs, F16) => Codegen(codegen_f16_f128::abs_f16(fx, x)), + (sym::fabs, F128) => Codegen(codegen_f16_f128::abs_f128(fx, x)), + + (sym::exp, F32) => Fallback("expf"), + (sym::exp, F64) => Fallback("exp"), + (sym::exp, F128) => Fallback("expf128"), + + (sym::exp2, F32) => Fallback("exp2f"), + (sym::exp2, F64) => Fallback("exp2"), + (sym::exp2, F128) => Fallback("exp2f128"), + + (sym::log, F32) => Fallback("logf"), + (sym::log, F64) => Fallback("log"), + (sym::log, F128) => Fallback("logf128"), + + (sym::log2, F32) => Fallback("log2f"), + (sym::log2, F64) => Fallback("log2"), + (sym::log2, F128) => Fallback("log2f128"), + + (sym::log10, F32) => Fallback("log10f"), + (sym::log10, F64) => Fallback("log10"), + (sym::log10, F128) => Fallback("log10f128"), + + (sym::sin, F32) => Fallback("sinf"), + (sym::sin, F64) => Fallback("sin"), + (sym::sin, F128) => Fallback("sinf128"), + + (sym::cos, F32) => Fallback("cosf"), + (sym::cos, F64) => Fallback("cos"), + (sym::cos, F128) => Fallback("cosf128"), + + (_, F16) => { + // We implement fallbacks for other f16 intrinsics via f32 + return Err(Instance::new_raw(instance.def_id(), instance.args)); + } + + _ => unreachable!(), + }; + let val = match res { + Codegen(val) => val, + Fallback(name) => { + let ty = fx.clif_type(layout.ty).unwrap(); + fx.lib_call(name, vec![AbiParam::new(ty)], vec![AbiParam::new(ty)], &[x])[0] + } }; let val = CValue::by_val(val, layout); ret.write_cvalue(fx, val); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 09ad3254e5714..189ca948bf7b4 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -62,22 +62,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::sqrtf64 => "sqrt", sym::powif32 => "__builtin_powif", sym::powif64 => "__builtin_powi", - sym::sinf32 => "sinf", - sym::sinf64 => "sin", - sym::cosf32 => "cosf", - sym::cosf64 => "cos", sym::powf32 => "powf", sym::powf64 => "pow", - sym::expf32 => "expf", - sym::expf64 => "exp", - sym::exp2f32 => "exp2f", - sym::exp2f64 => "exp2", - sym::logf32 => "logf", - sym::logf64 => "log", - sym::log10f32 => "log10f", - sym::log10f64 => "log10", - sym::log2f32 => "log2f", - sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation @@ -117,16 +103,18 @@ fn get_simple_function_f128<'gcc, 'tcx>( let f128_type = cx.type_f128(); let func_name = match name { sym::ceilf128 => "ceilf128", + sym::cos => "cosf128", sym::fabs => "fabsf128", - sym::expf128 => "expf128", - sym::exp2f128 => "exp2f128", + sym::exp => "expf128", + sym::exp2 => "exp2f128", sym::floorf128 => "floorf128", - sym::logf128 => "logf128", - sym::log2f128 => "log2f128", - sym::log10f128 => "log10f128", + sym::log => "logf128", + sym::log2 => "log2f128", + sym::log10 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", + sym::sin => "sinf128", sym::sqrtf128 => "sqrtf128", _ => span_bug!(span, "used get_simple_function_f128 for non-unary f128 intrinsic"), }; @@ -140,24 +128,6 @@ fn get_simple_function_f128<'gcc, 'tcx>( ) } -fn generic_f16_builtin<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - name: Symbol, - args: &[OperandRef<'tcx, RValue<'gcc>>], -) -> RValue<'gcc> { - let f32_type = cx.type_f32(); - let builtin_name = match name { - sym::fabs => "fabsf", - _ => unreachable!(), - }; - - let func = cx.context.get_builtin_function(builtin_name); - let args: Vec<_> = - args.iter().map(|arg| cx.context.new_cast(None, arg.immediate(), f32_type)).collect(); - let result = cx.context.new_call(None, func, &args); - cx.context.new_cast(None, result, cx.type_f16()) -} - fn f16_builtin<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, name: Symbol, @@ -167,17 +137,19 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", - sym::expf16 => "expf", - sym::exp2f16 => "exp2f", + sym::cos => "cosf", + sym::exp => "expf", + sym::exp2 => "exp2f", sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", - sym::logf16 => "logf", - sym::log2f16 => "log2f", - sym::log10f16 => "log10f", + sym::log => "logf", + sym::log2 => "log2f", + sym::log10 => "log10f", sym::powf16 => "__builtin_powf", sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", + sym::sin => "sinf", sym::sqrtf16 => "__builtin_sqrtf", sym::truncf16 => "__builtin_truncf", _ => unreachable!(), @@ -246,13 +218,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 - | sym::expf16 - | sym::exp2f16 | sym::floorf16 | sym::fmaf16 - | sym::logf16 - | sym::log2f16 - | sym::log10f16 | sym::powf16 | sym::roundf16 | sym::round_ties_even_f16 @@ -264,11 +231,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 - | sym::expf128 - | sym::exp2f128 - | sym::logf128 - | sym::log2f128 - | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); @@ -452,16 +414,55 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } } } - sym::fabs => 'fabs: { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log10 + | sym::log2 + | sym::sin + | sym::cos => 'float_unop: { let ty = args[0].layout.ty; let ty::Float(float_ty) = *ty.kind() else { span_bug!(span, "expected float type for fabs intrinsic: {:?}", ty); }; - let func = match float_ty { - ty::FloatTy::F16 => break 'fabs generic_f16_builtin(self, name, args), - ty::FloatTy::F32 => self.context.get_builtin_function("fabsf"), - ty::FloatTy::F64 => self.context.get_builtin_function("fabs"), - ty::FloatTy::F128 => get_simple_function_f128(span, self, name), + use ty::FloatTy::*; + let func = match (name, float_ty) { + (sym::fabs, F32) => self.context.get_builtin_function("fabsf"), + (sym::fabs, F64) => self.context.get_builtin_function("fabs"), + + (sym::exp, F32) => self.context.get_builtin_function("expf"), + (sym::exp, F64) => self.context.get_builtin_function("exp"), + + (sym::exp2, F32) => self.context.get_builtin_function("exp2f"), + (sym::exp2, F64) => self.context.get_builtin_function("exp2"), + + (sym::log, F32) => self.context.get_builtin_function("logf"), + (sym::log, F64) => self.context.get_builtin_function("log"), + + (sym::log10, F32) => self.context.get_builtin_function("log10f"), + (sym::log10, F64) => self.context.get_builtin_function("log10"), + + (sym::log2, F32) => self.context.get_builtin_function("log2f"), + (sym::log2, F64) => self.context.get_builtin_function("log2"), + + (sym::sin, F32) => self.context.get_builtin_function("sinf"), + (sym::sin, F64) => self.context.get_builtin_function("sin"), + + (sym::cos, F32) => self.context.get_builtin_function("cosf"), + (sym::cos, F64) => self.context.get_builtin_function("cos"), + + (_, F32 | F64) => unreachable!(), + + (_, F16) => break 'float_unop f16_builtin(self, name, args), + (_, F128) => { + if !self.cx.supports_f128_type { + // Fall back to default body + let fallback = Instance::new_raw(instance.def_id(), instance.args); + return IntrinsicResult::Fallback(fallback); + } + get_simple_function_f128(span, self, name) + } }; self.cx.context.new_call( self.location, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index ba11ef29fb536..0011e33feffe9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -66,46 +66,11 @@ fn call_simple_intrinsic<'ll, 'tcx>( sym::powif64 => ("llvm.powi", &[bx.type_f64(), bx.type_i32()]), sym::powif128 => ("llvm.powi", &[bx.type_f128(), bx.type_i32()]), - sym::sinf16 => ("llvm.sin", &[bx.type_f16()]), - sym::sinf32 => ("llvm.sin", &[bx.type_f32()]), - sym::sinf64 => ("llvm.sin", &[bx.type_f64()]), - sym::sinf128 => ("llvm.sin", &[bx.type_f128()]), - - sym::cosf16 => ("llvm.cos", &[bx.type_f16()]), - sym::cosf32 => ("llvm.cos", &[bx.type_f32()]), - sym::cosf64 => ("llvm.cos", &[bx.type_f64()]), - sym::cosf128 => ("llvm.cos", &[bx.type_f128()]), - sym::powf16 => ("llvm.pow", &[bx.type_f16()]), sym::powf32 => ("llvm.pow", &[bx.type_f32()]), sym::powf64 => ("llvm.pow", &[bx.type_f64()]), sym::powf128 => ("llvm.pow", &[bx.type_f128()]), - sym::expf16 => ("llvm.exp", &[bx.type_f16()]), - sym::expf32 => ("llvm.exp", &[bx.type_f32()]), - sym::expf64 => ("llvm.exp", &[bx.type_f64()]), - sym::expf128 => ("llvm.exp", &[bx.type_f128()]), - - sym::exp2f16 => ("llvm.exp2", &[bx.type_f16()]), - sym::exp2f32 => ("llvm.exp2", &[bx.type_f32()]), - sym::exp2f64 => ("llvm.exp2", &[bx.type_f64()]), - sym::exp2f128 => ("llvm.exp2", &[bx.type_f128()]), - - sym::logf16 => ("llvm.log", &[bx.type_f16()]), - sym::logf32 => ("llvm.log", &[bx.type_f32()]), - sym::logf64 => ("llvm.log", &[bx.type_f64()]), - sym::logf128 => ("llvm.log", &[bx.type_f128()]), - - sym::log10f16 => ("llvm.log10", &[bx.type_f16()]), - sym::log10f32 => ("llvm.log10", &[bx.type_f32()]), - sym::log10f64 => ("llvm.log10", &[bx.type_f64()]), - sym::log10f128 => ("llvm.log10", &[bx.type_f128()]), - - sym::log2f16 => ("llvm.log2", &[bx.type_f16()]), - sym::log2f32 => ("llvm.log2", &[bx.type_f32()]), - sym::log2f64 => ("llvm.log2", &[bx.type_f64()]), - sym::log2f128 => ("llvm.log2", &[bx.type_f128()]), - sym::fmaf16 => ("llvm.fma", &[bx.type_f16()]), sym::fmaf32 => ("llvm.fma", &[bx.type_f32()]), sym::fmaf64 => ("llvm.fma", &[bx.type_f64()]), @@ -191,6 +156,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let simple = call_simple_intrinsic(self, name, args); let llval = match name { _ if simple.is_some() => simple.unwrap(), + // Need at least LLVM 22 for `min/maximumnum` to not crash LLVM. sym::minimum_number_nsz_f16 | sym::minimum_number_nsz_f32 | sym::minimum_number_nsz_f64 @@ -199,7 +165,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | sym::maximum_number_nsz_f32 | sym::maximum_number_nsz_f64 | sym::maximum_number_nsz_f128 - // Need at least LLVM 22 for `min/maximumnum` to not crash LLVM. if llvm_version >= (22, 0, 0) => { let intrinsic_name = if name.as_str().starts_with("min") { @@ -268,10 +233,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let ptr = select(self, true_val.llval, false_val.llval); let selected = OperandValue::Ref(PlaceValue::new_sized(ptr, true_val.align)); - let result = PlaceRef { - val: result_place.unwrap(), - layout: result_layout, - }; + let result = PlaceRef { val: result_place.unwrap(), layout: result_layout }; selected.store(self, result); return IntrinsicResult::WroteIntoPlace; } @@ -281,18 +243,18 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let false_val = args[2].immediate_or_packed_pair(self); select(self, true_val, false_val) } - (OperandValue::ZeroSized, OperandValue::ZeroSized) => return IntrinsicResult::Operand(OperandValue::ZeroSized), + (OperandValue::ZeroSized, OperandValue::ZeroSized) => { + return IntrinsicResult::Operand(OperandValue::ZeroSized); + } _ => span_bug!(span, "Incompatible OperandValue for select_unpredictable"), } } - sym::catch_unwind => { - catch_unwind_intrinsic( - self, - args[0].immediate(), - args[1].immediate(), - args[2].immediate(), - ) - } + sym::catch_unwind => catch_unwind_intrinsic( + self, + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + ), sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[], &[]), sym::va_arg => { let target = &self.cx.tcx.sess.target; @@ -369,10 +331,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // use an LLVM integer type of the correct width and let it split it however. let llty = self.type_ix(result_layout.size.bits()); let temp = if let Some(result_place) = result_place { - PlaceRef { - val: result_place, - layout: result_layout, - } + PlaceRef { val: result_place, layout: result_layout } } else { PlaceRef::alloca(self, result_layout) }; @@ -541,13 +500,35 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } - sym::fabs => { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log10 + | sym::log2 + | sym::sin + | sym::cos => { let ty = args[0].layout.ty; let ty::Float(f) = ty.kind() else { - span_bug!(span, "the `fabs` intrinsic requires a floating-point argument, got {:?}", ty); + span_bug!( + span, + "the `{}` intrinsic requires a floating-point argument, got {:?}", + name, + ty + ); }; let llty = self.type_float_from_ty(*f); - let llvm_name = "llvm.fabs"; + let llvm_name = match name { + sym::fabs => "llvm.fabs", + sym::exp => "llvm.exp", + sym::exp2 => "llvm.exp2", + sym::log => "llvm.log", + sym::log10 => "llvm.log10", + sym::log2 => "llvm.log2", + sym::sin => "llvm.sin", + sym::cos => "llvm.cos", + _ => bug!(), + }; self.call_intrinsic( llvm_name, &[llty], @@ -606,10 +587,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::black_box => { - let result = PlaceRef { - val: result_place.unwrap(), - layout: result_layout, - }; + let result = PlaceRef { val: result_place.unwrap(), layout: result_layout }; args[0].val.store(self, result); let result_val_span = [result.val.llval]; // We need to "use" the argument in some way LLVM can't introspect, and on @@ -867,8 +845,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::return_address => { match self.sess().target.arch { // Expand this list as needed - | Arch::Wasm32 - | Arch::Wasm64 => { + Arch::Wasm32 | Arch::Wasm64 => { let ty = self.type_ptr(); self.const_null(ty) } @@ -876,11 +853,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let ty = self.type_ix(32); let val = self.const_int(ty, 0); - let type_params: &[&'ll Type] = if llvm_version < (23, 0, 0) { - &[] - } else { - &[self.type_ptr()] - }; + let type_params: &[&'ll Type] = + if llvm_version < (23, 0, 0) { &[] } else { &[self.type_ptr()] }; self.call_intrinsic("llvm.returnaddress", type_params, &[val]) } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 552a91ffee071..dc70e91b5e899 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -335,14 +335,14 @@ impl CodegenBackend for LlvmCodegenBackend { sym::carrying_mul_add, // Fallback via libm, but the LLVM intrinsic is used instead. - sym::sinf16, sym::sinf32, sym::sinf64, - sym::cosf16, sym::cosf32, sym::cosf64, + sym::sin, + sym::cos, sym::powf16, sym::powf32, sym::powf64, - sym::expf16, sym::expf32, sym::expf64, - sym::exp2f16, sym::exp2f32, sym::exp2f64, - sym::logf16, sym::logf32, sym::logf64, - sym::log10f16, sym::log10f32, sym::log10f64, - sym::log2f16, sym::log2f32, sym::log2f64, + sym::exp, + sym::exp2, + sym::log, + sym::log10, + sym::log2, // Fallback via f32 or f64, but the LLVM intrinsic is used instead. sym::floorf16, sym::ceilf16, sym::truncf16, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index ddd91fe6976ba..383cf441ed45c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -95,22 +95,13 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::copysignf32 | sym::copysignf64 | sym::copysignf128 - | sym::cosf16 - | sym::cosf32 - | sym::cosf64 - | sym::cosf128 + | sym::cos | sym::ctlz | sym::ctpop | sym::cttz | sym::discriminant_value - | sym::exp2f16 - | sym::exp2f32 - | sym::exp2f64 - | sym::exp2f128 - | sym::expf16 - | sym::expf32 - | sym::expf64 - | sym::expf128 + | sym::exp + | sym::exp2 | sym::fabs | sym::fadd_algebraic | sym::fdiv_algebraic @@ -136,18 +127,9 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::fsub_algebraic | sym::gpu_launch_sized_workgroup_mem | sym::is_val_statically_known - | sym::log2f16 - | sym::log2f32 - | sym::log2f64 - | sym::log2f128 - | sym::log10f16 - | sym::log10f32 - | sym::log10f64 - | sym::log10f128 - | sym::logf16 - | sym::logf32 - | sym::logf64 - | sym::logf128 + | sym::log + | sym::log2 + | sym::log10 | sym::maximum_number_nsz_f16 | sym::maximum_number_nsz_f32 | sym::maximum_number_nsz_f64 @@ -200,10 +182,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::saturating_add | sym::saturating_sub | sym::select_unpredictable - | sym::sinf16 - | sym::sinf32 - | sym::sinf64 - | sym::sinf128 + | sym::sin | sym::size_of | sym::size_of_type_id | sym::sqrtf16 @@ -432,46 +411,11 @@ pub(crate) fn check_intrinsic_type( sym::powif64 => (0, 0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), sym::powif128 => (0, 0, vec![tcx.types.f128, tcx.types.i32], tcx.types.f128), - sym::sinf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::sinf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::sinf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::sinf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::cosf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::cosf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::cosf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::cosf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::powf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::powf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::powf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::powf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), - sym::expf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::expf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::expf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::expf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::exp2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::exp2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::exp2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::exp2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::logf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::logf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::logf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::logf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::log10f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::log10f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::log10f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::log10f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::log2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::log2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::log2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::log2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::fmaf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::fmaf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::fmaf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), @@ -486,7 +430,14 @@ pub(crate) fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } - sym::fabs => (1, 0, vec![param(0)], param(0)), + sym::exp + | sym::exp2 + | sym::log + | sym::log2 + | sym::log10 + | sym::fabs + | sym::sin + | sym::cos => (1, 0, vec![param(0)], param(0)), sym::minimum_number_nsz_f16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::minimum_number_nsz_f32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a07cd26f0cbc5..9df1b8017407b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -736,10 +736,7 @@ symbols! { coroutine_state, coroutine_yield, coroutines, - cosf16, - cosf32, - cosf64, - cosf128, + cos, count, covariant_unsafe_cell, coverage, @@ -907,18 +904,12 @@ symbols! { exhaustive_integer_patterns, exhaustive_patterns, existential_type, - exp2f16, - exp2f32, - exp2f64, - exp2f128, + exp, + exp2, expand1, expand2, expect, expected, - expf16, - expf32, - expf64, - expf128, explicit_extern_abis, explicit_generic_args_with_impl_trait, explicit_tail_calls, @@ -1221,19 +1212,10 @@ symbols! { loaded_from_disk, local, local_inner_macros, - log2f16, - log2f32, - log2f64, - log2f128, - log10f16, - log10f32, - log10f64, - log10f128, + log, + log2, + log10, log_syntax, - logf16, - logf32, - logf64, - logf128, loongarch32, loongarch64, loongarch_target_feature, @@ -2000,11 +1982,8 @@ symbols! { simd_trunc, simd_with_exposed_provenance, simd_xor, + sin, since, - sinf16, - sinf32, - sinf64, - sinf128, size, size_of, size_of_type_id, diff --git a/library/core/src/intrinsics/macros.rs b/library/core/src/intrinsics/macros.rs new file mode 100644 index 0000000000000..5abad0e2c9726 --- /dev/null +++ b/library/core/src/intrinsics/macros.rs @@ -0,0 +1,74 @@ +//! Macros used to declare intrinsics. + +/// Declares an intrinsic that is generic over its type, but whose fallback body has to be +/// written per-type. This is needed for the float intrinsics, which are generics but may +/// have different fallback bodies for each float width. +/// +/// ```ignore (illustrative) +/// intrinsic_dispatch_on_type! { +/// /// Returns the exponential of a float. +/// #[rustc_nounwind] +/// #[rustc_intrinsic] +/// pub fn expf(x: T) -> T; +/// +/// f16 => { expf(x as f32) as f16 } +/// f32 => { libm::likely_available::expf(x) } +/// f64 => { libm::likely_available::exp(x) } +/// f128 => { libm::maybe_available::expf128(x) } +/// } +/// ``` +macro_rules! intrinsic_dispatch_on_type { + ( + $(#[$attr:meta])* + $vis:vis fn $name:ident<$generic:ident: $bound:path>( + $($arg:ident: $arg_ty:ty),* $(,)? + ) -> $ret_ty:ty; + $($concrete:ty => $body:block)* + ) => { + mod $name { + use super::*; + + pub trait Dispatch<$generic = Self>: $bound { + fn dispatch($($arg: $arg_ty),*) -> $ret_ty; + } + + intrinsic_dispatch_on_type! { + @impls $generic, ($($arg: $arg_ty),*) -> $ret_ty, + $($concrete => $body)* + } + } + + $(#[$attr])* + $vis fn $name<$generic: $name::Dispatch>($($arg: $arg_ty),*) -> $ret_ty { + <$generic as $name::Dispatch>::dispatch($($arg),*) + } + }; + + ( + @impls $generic:ident, $args:tt -> $ret_ty:ty, + $($concrete:ty => $body:block)* + ) => { + $(intrinsic_dispatch_on_type! { @impl $generic = $concrete, $args -> $ret_ty $body })* + }; + + ( + @impl $generic:ident = $concrete:ty, + ($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty $body:block + ) => { + // We need a const block here to define a type alias for the type var ($generic), + // because the arguments in `fn dispatch` are the ones used to define the intrinsic. + // + // For instance, when defining `fn exp(x: T) -> T`, + // the definition of `dispatch` below is going to be `fn dispatch(x: T) -> T`. + const _: () = { + type $generic = $concrete; + + impl Dispatch<$concrete> for $concrete { + #[inline] + fn dispatch($($arg: $arg_ty),*) -> $ret_ty $body + } + }; + }; +} + +pub(super) use intrinsic_dispatch_on_type; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 24b270bf9ef03..5489a37d66dbe 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -61,9 +61,12 @@ use crate::{mem, ptr}; mod bounds; pub mod fallback; pub mod gpu; +mod macros; pub mod mir; pub mod simd; +use macros::intrinsic_dispatch_on_type; + // These imports are used for simplifying intra-doc links #[allow(unused_imports)] #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] @@ -1110,92 +1113,46 @@ pub fn powif64(a: f64, x: i32) -> f64; #[rustc_nounwind] pub fn powif128(a: f128, x: i32) -> f128; -/// Returns the sine of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::sin`](../../std/primitive.f16.html#method.sin) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn sinf16(x: f16) -> f16 { - sinf32(x as f32) as f16 -} -/// Returns the sine of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::sin`](../../std/primitive.f32.html#method.sin) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn sinf32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => sinf64(x as f64) as f32, - _ => libm::likely_available::sinf(x), +intrinsic_dispatch_on_type! { + /// Returns the sine of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `sin` method. For example, [`f32::sin`](../../std/primitive.f32.html#method.sin). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn sin(x: T) -> T; + + f16 => { sin(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => sin(x as f64) as f32, + _ => libm::likely_available::sinf(x), + } } -} -/// Returns the sine of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::sin`](../../std/primitive.f64.html#method.sin) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn sinf64(x: f64) -> f64 { - libm::likely_available::sin(x) -} -/// Returns the sine of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::sin`](../../std/primitive.f128.html#method.sin) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn sinf128(x: f128) -> f128 { - libm::maybe_available::sinf128(x) -} - -/// Returns the cosine of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::cos`](../../std/primitive.f16.html#method.cos) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn cosf16(x: f16) -> f16 { - cosf32(x as f32) as f16 -} -/// Returns the cosine of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::cos`](../../std/primitive.f32.html#method.cos) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn cosf32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => cosf64(x as f64) as f32, - _ => libm::likely_available::cosf(x), + f64 => { libm::likely_available::sin(x) } + f128 => { libm::maybe_available::sinf128(x) } +} + +intrinsic_dispatch_on_type! { + /// Returns the cosine of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `cos` method. For example, [`f32::cos`](../../std/primitive.f32.html#method.cos). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn cos(x: T) -> T; + + f16 => { cos(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => cos(x as f64) as f32, + _ => libm::likely_available::cosf(x), + } } -} -/// Returns the cosine of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::cos`](../../std/primitive.f64.html#method.cos) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn cosf64(x: f64) -> f64 { - libm::likely_available::cos(x) -} -/// Returns the cosine of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::cos`](../../std/primitive.f128.html#method.cos) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn cosf128(x: f128) -> f128 { - libm::maybe_available::cosf128(x) + f64 => { libm::likely_available::cos(x) } + f128 => { libm::maybe_available::cosf128(x) } } /// Raises an `f16` to an `f16` power. @@ -1242,224 +1199,109 @@ pub fn powf128(a: f128, x: f128) -> f128 { libm::maybe_available::powf128(a, x) } -/// Returns the exponential of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::exp`](../../std/primitive.f16.html#method.exp) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn expf16(x: f16) -> f16 { - expf32(x as f32) as f16 -} -/// Returns the exponential of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::exp`](../../std/primitive.f32.html#method.exp) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn expf32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => expf64(x as f64) as f32, - _ => libm::likely_available::expf(x), +intrinsic_dispatch_on_type! { + /// Returns the exponential of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `exp` method. For example, [`f32::exp`](../../std/primitive.f32.html#method.exp). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn exp(x: T) -> T; + + f16 => { exp(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => exp(x as f64) as f32, + _ => libm::likely_available::expf(x), + } } -} -/// Returns the exponential of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::exp`](../../std/primitive.f64.html#method.exp) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn expf64(x: f64) -> f64 { - libm::likely_available::exp(x) -} -/// Returns the exponential of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::exp`](../../std/primitive.f128.html#method.exp) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn expf128(x: f128) -> f128 { - libm::maybe_available::expf128(x) -} - -/// Returns 2 raised to the power of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn exp2f16(x: f16) -> f16 { - exp2f32(x as f32) as f16 -} -/// Returns 2 raised to the power of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn exp2f32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => exp2f64(x as f64) as f32, - _ => libm::likely_available::exp2f(x), + f64 => { libm::likely_available::exp(x) } + f128 => { libm::maybe_available::expf128(x) } +} + +intrinsic_dispatch_on_type! { + /// Returns 2 raised to the power of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `exp2` method. For example, [`f32::exp2`](../../std/primitive.f32.html#method.exp2). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn exp2(x: T) -> T; + + f16 => { exp2(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => exp2(x as f64) as f32, + _ => libm::likely_available::exp2f(x), + } } -} -/// Returns 2 raised to the power of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn exp2f64(x: f64) -> f64 { - libm::likely_available::exp2(x) -} -/// Returns 2 raised to the power of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn exp2f128(x: f128) -> f128 { - libm::maybe_available::exp2f128(x) -} - -/// Returns the natural logarithm of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::ln`](../../std/primitive.f16.html#method.ln) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn logf16(x: f16) -> f16 { - logf32(x as f32) as f16 -} -/// Returns the natural logarithm of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::ln`](../../std/primitive.f32.html#method.ln) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn logf32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => logf64(x as f64) as f32, - _ => libm::likely_available::logf(x), + f64 => { libm::likely_available::exp2(x) } + f128 => { libm::maybe_available::exp2f128(x) } +} + +intrinsic_dispatch_on_type! { + /// Returns the natural logarithm of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `ln` method. For example, [`f32::ln`](../../std/primitive.f32.html#method.ln). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn log(x: T) -> T; + + f16 => { log(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => log(x as f64) as f32, + _ => libm::likely_available::logf(x), + } } -} -/// Returns the natural logarithm of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::ln`](../../std/primitive.f64.html#method.ln) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn logf64(x: f64) -> f64 { - libm::likely_available::log(x) -} -/// Returns the natural logarithm of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::ln`](../../std/primitive.f128.html#method.ln) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn logf128(x: f128) -> f128 { - libm::maybe_available::logf128(x) -} - -/// Returns the base 10 logarithm of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::log10`](../../std/primitive.f16.html#method.log10) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log10f16(x: f16) -> f16 { - log10f32(x as f32) as f16 -} -/// Returns the base 10 logarithm of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::log10`](../../std/primitive.f32.html#method.log10) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log10f32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => log10f64(x as f64) as f32, - _ => libm::likely_available::log10f(x), + f64 => { libm::likely_available::log(x) } + f128 => { libm::maybe_available::logf128(x) } +} + +intrinsic_dispatch_on_type! { + /// Returns the base 10 logarithm of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `log10` method. For example, [`f32::log10`](../../std/primitive.f32.html#method.log10). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn log10(x: T) -> T; + + f16 => { log10(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => log10(x as f64) as f32, + _ => libm::likely_available::log10f(x), + } } -} -/// Returns the base 10 logarithm of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::log10`](../../std/primitive.f64.html#method.log10) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log10f64(x: f64) -> f64 { - libm::likely_available::log10(x) -} -/// Returns the base 10 logarithm of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::log10`](../../std/primitive.f128.html#method.log10) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log10f128(x: f128) -> f128 { - libm::maybe_available::log10f128(x) -} - -/// Returns the base 2 logarithm of an `f16`. -/// -/// The stabilized version of this intrinsic is -/// [`f16::log2`](../../std/primitive.f16.html#method.log2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log2f16(x: f16) -> f16 { - log2f32(x as f32) as f16 -} -/// Returns the base 2 logarithm of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::log2`](../../std/primitive.f32.html#method.log2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log2f32(x: f32) -> f32 { - cfg_select! { - all(target_env = "msvc", target_arch = "x86") => log2f64(x as f64) as f32, - _ => libm::likely_available::log2f(x), + f64 => { libm::likely_available::log10(x) } + f128 => { libm::maybe_available::log10f128(x) } +} + +intrinsic_dispatch_on_type! { + /// Returns the base 2 logarithm of a floating-point value. + /// + /// The stabilized versions of this intrinsic are available on the float primitives via the + /// `log2` method. For example, [`f32::log2`](../../std/primitive.f32.html#method.log2). + #[rustc_nounwind] + #[inline] + #[rustc_intrinsic] + pub fn log2(x: T) -> T; + + f16 => { log2(x as f32) as f16 } + f32 => { + cfg_select! { + all(target_env = "msvc", target_arch = "x86") => log2(x as f64) as f32, + _ => libm::likely_available::log2f(x), + } } -} -/// Returns the base 2 logarithm of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::log2`](../../std/primitive.f64.html#method.log2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log2f64(x: f64) -> f64 { - libm::likely_available::log2(x) -} -/// Returns the base 2 logarithm of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::log2`](../../std/primitive.f128.html#method.log2) -#[inline] -#[rustc_intrinsic] -#[rustc_nounwind] -pub fn log2f128(x: f128) -> f128 { - libm::maybe_available::log2f128(x) + f64 => { libm::likely_available::log2(x) } + f128 => { libm::maybe_available::log2f128(x) } } /// Returns `a * b + c` without rounding the intermediate result for `f16` values. diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs index aaf9c1b54efb8..adc06358a5149 100644 --- a/library/std/src/num/f128.rs +++ b/library/std/src/num/f128.rs @@ -81,7 +81,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp(self) -> f128 { - intrinsics::expf128(self) + intrinsics::exp(self) } /// Returns `2^(self)`. @@ -110,7 +110,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp2(self) -> f128 { - intrinsics::exp2f128(self) + intrinsics::exp2(self) } /// Returns the natural logarithm of the number. @@ -153,7 +153,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln(self) -> f128 { - intrinsics::logf128(self) + intrinsics::log(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -239,7 +239,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log2(self) -> f128 { - intrinsics::log2f128(self) + intrinsics::log2(self) } /// Returns the base 10 logarithm of the number. @@ -280,7 +280,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log10(self) -> f128 { - intrinsics::log10f128(self) + intrinsics::log10(self) } /// Returns the cube root of a number. @@ -378,7 +378,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sin(self) -> f128 { - intrinsics::sinf128(self) + intrinsics::sin(self) } /// Computes the cosine of a number (in radians). @@ -406,7 +406,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cos(self) -> f128 { - intrinsics::cosf128(self) + intrinsics::cos(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs index 4a7493fb5a5ed..3b5354d62f131 100644 --- a/library/std/src/num/f16.rs +++ b/library/std/src/num/f16.rs @@ -81,7 +81,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp(self) -> f16 { - intrinsics::expf16(self) + intrinsics::exp(self) } /// Returns `2^(self)`. @@ -110,7 +110,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp2(self) -> f16 { - intrinsics::exp2f16(self) + intrinsics::exp2(self) } /// Returns the natural logarithm of the number. @@ -153,7 +153,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln(self) -> f16 { - intrinsics::logf16(self) + intrinsics::log(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -239,7 +239,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log2(self) -> f16 { - intrinsics::log2f16(self) + intrinsics::log2(self) } /// Returns the base 10 logarithm of the number. @@ -280,7 +280,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log10(self) -> f16 { - intrinsics::log10f16(self) + intrinsics::log10(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -344,7 +344,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sin(self) -> f16 { - intrinsics::sinf16(self) + intrinsics::sin(self) } /// Computes the cosine of a number (in radians). @@ -372,7 +372,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cos(self) -> f16 { - intrinsics::cosf16(self) + intrinsics::cos(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index 385533748cb5d..ac3f2e263195d 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -411,7 +411,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f32 { - intrinsics::expf32(self) + intrinsics::exp(self) } /// Returns `2^(self)`. @@ -436,7 +436,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f32 { - intrinsics::exp2f32(self) + intrinsics::exp2(self) } /// Returns the natural logarithm of the number. @@ -471,7 +471,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f32 { - intrinsics::logf32(self) + intrinsics::log(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -541,7 +541,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { - intrinsics::log2f32(self) + intrinsics::log2(self) } /// Returns the base 10 logarithm of the number. @@ -574,7 +574,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f32 { - intrinsics::log10f32(self) + intrinsics::log10(self) } /// The positive difference of two numbers. @@ -699,7 +699,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f32 { - intrinsics::sinf32(self) + intrinsics::sin(self) } /// Computes the cosine of a number (in radians). @@ -723,7 +723,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f32 { - intrinsics::cosf32(self) + intrinsics::cos(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index 66482a8b654a5..9b3086b1ce12e 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -411,7 +411,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f64 { - intrinsics::expf64(self) + intrinsics::exp(self) } /// Returns `2^(self)`. @@ -436,7 +436,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f64 { - intrinsics::exp2f64(self) + intrinsics::exp2(self) } /// Returns the natural logarithm of the number. @@ -471,7 +471,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f64 { - intrinsics::logf64(self) + intrinsics::log(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -541,7 +541,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { - intrinsics::log2f64(self) + intrinsics::log2(self) } /// Returns the base 10 logarithm of the number. @@ -574,7 +574,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f64 { - intrinsics::log10f64(self) + intrinsics::log10(self) } /// The positive difference of two numbers. @@ -699,7 +699,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f64 { - intrinsics::sinf64(self) + intrinsics::sin(self) } /// Computes the cosine of a number (in radians). @@ -723,7 +723,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f64 { - intrinsics::cosf64(self) + intrinsics::cos(self) } /// Computes the tangent of a number (in radians). diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index aaaf91f363abd..70f5008e57c34 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -223,7 +223,6 @@ generate! { eprint_macro, eprintln_macro, err, - exp, expect_err, expn_data, exported_private_dependencies, @@ -406,9 +405,6 @@ generate! { ln, lock, lock_api, - log, - log10, - log2, macro_concat, macro_use_imports, map_break, diff --git a/src/tools/miri/src/intrinsics/math.rs b/src/tools/miri/src/intrinsics/math.rs index ad3881b0e6a6d..637c8b089a9ea 100644 --- a/src/tools/miri/src/intrinsics/math.rs +++ b/src/tools/miri/src/intrinsics/math.rs @@ -17,18 +17,11 @@ fn sqrt<'tcx, F: Float + FloatConvert + Into>( } /// Determine which float operation on which type this is. -fn is_host_unary_float_op(intrinsic_name: &str) -> Option<(FloatTy, HostUnaryFloatOp)> { - let (op, ty) = intrinsic_name.rsplit_once('f')?; - - let float_ty = match ty { - "16" => FloatTy::F16, - "32" => FloatTy::F32, - "64" => FloatTy::F64, - "128" => FloatTy::F128, - _ => return None, - }; - - let host_float_op = match op { +fn is_host_unary_float_op( + intrinsic_name: &str, + generic_args: ty::GenericArgsRef<'_>, +) -> Option<(FloatTy, HostUnaryFloatOp)> { + let host_float_op = match intrinsic_name { "sin" => HostUnaryFloatOp::Sin, "cos" => HostUnaryFloatOp::Cos, "exp" => HostUnaryFloatOp::Exp, @@ -39,6 +32,9 @@ fn is_host_unary_float_op(intrinsic_name: &str) -> Option<(FloatTy, HostUnaryFlo _ => return None, }; + let ty::Float(float_ty) = *generic_args.type_at(0).kind() else { + bug!("`{intrinsic_name}` intrinsic called on non-float type"); + }; Some((float_ty, host_float_op)) } @@ -96,7 +92,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_math_intrinsic( &mut self, intrinsic_name: &str, - _generic_args: ty::GenericArgsRef<'tcx>, + generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx>], dest: &PlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -179,7 +175,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Operations that need host floats. - _ if let Some((float_ty, op)) = is_host_unary_float_op(intrinsic_name) => { + _ if let Some((float_ty, op)) = + is_host_unary_float_op(intrinsic_name, generic_args) => + { let [f] = check_intrinsic_arg_count(args)?; match float_ty { FloatTy::F16 => host_unary_float_op::(this, f, op, dest)?, diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs index 1cacc9dde86f8..bbee903252602 100644 --- a/src/tools/miri/src/math.rs +++ b/src/tools/miri/src/math.rs @@ -230,11 +230,11 @@ where } /// For the intrinsics: -/// - sinf32, sinf64, sinhf, sinh -/// - cosf32, cosf64, coshf, cosh +/// - sin, sinhf, sinh +/// - cos, coshf, cosh /// - tanhf, tanh, atanf, atan, atan2f, atan2 -/// - expf32, expf64, exp2f32, exp2f64 -/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64 +/// - exp, exp2 +/// - log, log2, log10 /// - powf32, powf64 /// - erff, erf, erfcf, erfc /// - hypotf, hypot diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout index c75cc7b2179d3..689453326c0b5 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout @@ -15,8 +15,8 @@ macro lifetime_hygiene /* 0#0 */ { - ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 - */>) => + ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 */>) + => { fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } } fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {} diff --git a/tests/ui/intrinsics/reify-intrinsic.rs b/tests/ui/intrinsics/reify-intrinsic.rs index 5b2324235c1a9..8d6f2ea93b723 100644 --- a/tests/ui/intrinsics/reify-intrinsic.rs +++ b/tests/ui/intrinsics/reify-intrinsic.rs @@ -15,7 +15,7 @@ fn b() { fn c() { let _: [unsafe fn(f32) -> f32; 2] = [ std::intrinsics::floorf32, //~ ERROR cannot coerce - std::intrinsics::log2f32, + std::intrinsics::log2, ]; } diff --git a/tests/ui/resolve/bad-env-capture.stderr b/tests/ui/resolve/bad-env-capture.stderr index a3a15ca245b2a..a8456ca33d46c 100644 --- a/tests/ui/resolve/bad-env-capture.stderr +++ b/tests/ui/resolve/bad-env-capture.stderr @@ -6,17 +6,22 @@ LL | fn bar() { log(debug, x); } | = help: use the `|| { ... }` closure form instead -error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture.rs:3:20 - | -LL | fn bar() { log(debug, x); } - | ^^^^^ not found in this scope - error[E0425]: cannot find function `log` in this scope --> $DIR/bad-env-capture.rs:3:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::log; + | + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture.rs:3:20 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/bad-env-capture2.stderr b/tests/ui/resolve/bad-env-capture2.stderr index 403fe2d32b980..4e8ebb621b671 100644 --- a/tests/ui/resolve/bad-env-capture2.stderr +++ b/tests/ui/resolve/bad-env-capture2.stderr @@ -6,17 +6,22 @@ LL | fn bar() { log(debug, x); } | = help: use the `|| { ... }` closure form instead -error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture2.rs:2:20 - | -LL | fn bar() { log(debug, x); } - | ^^^^^ not found in this scope - error[E0425]: cannot find function `log` in this scope --> $DIR/bad-env-capture2.rs:2:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::log; + | + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture2.rs:2:20 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/bad-env-capture3.stderr b/tests/ui/resolve/bad-env-capture3.stderr index 962eb72ee68bf..65c39ace65d96 100644 --- a/tests/ui/resolve/bad-env-capture3.stderr +++ b/tests/ui/resolve/bad-env-capture3.stderr @@ -6,17 +6,22 @@ LL | fn bar() { log(debug, x); } | = help: use the `|| { ... }` closure form instead -error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture3.rs:3:24 - | -LL | fn bar() { log(debug, x); } - | ^^^^^ not found in this scope - error[E0425]: cannot find function `log` in this scope --> $DIR/bad-env-capture3.rs:3:20 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::log; + | + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture3.rs:3:24 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/bad-expr-path.stderr b/tests/ui/resolve/bad-expr-path.stderr index 0392c1fa23993..be2e3a1e90350 100644 --- a/tests/ui/resolve/bad-expr-path.stderr +++ b/tests/ui/resolve/bad-expr-path.stderr @@ -1,3 +1,14 @@ +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-expr-path.rs:4:5 + | +LL | log(debug, m1::arguments); + | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::log; + | + error[E0425]: cannot find value `debug` in this scope --> $DIR/bad-expr-path.rs:4:9 | @@ -19,12 +30,6 @@ LL | fn main(arguments: Vec) { = note: expected signature `fn()` found signature `fn(Vec)` -error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-expr-path.rs:4:5 - | -LL | log(debug, m1::arguments); - | ^^^ not found in this scope - error: aborting due to 4 previous errors Some errors have detailed explanations: E0425, E0580. diff --git a/tests/ui/resolve/bad-expr-path2.stderr b/tests/ui/resolve/bad-expr-path2.stderr index dd62eb1c1a728..073af5b31089d 100644 --- a/tests/ui/resolve/bad-expr-path2.stderr +++ b/tests/ui/resolve/bad-expr-path2.stderr @@ -1,3 +1,14 @@ +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-expr-path2.rs:6:5 + | +LL | log(debug, m1::arguments); + | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::log; + | + error[E0425]: cannot find value `debug` in this scope --> $DIR/bad-expr-path2.rs:6:9 | @@ -21,12 +32,6 @@ LL | fn main(arguments: Vec) { = note: expected signature `fn()` found signature `fn(Vec)` -error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-expr-path2.rs:6:5 - | -LL | log(debug, m1::arguments); - | ^^^ not found in this scope - error: aborting due to 4 previous errors Some errors have detailed explanations: E0423, E0425, E0580.