|
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