rustc_codegen_llvm/llvm/
mod.rs

1#![allow(non_snake_case)]
2
3use std::ffi::{CStr, CString};
4use std::ptr;
5use std::str::FromStr;
6use std::string::FromUtf8Error;
7
8use libc::c_uint;
9use rustc_abi::{Align, Size, WrappingRange};
10use rustc_llvm::RustString;
11
12pub use self::CallConv::*;
13pub use self::CodeGenOptSize::*;
14pub use self::MetadataType::*;
15pub use self::ffi::*;
16use crate::common::AsCCharPtr;
17
18pub mod archive_ro;
19pub mod diagnostic;
20pub mod enzyme_ffi;
21mod ffi;
22
23pub use self::enzyme_ffi::*;
24
25impl LLVMRustResult {
26    pub(crate) fn into_result(self) -> Result<(), ()> {
27        match self {
28            LLVMRustResult::Success => Ok(()),
29            LLVMRustResult::Failure => Err(()),
30        }
31    }
32}
33
34pub(crate) fn AddFunctionAttributes<'ll>(
35    llfn: &'ll Value,
36    idx: AttributePlace,
37    attrs: &[&'ll Attribute],
38) {
39    unsafe {
40        LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len());
41    }
42}
43
44pub(crate) fn AddCallSiteAttributes<'ll>(
45    callsite: &'ll Value,
46    idx: AttributePlace,
47    attrs: &[&'ll Attribute],
48) {
49    unsafe {
50        LLVMRustAddCallSiteAttributes(callsite, idx.as_uint(), attrs.as_ptr(), attrs.len());
51    }
52}
53
54pub(crate) fn CreateAttrStringValue<'ll>(
55    llcx: &'ll Context,
56    attr: &str,
57    value: &str,
58) -> &'ll Attribute {
59    unsafe {
60        LLVMCreateStringAttribute(
61            llcx,
62            attr.as_c_char_ptr(),
63            attr.len().try_into().unwrap(),
64            value.as_c_char_ptr(),
65            value.len().try_into().unwrap(),
66        )
67    }
68}
69
70pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
71    unsafe {
72        LLVMCreateStringAttribute(
73            llcx,
74            attr.as_c_char_ptr(),
75            attr.len().try_into().unwrap(),
76            std::ptr::null(),
77            0,
78        )
79    }
80}
81
82pub(crate) fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
83    unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) }
84}
85
86pub(crate) fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
87    unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) }
88}
89
90pub(crate) fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
91    unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) }
92}
93
94pub(crate) fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
95    unsafe { LLVMRustCreateByValAttr(llcx, ty) }
96}
97
98pub(crate) fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
99    unsafe { LLVMRustCreateStructRetAttr(llcx, ty) }
100}
101
102pub(crate) fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
103    unsafe { LLVMRustCreateUWTableAttr(llcx, async_) }
104}
105
106pub(crate) fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
107    unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) }
108}
109
110pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
111    unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) }
112}
113
114pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
115    let lower = range.start;
116    let upper = range.end.wrapping_add(1);
117    let lower_words = [lower as u64, (lower >> 64) as u64];
118    let upper_words = [upper as u64, (upper >> 64) as u64];
119    unsafe {
120        LLVMRustCreateRangeAttribute(
121            llcx,
122            size.bits().try_into().unwrap(),
123            lower_words.as_ptr(),
124            upper_words.as_ptr(),
125        )
126    }
127}
128
129#[derive(Copy, Clone)]
130pub enum AttributePlace {
131    ReturnValue,
132    Argument(u32),
133    Function,
134}
135
136impl AttributePlace {
137    pub(crate) fn as_uint(self) -> c_uint {
138        match self {
139            AttributePlace::ReturnValue => 0,
140            AttributePlace::Argument(i) => 1 + i,
141            AttributePlace::Function => !0,
142        }
143    }
144}
145
146#[derive(Copy, Clone, PartialEq)]
147#[repr(C)]
148pub enum CodeGenOptSize {
149    CodeGenOptSizeNone = 0,
150    CodeGenOptSizeDefault = 1,
151    CodeGenOptSizeAggressive = 2,
152}
153
154impl FromStr for ArchiveKind {
155    type Err = ();
156
157    fn from_str(s: &str) -> Result<Self, Self::Err> {
158        match s {
159            "gnu" => Ok(ArchiveKind::K_GNU),
160            "bsd" => Ok(ArchiveKind::K_BSD),
161            "darwin" => Ok(ArchiveKind::K_DARWIN),
162            "coff" => Ok(ArchiveKind::K_COFF),
163            "aix_big" => Ok(ArchiveKind::K_AIXBIG),
164            _ => Err(()),
165        }
166    }
167}
168
169pub(crate) fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
170    unsafe {
171        LLVMSetInstructionCallConv(instr, cc as c_uint);
172    }
173}
174pub(crate) fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
175    unsafe {
176        LLVMSetFunctionCallConv(fn_, cc as c_uint);
177    }
178}
179
180// Externally visible symbols that might appear in multiple codegen units need to appear in
181// their own comdat section so that the duplicates can be discarded at link time. This can for
182// example happen for generics when using multiple codegen units. This function simply uses the
183// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
184// function.
185// For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
186pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) {
187    let name_buf = get_value_name(val).to_vec();
188    let name =
189        CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap();
190    set_comdat(llmod, val, &name);
191}
192
193pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
194    unsafe {
195        LLVMSetUnnamedAddress(global, unnamed);
196    }
197}
198
199pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
200    unsafe {
201        LLVMSetThreadLocalMode(global, mode);
202    }
203}
204
205impl AttributeKind {
206    /// Create an LLVM Attribute with no associated value.
207    pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
208        unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
209    }
210}
211
212impl MemoryEffects {
213    /// Create an LLVM Attribute with these memory effects.
214    pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
215        unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
216    }
217}
218
219pub(crate) fn set_section(llglobal: &Value, section_name: &CStr) {
220    unsafe {
221        LLVMSetSection(llglobal, section_name.as_ptr());
222    }
223}
224
225pub(crate) fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
226    unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
227}
228
229pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
230    unsafe {
231        LLVMSetInitializer(llglobal, constant_val);
232    }
233}
234
235pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
236    unsafe {
237        LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
238    }
239}
240
241pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
242    unsafe { LLVMGetLinkage(llglobal) }.to_rust()
243}
244
245pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
246    unsafe {
247        LLVMSetLinkage(llglobal, linkage);
248    }
249}
250
251pub(crate) fn is_declaration(llglobal: &Value) -> bool {
252    unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
253}
254
255pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
256    unsafe { LLVMGetVisibility(llglobal) }.to_rust()
257}
258
259pub(crate) fn set_visibility(llglobal: &Value, visibility: Visibility) {
260    unsafe {
261        LLVMSetVisibility(llglobal, visibility);
262    }
263}
264
265pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
266    unsafe {
267        ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
268    }
269}
270
271/// Get the `name`d comdat from `llmod` and assign it to `llglobal`.
272///
273/// Inserts the comdat into `llmod` if it does not exist.
274/// It is an error to call this if the target does not support comdat.
275pub(crate) fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
276    unsafe {
277        let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr());
278        LLVMSetComdat(llglobal, comdat);
279    }
280}
281
282/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
283pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value {
284    unsafe {
285        assert!(
286            index < LLVMCountParams(llfn),
287            "out of bounds argument access: {} out of {} arguments",
288            index,
289            LLVMCountParams(llfn)
290        );
291        LLVMGetParam(llfn, index)
292    }
293}
294
295/// Safe wrapper for `LLVMGetValueName2` into a byte slice
296pub(crate) fn get_value_name(value: &Value) -> &[u8] {
297    unsafe {
298        let mut len = 0;
299        let data = LLVMGetValueName2(value, &mut len);
300        std::slice::from_raw_parts(data.cast(), len)
301    }
302}
303
304/// Safe wrapper for `LLVMSetValueName2` from a byte slice
305pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
306    unsafe {
307        let data = name.as_c_char_ptr();
308        LLVMSetValueName2(value, data, name.len());
309    }
310}
311
312pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
313    String::from_utf8(RustString::build_byte_buffer(f))
314}
315
316pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
317    RustString::build_byte_buffer(f)
318}
319
320pub(crate) fn twine_to_string(tr: &Twine) -> String {
321    unsafe {
322        build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
323    }
324}
325
326pub(crate) fn last_error() -> Option<String> {
327    unsafe {
328        let cstr = LLVMRustGetLastError();
329        if cstr.is_null() {
330            None
331        } else {
332            let err = CStr::from_ptr(cstr).to_bytes();
333            let err = String::from_utf8_lossy(err).to_string();
334            libc::free(cstr as *mut _);
335            Some(err)
336        }
337    }
338}
339
340/// Owns an [`OperandBundle`], and will dispose of it when dropped.
341pub(crate) struct OperandBundleOwned<'a> {
342    raw: ptr::NonNull<OperandBundle<'a>>,
343}
344
345impl<'a> OperandBundleOwned<'a> {
346    pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
347        let raw = unsafe {
348            LLVMCreateOperandBundle(
349                name.as_c_char_ptr(),
350                name.len(),
351                vals.as_ptr(),
352                vals.len() as c_uint,
353            )
354        };
355        OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() }
356    }
357
358    /// Returns inner `OperandBundle` type.
359    ///
360    /// This could be a `Deref` implementation, but `OperandBundle` contains an extern type and
361    /// `Deref::Target: ?Sized`.
362    pub(crate) fn raw(&self) -> &OperandBundle<'a> {
363        // SAFETY: The returned reference is opaque and can only used for FFI.
364        // It is valid for as long as `&self` is.
365        unsafe { self.raw.as_ref() }
366    }
367}
368
369impl Drop for OperandBundleOwned<'_> {
370    fn drop(&mut self) {
371        unsafe {
372            LLVMDisposeOperandBundle(self.raw);
373        }
374    }
375}
376
377pub(crate) fn add_module_flag_u32(
378    module: &Module,
379    merge_behavior: ModuleFlagMergeBehavior,
380    key: &str,
381    value: u32,
382) {
383    unsafe {
384        LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_c_char_ptr(), key.len(), value);
385    }
386}
387
388pub(crate) fn add_module_flag_str(
389    module: &Module,
390    merge_behavior: ModuleFlagMergeBehavior,
391    key: &str,
392    value: &str,
393) {
394    unsafe {
395        LLVMRustAddModuleFlagString(
396            module,
397            merge_behavior,
398            key.as_c_char_ptr(),
399            key.len(),
400            value.as_c_char_ptr(),
401            value.len(),
402        );
403    }
404}
405
406pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) {
407    unsafe {
408        LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport);
409    }
410}
411
412pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
413    unsafe {
414        LLVMRustSetDSOLocal(v, true);
415    }
416}