about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm/mod.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs45
1 files changed, 44 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index ed23f911930..bc3538c768d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -1,9 +1,10 @@
 #![allow(non_snake_case)]
 
 use std::ffi::{CStr, CString};
-use std::ptr;
+use std::num::NonZero;
 use std::str::FromStr;
 use std::string::FromUtf8Error;
+use std::{ptr, slice};
 
 use libc::c_uint;
 use rustc_abi::{Align, Size, WrappingRange};
@@ -327,6 +328,48 @@ pub(crate) fn get_value_name(value: &Value) -> &[u8] {
     }
 }
 
+#[derive(Debug, Copy, Clone)]
+pub(crate) struct Intrinsic {
+    id: NonZero<c_uint>,
+}
+
+impl Intrinsic {
+    pub(crate) fn lookup(name: &[u8]) -> Option<Self> {
+        let id = unsafe { LLVMLookupIntrinsicID(name.as_c_char_ptr(), name.len()) };
+        NonZero::new(id).map(|id| Self { id })
+    }
+
+    pub(crate) fn is_overloaded(self) -> bool {
+        unsafe { LLVMIntrinsicIsOverloaded(self.id) == True }
+    }
+
+    pub(crate) fn overloaded_name<'ll>(
+        self,
+        llmod: &'ll Module,
+        type_params: &[&'ll Type],
+    ) -> String {
+        let mut len = 0;
+        let ptr = unsafe {
+            LLVMIntrinsicCopyOverloadedName2(
+                llmod,
+                self.id,
+                type_params.as_ptr(),
+                type_params.len(),
+                &mut len,
+            )
+        };
+
+        let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), len) };
+        let copied = str::from_utf8(slice).expect("Non-UTF8 intrinsic name").to_string();
+
+        unsafe {
+            libc::free(ptr.cast());
+        }
+
+        copied
+    }
+}
+
 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
 pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
     unsafe {