diff options
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/mod.rs | 45 |
2 files changed, 56 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index e27fbf94f34..59c61db5fcd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -15,6 +15,7 @@ use std::fmt::Debug; use std::marker::PhantomData; +use std::num::NonZero; use std::ptr; use bitflags::bitflags; @@ -1195,6 +1196,17 @@ unsafe extern "C" { // Operations on functions pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); + // Operations about llvm intrinsics + pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint; + pub(crate) fn LLVMIntrinsicIsOverloaded(ID: NonZero<c_uint>) -> Bool; + pub(crate) fn LLVMIntrinsicCopyOverloadedName2<'a>( + Mod: &'a Module, + ID: NonZero<c_uint>, + ParamTypes: *const &'a Type, + ParamCount: size_t, + NameLength: *mut size_t, + ) -> *mut c_char; + // Operations on parameters pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; pub(crate) safe fn LLVMCountParams(Fn: &Value) -> c_uint; 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 { |
