1#![allow(non_snake_case)]
2
3use std::ffi::{CStr, CString};
4use std::num::NonZero;
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(crate) use self::CallConv::*;
14pub(crate) use self::CodeGenOptSize::*;
15pub(crate) use self::MetadataType::*;
16pub(crate) use self::ffi::*;
17use crate::common::AsCCharPtr;
18
19pub(crate) mod archive_ro;
20pub(crate) mod diagnostic;
21pub(crate) mod enzyme_ffi;
22mod ffi;
23
24pub(crate) 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(crate) 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(crate) 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);
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 set_unnamed_address(global: &Value, unnamed: UnnamedAddr) {
195 LLVMSetUnnamedAddress(global, unnamed);
196}
197
198pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
199 unsafe {
200 LLVMSetThreadLocalMode(global, mode);
201 }
202}
203
204impl AttributeKind {
205 pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
207 unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
208 }
209}
210
211impl MemoryEffects {
212 pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
214 unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
215 }
216}
217
218pub(crate) fn set_section(llglobal: &Value, section_name: &CStr) {
219 unsafe {
220 LLVMSetSection(llglobal, section_name.as_ptr());
221 }
222}
223
224pub(crate) fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
225 unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
226}
227
228pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
229 unsafe {
230 LLVMSetInitializer(llglobal, constant_val);
231 }
232}
233
234pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
235 LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
236}
237
238pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
239 unsafe { LLVMGetLinkage(llglobal) }.to_rust()
240}
241
242pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
243 unsafe {
244 LLVMSetLinkage(llglobal, linkage);
245 }
246}
247
248pub(crate) fn is_declaration(llglobal: &Value) -> bool {
249 unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
250}
251
252pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
253 unsafe { LLVMGetVisibility(llglobal) }.to_rust()
254}
255
256pub(crate) fn set_visibility(llglobal: &Value, visibility: Visibility) {
257 unsafe {
258 LLVMSetVisibility(llglobal, visibility);
259 }
260}
261
262pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
263 unsafe {
264 ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
265 }
266}
267
268pub(crate) fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
273 unsafe {
274 let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr());
275 LLVMSetComdat(llglobal, comdat);
276 }
277}
278
279pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value {
281 unsafe {
282 assert!(
283 index < LLVMCountParams(llfn),
284 "out of bounds argument access: {} out of {} arguments",
285 index,
286 LLVMCountParams(llfn)
287 );
288 LLVMGetParam(llfn, index)
289 }
290}
291
292pub(crate) fn get_value_name(value: &Value) -> Vec<u8> {
296 unsafe {
297 let mut len = 0;
298 let data = LLVMGetValueName2(value, &mut len);
299 std::slice::from_raw_parts(data.cast(), len).to_vec()
300 }
301}
302
303#[derive(Debug, Copy, Clone)]
304pub(crate) struct Intrinsic {
305 id: NonZero<c_uint>,
306}
307
308impl Intrinsic {
309 pub(crate) fn lookup(name: &[u8]) -> Option<Self> {
310 let id = unsafe { LLVMLookupIntrinsicID(name.as_c_char_ptr(), name.len()) };
311 NonZero::new(id).map(|id| Self { id })
312 }
313
314 pub(crate) fn get_declaration<'ll>(
315 self,
316 llmod: &'ll Module,
317 type_params: &[&'ll Type],
318 ) -> &'ll Value {
319 unsafe {
320 LLVMGetIntrinsicDeclaration(llmod, self.id, type_params.as_ptr(), type_params.len())
321 }
322 }
323}
324
325pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
327 unsafe {
328 let data = name.as_c_char_ptr();
329 LLVMSetValueName2(value, data, name.len());
330 }
331}
332
333pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
334 String::from_utf8(RustString::build_byte_buffer(f))
335}
336
337pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
338 RustString::build_byte_buffer(f)
339}
340
341pub(crate) fn twine_to_string(tr: &Twine) -> String {
342 unsafe {
343 build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
344 }
345}
346
347pub(crate) fn last_error() -> Option<String> {
348 unsafe {
349 let cstr = LLVMRustGetLastError();
350 if cstr.is_null() {
351 None
352 } else {
353 let err = CStr::from_ptr(cstr).to_bytes();
354 let err = String::from_utf8_lossy(err).to_string();
355 libc::free(cstr as *mut _);
356 Some(err)
357 }
358 }
359}
360
361pub(crate) struct OperandBundleBox<'a> {
364 raw: ptr::NonNull<OperandBundle<'a>>,
365}
366
367impl<'a> OperandBundleBox<'a> {
368 pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
369 let raw = unsafe {
370 LLVMCreateOperandBundle(
371 name.as_c_char_ptr(),
372 name.len(),
373 vals.as_ptr(),
374 vals.len() as c_uint,
375 )
376 };
377 Self { raw: ptr::NonNull::new(raw).unwrap() }
378 }
379
380 pub(crate) fn as_ref(&self) -> &OperandBundle<'a> {
385 unsafe { self.raw.as_ref() }
388 }
389}
390
391impl Drop for OperandBundleBox<'_> {
392 fn drop(&mut self) {
393 unsafe {
394 LLVMDisposeOperandBundle(self.raw);
395 }
396 }
397}
398
399pub(crate) fn add_module_flag_u32(
400 module: &Module,
401 merge_behavior: ModuleFlagMergeBehavior,
402 key: &str,
403 value: u32,
404) {
405 unsafe {
406 LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_c_char_ptr(), key.len(), value);
407 }
408}
409
410pub(crate) fn add_module_flag_str(
411 module: &Module,
412 merge_behavior: ModuleFlagMergeBehavior,
413 key: &str,
414 value: &str,
415) {
416 unsafe {
417 LLVMRustAddModuleFlagString(
418 module,
419 merge_behavior,
420 key.as_c_char_ptr(),
421 key.len(),
422 value.as_c_char_ptr(),
423 value.len(),
424 );
425 }
426}
427
428pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) {
429 unsafe {
430 LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport);
431 }
432}
433
434pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
435 unsafe {
436 LLVMRustSetDSOLocal(v, true);
437 }
438}
439
440pub(crate) fn append_module_inline_asm<'ll>(llmod: &'ll Module, asm: &[u8]) {
443 unsafe {
444 LLVMAppendModuleInlineAsm(llmod, asm.as_ptr(), asm.len());
445 }
446}