|  | 
| 1 |  | -use std::borrow::Borrow; | 
|  | 1 | +use std::borrow::{Borrow, Cow}; | 
| 2 | 2 | use std::cell::{Cell, RefCell}; | 
| 3 | 3 | use std::ffi::{CStr, c_char, c_uint}; | 
| 4 | 4 | use std::marker::PhantomData; | 
| @@ -138,7 +138,7 @@ pub(crate) struct FullCx<'ll, 'tcx> { | 
| 138 | 138 |     pub rust_try_fn: Cell<Option<(&'ll Type, &'ll Value)>>, | 
| 139 | 139 | 
 | 
| 140 | 140 |     intrinsics: | 
| 141 |  | -        RefCell<FxHashMap<(&'static str, SmallVec<[&'ll Type; 2]>), (&'ll Type, &'ll Value)>>, | 
|  | 141 | +        RefCell<FxHashMap<(Cow<'static, str>, SmallVec<[&'ll Type; 2]>), (&'ll Type, &'ll Value)>>, | 
| 142 | 142 | 
 | 
| 143 | 143 |     /// A counter that is used for generating local symbol names | 
| 144 | 144 |     local_gen_sym_counter: Cell<usize>, | 
| @@ -845,201 +845,39 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { | 
| 845 | 845 | impl<'ll> CodegenCx<'ll, '_> { | 
| 846 | 846 |     pub(crate) fn get_intrinsic( | 
| 847 | 847 |         &self, | 
| 848 |  | -        base_name: &str, | 
|  | 848 | +        base_name: Cow<'static, str>, | 
| 849 | 849 |         type_params: &[&'ll Type], | 
| 850 | 850 |     ) -> (&'ll Type, &'ll Value) { | 
| 851 |  | -        if let Some(v) = | 
| 852 |  | -            self.intrinsics.borrow().get(&(base_name, SmallVec::from_slice(type_params))) | 
| 853 |  | -        { | 
| 854 |  | -            return *v; | 
| 855 |  | -        } | 
| 856 |  | - | 
| 857 |  | -        self.declare_intrinsic(base_name, type_params) | 
| 858 |  | -    } | 
| 859 |  | - | 
| 860 |  | -    fn insert_intrinsic( | 
| 861 |  | -        &self, | 
| 862 |  | -        base_name: &'static str, | 
| 863 |  | -        type_params: &[&'ll Type], | 
| 864 |  | -        args: Option<&[&'ll llvm::Type]>, | 
| 865 |  | -        ret: &'ll llvm::Type, | 
| 866 |  | -    ) -> (&'ll llvm::Type, &'ll llvm::Value) { | 
| 867 |  | -        let fn_ty = if let Some(args) = args { | 
| 868 |  | -            self.type_func(args, ret) | 
| 869 |  | -        } else { | 
| 870 |  | -            self.type_variadic_func(&[], ret) | 
| 871 |  | -        }; | 
| 872 |  | - | 
| 873 |  | -        let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes()) | 
| 874 |  | -            .expect("Unknown LLVM intrinsic `{base_name}`"); | 
| 875 |  | - | 
| 876 |  | -        let full_name = if intrinsic.is_overloaded() { | 
| 877 |  | -            &intrinsic.overloaded_name(self.llmod, type_params) | 
| 878 |  | -        } else { | 
| 879 |  | -            base_name | 
| 880 |  | -        }; | 
| 881 |  | - | 
| 882 |  | -        let f = self.declare_cfn(full_name, llvm::UnnamedAddr::No, fn_ty); | 
| 883 |  | -        self.intrinsics | 
|  | 851 | +        *self | 
|  | 852 | +            .intrinsics | 
| 884 | 853 |             .borrow_mut() | 
| 885 |  | -            .insert((base_name, SmallVec::from_slice(type_params)), (fn_ty, f)); | 
| 886 |  | -        (fn_ty, f) | 
|  | 854 | +            .entry((base_name, SmallVec::from_slice(type_params))) | 
|  | 855 | +            .or_insert_with_key(|(base_name, type_params)| { | 
|  | 856 | +                self.declare_intrinsic(base_name, type_params) | 
|  | 857 | +            }) | 
| 887 | 858 |     } | 
| 888 | 859 | 
 | 
| 889 | 860 |     fn declare_intrinsic( | 
| 890 | 861 |         &self, | 
| 891 | 862 |         base_name: &str, | 
| 892 | 863 |         type_params: &[&'ll Type], | 
| 893 | 864 |     ) -> (&'ll Type, &'ll Value) { | 
| 894 |  | -        macro_rules! param { | 
| 895 |  | -            ($index:literal) => { | 
| 896 |  | -                type_params[$index] | 
| 897 |  | -            }; | 
| 898 |  | -            ($other:expr) => { | 
| 899 |  | -                $other | 
| 900 |  | -            }; | 
| 901 |  | -        } | 
| 902 |  | -        macro_rules! ifn { | 
| 903 |  | -            ($name:expr, fn(...) -> $ret:expr) => ( | 
| 904 |  | -                if base_name == $name { | 
| 905 |  | -                    return self.insert_intrinsic($name, type_params, None, param!($ret)); | 
| 906 |  | -                } | 
| 907 |  | -            ); | 
| 908 |  | -            ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( | 
| 909 |  | -                if base_name == $name { | 
| 910 |  | -                    return self.insert_intrinsic($name, type_params, Some(&[$(param!($arg)),*]), param!($ret)); | 
| 911 |  | -                } | 
| 912 |  | -            ); | 
| 913 |  | -        } | 
| 914 |  | -        macro_rules! mk_struct { | 
| 915 |  | -            ($($field_ty:expr),*) => (self.type_struct( &[$(param!($field_ty)),*], false)) | 
| 916 |  | -        } | 
| 917 |  | - | 
| 918 |  | -        let same_width_vector = |index, element_ty| { | 
| 919 |  | -            self.type_vector(element_ty, self.vector_length(type_params[index]) as u64) | 
| 920 |  | -        }; | 
| 921 |  | - | 
| 922 |  | -        let ptr = self.type_ptr(); | 
| 923 |  | -        let void = self.type_void(); | 
| 924 |  | -        let i1 = self.type_i1(); | 
| 925 |  | -        let t_i32 = self.type_i32(); | 
| 926 |  | -        let t_i64 = self.type_i64(); | 
| 927 |  | -        let t_isize = self.type_isize(); | 
| 928 |  | -        let t_metadata = self.type_metadata(); | 
| 929 |  | -        let t_token = self.type_token(); | 
| 930 |  | - | 
| 931 |  | -        ifn!("llvm.wasm.get.exception", fn(t_token) -> ptr); | 
| 932 |  | -        ifn!("llvm.wasm.get.ehselector", fn(t_token) -> t_i32); | 
| 933 |  | - | 
| 934 |  | -        ifn!("llvm.wasm.trunc.unsigned", fn(1) -> 0); | 
| 935 |  | -        ifn!("llvm.wasm.trunc.signed", fn(1) -> 0); | 
| 936 |  | -        ifn!("llvm.fptosi.sat", fn(1) -> 0); | 
| 937 |  | -        ifn!("llvm.fptoui.sat", fn(1) -> 0); | 
| 938 |  | - | 
| 939 |  | -        ifn!("llvm.trap", fn() -> void); | 
| 940 |  | -        ifn!("llvm.debugtrap", fn() -> void); | 
| 941 |  | -        ifn!("llvm.frameaddress", fn(t_i32) -> ptr); | 
| 942 |  | - | 
| 943 |  | -        ifn!("llvm.powi", fn(0, 1) -> 0); | 
| 944 |  | -        ifn!("llvm.pow", fn(0, 0) -> 0); | 
| 945 |  | -        ifn!("llvm.sqrt", fn(0) -> 0); | 
| 946 |  | -        ifn!("llvm.sin", fn(0) -> 0); | 
| 947 |  | -        ifn!("llvm.cos", fn(0) -> 0); | 
| 948 |  | -        ifn!("llvm.exp", fn(0) -> 0); | 
| 949 |  | -        ifn!("llvm.exp2", fn(0) -> 0); | 
| 950 |  | -        ifn!("llvm.log", fn(0) -> 0); | 
| 951 |  | -        ifn!("llvm.log10", fn(0) -> 0); | 
| 952 |  | -        ifn!("llvm.log2", fn(0) -> 0); | 
| 953 |  | -        ifn!("llvm.fma", fn(0, 0, 0) -> 0); | 
| 954 |  | -        ifn!("llvm.fmuladd", fn(0, 0, 0) -> 0); | 
| 955 |  | -        ifn!("llvm.fabs", fn(0) -> 0); | 
| 956 |  | -        ifn!("llvm.minnum", fn(0, 0) -> 0); | 
| 957 |  | -        ifn!("llvm.minimum", fn(0, 0) -> 0); | 
| 958 |  | -        ifn!("llvm.maxnum", fn(0, 0) -> 0); | 
| 959 |  | -        ifn!("llvm.maximum", fn(0, 0) -> 0); | 
| 960 |  | -        ifn!("llvm.floor", fn(0) -> 0); | 
| 961 |  | -        ifn!("llvm.ceil", fn(0) -> 0); | 
| 962 |  | -        ifn!("llvm.trunc", fn(0) -> 0); | 
| 963 |  | -        ifn!("llvm.copysign", fn(0, 0) -> 0); | 
| 964 |  | -        ifn!("llvm.round", fn(0) -> 0); | 
| 965 |  | -        ifn!("llvm.rint", fn(0) -> 0); | 
| 966 |  | -        ifn!("llvm.nearbyint", fn(0) -> 0); | 
| 967 |  | - | 
| 968 |  | -        ifn!("llvm.ctpop", fn(0) -> 0); | 
| 969 |  | -        ifn!("llvm.ctlz", fn(0, i1) -> 0); | 
| 970 |  | -        ifn!("llvm.cttz", fn(0, i1) -> 0); | 
| 971 |  | -        ifn!("llvm.bswap", fn(0) -> 0); | 
| 972 |  | -        ifn!("llvm.bitreverse", fn(0) -> 0); | 
| 973 |  | -        ifn!("llvm.fshl", fn(0, 0, 0) -> 0); | 
| 974 |  | -        ifn!("llvm.fshr", fn(0, 0, 0) -> 0); | 
| 975 |  | - | 
| 976 |  | -        ifn!("llvm.sadd.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 977 |  | -        ifn!("llvm.uadd.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 978 |  | -        ifn!("llvm.ssub.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 979 |  | -        ifn!("llvm.usub.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 980 |  | -        ifn!("llvm.smul.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 981 |  | -        ifn!("llvm.umul.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); | 
| 982 |  | - | 
| 983 |  | -        ifn!("llvm.sadd.sat", fn(0, 0) -> 0); | 
| 984 |  | -        ifn!("llvm.uadd.sat", fn(0, 0) -> 0); | 
| 985 |  | -        ifn!("llvm.ssub.sat", fn(0, 0) -> 0); | 
| 986 |  | -        ifn!("llvm.usub.sat", fn(0, 0) -> 0); | 
| 987 |  | - | 
| 988 |  | -        ifn!("llvm.scmp", fn(1, 1) -> 0); | 
| 989 |  | -        ifn!("llvm.ucmp", fn(1, 1) -> 0); | 
| 990 |  | - | 
| 991 |  | -        ifn!("llvm.lifetime.start", fn(t_i64, 0) -> void); | 
| 992 |  | -        ifn!("llvm.lifetime.end", fn(t_i64, 0) -> void); | 
| 993 |  | - | 
| 994 |  | -        ifn!("llvm.is.constant", fn(0) -> i1); | 
| 995 |  | -        ifn!("llvm.expect", fn(0, 0) -> 0); | 
| 996 |  | - | 
| 997 |  | -        ifn!("llvm.eh.typeid.for", fn(0) -> t_i32); | 
| 998 |  | -        ifn!("llvm.localescape", fn(...) -> void); | 
| 999 |  | -        ifn!("llvm.localrecover", fn(ptr, ptr, t_i32) -> ptr); | 
| 1000 |  | - | 
| 1001 |  | -        ifn!("llvm.assume", fn(i1) -> void); | 
| 1002 |  | -        ifn!("llvm.prefetch", fn(0, t_i32, t_i32, t_i32) -> void); | 
| 1003 |  | - | 
| 1004 | 865 |         // This isn't an "LLVM intrinsic", but LLVM's optimization passes | 
| 1005 | 866 |         // recognize it like one (including turning it into `bcmp` sometimes) | 
| 1006 | 867 |         // and we use it to implement intrinsics like `raw_eq` and `compare_bytes` | 
| 1007 | 868 |         if base_name == "memcmp" { | 
| 1008 |  | -            let fn_ty = self.type_func(&[ptr, ptr, t_isize], self.type_int()); | 
|  | 869 | +            let fn_ty = self | 
|  | 870 | +                .type_func(&[self.type_ptr(), self.type_ptr(), self.type_isize()], self.type_int()); | 
| 1009 | 871 |             let f = self.declare_cfn("memcmp", llvm::UnnamedAddr::No, fn_ty); | 
| 1010 |  | -            self.intrinsics.borrow_mut().insert(("memcmp", SmallVec::new()), (fn_ty, f)); | 
| 1011 | 872 | 
 | 
| 1012 | 873 |             return (fn_ty, f); | 
| 1013 | 874 |         } | 
| 1014 | 875 | 
 | 
| 1015 |  | -        // variadic intrinsics | 
| 1016 |  | -        ifn!("llvm.va_start", fn(0) -> void); | 
| 1017 |  | -        ifn!("llvm.va_end", fn(0) -> void); | 
| 1018 |  | -        ifn!("llvm.va_copy", fn(0, 0) -> void); | 
| 1019 |  | - | 
| 1020 |  | -        if self.sess().instrument_coverage() { | 
| 1021 |  | -            ifn!("llvm.instrprof.increment", fn(ptr, t_i64, t_i32, t_i32) -> void); | 
| 1022 |  | -            ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void); | 
| 1023 |  | -            ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void); | 
| 1024 |  | -        } | 
| 1025 |  | - | 
| 1026 |  | -        ifn!("llvm.type.test", fn(ptr, t_metadata) -> i1); | 
| 1027 |  | -        ifn!("llvm.type.checked.load", fn(ptr, t_i32, t_metadata) -> mk_struct! {ptr, i1}); | 
| 1028 |  | - | 
| 1029 |  | -        if self.sess().opts.debuginfo != DebugInfo::None { | 
| 1030 |  | -            ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata, t_metadata) -> void); | 
| 1031 |  | -            ifn!("llvm.dbg.value", fn(t_metadata, t_metadata, t_metadata) -> void); | 
| 1032 |  | -        } | 
| 1033 |  | - | 
| 1034 |  | -        ifn!("llvm.ptrmask", fn(0, 1) -> 0); | 
| 1035 |  | -        ifn!("llvm.threadlocal.address", fn(ptr) -> ptr); | 
| 1036 |  | - | 
| 1037 |  | -        ifn!("llvm.masked.load", fn(1, t_i32, same_width_vector(0, i1), 0) -> 0); | 
| 1038 |  | -        ifn!("llvm.masked.store", fn(0, 1, t_i32, same_width_vector(0, i1)) -> void); | 
| 1039 |  | -        ifn!("llvm.masked.gather", fn(1, t_i32, same_width_vector(0, i1), 0) -> 0); | 
| 1040 |  | -        ifn!("llvm.masked.scatter", fn(0, 1, t_i32, same_width_vector(0, i1)) -> void); | 
|  | 876 | +        let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes()) | 
|  | 877 | +            .unwrap_or_else(|| bug!("Unknown intrinsic: `{base_name}`")); | 
|  | 878 | +        let f = intrinsic.get_declaration(self.llmod, &type_params); | 
| 1041 | 879 | 
 | 
| 1042 |  | -        bug!("Unknown intrinsic: `{base_name}`") | 
|  | 880 | +        (self.get_type_of_global(f), f) | 
| 1043 | 881 |     } | 
| 1044 | 882 | 
 | 
| 1045 | 883 |     pub(crate) fn eh_catch_typeinfo(&self) -> &'ll Value { | 
|  | 
0 commit comments