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