1use llvm_sys::target::{
2 LLVMABIAlignmentOfType, LLVMABISizeOfType, LLVMByteOrder, LLVMByteOrdering, LLVMCallFrameAlignmentOfType,
3 LLVMCopyStringRepOfTargetData, LLVMCreateTargetData, LLVMDisposeTargetData, LLVMElementAtOffset,
4 LLVMIntPtrTypeForASInContext, LLVMIntPtrTypeInContext, LLVMOffsetOfElement, LLVMPointerSize, LLVMPointerSizeForAS,
5 LLVMPreferredAlignmentOfGlobal, LLVMPreferredAlignmentOfType, LLVMSizeOfTypeInBits, LLVMStoreSizeOfType,
6 LLVMTargetDataRef,
7};
8use llvm_sys::target_machine::LLVMCreateTargetDataLayout;
9use llvm_sys::target_machine::{
10 LLVMAddAnalysisPasses, LLVMCodeGenFileType, LLVMCodeModel, LLVMCreateTargetMachine, LLVMDisposeTargetMachine,
11 LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMGetNextTarget, LLVMGetTargetDescription, LLVMGetTargetFromName,
12 LLVMGetTargetFromTriple, LLVMGetTargetMachineCPU, LLVMGetTargetMachineFeatureString, LLVMGetTargetMachineTarget,
13 LLVMGetTargetMachineTriple, LLVMGetTargetName, LLVMRelocMode, LLVMSetTargetMachineAsmVerbosity,
14 LLVMTargetHasAsmBackend, LLVMTargetHasJIT, LLVMTargetHasTargetMachine, LLVMTargetMachineEmitToFile,
15 LLVMTargetMachineEmitToMemoryBuffer, LLVMTargetMachineRef, LLVMTargetRef,
16};
17#[llvm_versions(18..)]
18use llvm_sys::target_machine::{
19 LLVMCreateTargetMachineOptions, LLVMCreateTargetMachineWithOptions, LLVMDisposeTargetMachineOptions,
20 LLVMTargetMachineOptionsRef, LLVMTargetMachineOptionsSetABI, LLVMTargetMachineOptionsSetCPU,
21 LLVMTargetMachineOptionsSetCodeGenOptLevel, LLVMTargetMachineOptionsSetCodeModel,
22 LLVMTargetMachineOptionsSetFeatures, LLVMTargetMachineOptionsSetRelocMode,
23};
24use once_cell::sync::Lazy;
25use std::sync::RwLock;
26
27use crate::context::AsContextRef;
28use crate::data_layout::DataLayout;
29use crate::memory_buffer::MemoryBuffer;
30use crate::module::Module;
31use crate::passes::PassManager;
32use crate::support::{to_c_str, LLVMString};
33use crate::types::{AnyType, AsTypeRef, IntType, StructType};
34use crate::values::{AsValueRef, GlobalValue};
35use crate::{AddressSpace, OptimizationLevel};
36
37use std::default::Default;
38use std::ffi::CStr;
39use std::fmt;
40use std::mem::MaybeUninit;
41use std::path::Path;
42use std::ptr;
43
44#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
45pub enum CodeModel {
46 #[default]
47 Default,
48 JITDefault,
49 Small,
50 Kernel,
51 Medium,
52 Large,
53}
54
55impl From<CodeModel> for LLVMCodeModel {
56 fn from(value: CodeModel) -> Self {
57 match value {
58 CodeModel::Default => LLVMCodeModel::LLVMCodeModelDefault,
59 CodeModel::JITDefault => LLVMCodeModel::LLVMCodeModelJITDefault,
60 CodeModel::Small => LLVMCodeModel::LLVMCodeModelSmall,
61 CodeModel::Kernel => LLVMCodeModel::LLVMCodeModelKernel,
62 CodeModel::Medium => LLVMCodeModel::LLVMCodeModelMedium,
63 CodeModel::Large => LLVMCodeModel::LLVMCodeModelLarge,
64 }
65 }
66}
67
68#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
69pub enum RelocMode {
70 #[default]
71 Default,
72 Static,
73 PIC,
74 DynamicNoPic,
75}
76
77impl From<RelocMode> for LLVMRelocMode {
78 fn from(value: RelocMode) -> Self {
79 match value {
80 RelocMode::Default => LLVMRelocMode::LLVMRelocDefault,
81 RelocMode::Static => LLVMRelocMode::LLVMRelocStatic,
82 RelocMode::PIC => LLVMRelocMode::LLVMRelocPIC,
83 RelocMode::DynamicNoPic => LLVMRelocMode::LLVMRelocDynamicNoPic,
84 }
85 }
86}
87
88#[derive(Debug, PartialEq, Eq, Copy, Clone)]
89pub enum FileType {
90 Assembly,
91 Object,
92}
93
94impl FileType {
95 fn as_llvm_file_type(&self) -> LLVMCodeGenFileType {
96 match *self {
97 FileType::Assembly => LLVMCodeGenFileType::LLVMAssemblyFile,
98 FileType::Object => LLVMCodeGenFileType::LLVMObjectFile,
99 }
100 }
101}
102
103#[derive(Copy, Clone, Debug, PartialEq, Eq)]
105pub struct InitializationConfig {
106 pub asm_parser: bool,
107 pub asm_printer: bool,
108 pub base: bool,
109 pub disassembler: bool,
110 pub info: bool,
111 pub machine_code: bool,
112}
113
114impl Default for InitializationConfig {
115 fn default() -> Self {
116 InitializationConfig {
117 asm_parser: true,
118 asm_printer: true,
119 base: true,
120 disassembler: true,
121 info: true,
122 machine_code: true,
123 }
124 }
125}
126
127#[derive(Eq)]
128pub struct TargetTriple {
129 pub(crate) triple: LLVMString,
130}
131
132impl TargetTriple {
133 pub unsafe fn new(triple: LLVMString) -> TargetTriple {
134 TargetTriple { triple }
135 }
136
137 pub fn create(triple: &str) -> TargetTriple {
138 let c_string = to_c_str(triple);
139
140 TargetTriple {
141 triple: LLVMString::create_from_c_str(&c_string),
142 }
143 }
144
145 pub fn as_str(&self) -> &CStr {
146 unsafe { CStr::from_ptr(self.as_ptr()) }
147 }
148
149 pub fn as_ptr(&self) -> *const ::libc::c_char {
150 self.triple.as_ptr()
151 }
152}
153
154impl PartialEq for TargetTriple {
155 fn eq(&self, other: &TargetTriple) -> bool {
156 self.triple == other.triple
157 }
158}
159
160impl fmt::Debug for TargetTriple {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 write!(f, "TargetTriple({:?})", self.triple)
163 }
164}
165
166impl fmt::Display for TargetTriple {
167 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
168 write!(f, "TargetTriple({:?})", self.triple)
169 }
170}
171
172static TARGET_LOCK: Lazy<RwLock<()>> = Lazy::new(|| RwLock::new(()));
173
174#[derive(Debug, Eq, PartialEq)]
176pub struct Target {
177 target: LLVMTargetRef,
178}
179
180impl Target {
181 pub unsafe fn new(target: LLVMTargetRef) -> Self {
182 assert!(!target.is_null());
183
184 Target { target }
185 }
186
187 pub fn as_mut_ptr(&self) -> LLVMTargetRef {
189 self.target
190 }
191
192 #[cfg(feature = "target-x86")]
194 pub fn initialize_x86(config: &InitializationConfig) {
195 use llvm_sys::target::{
196 LLVMInitializeX86AsmParser, LLVMInitializeX86AsmPrinter, LLVMInitializeX86Disassembler,
197 LLVMInitializeX86Target, LLVMInitializeX86TargetInfo, LLVMInitializeX86TargetMC,
198 };
199
200 if config.base {
201 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
202 unsafe { LLVMInitializeX86Target() };
203 }
204
205 if config.info {
206 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
207 unsafe { LLVMInitializeX86TargetInfo() };
208 }
209
210 if config.asm_printer {
211 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
212 unsafe { LLVMInitializeX86AsmPrinter() };
213 }
214
215 if config.asm_parser {
216 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
217 unsafe { LLVMInitializeX86AsmParser() };
218 }
219
220 if config.disassembler {
221 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
222 unsafe { LLVMInitializeX86Disassembler() };
223 }
224
225 if config.machine_code {
226 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
227 unsafe { LLVMInitializeX86TargetMC() };
228 }
229 }
230
231 #[cfg(feature = "target-arm")]
232 pub fn initialize_arm(config: &InitializationConfig) {
233 use llvm_sys::target::{
234 LLVMInitializeARMAsmParser, LLVMInitializeARMAsmPrinter, LLVMInitializeARMDisassembler,
235 LLVMInitializeARMTarget, LLVMInitializeARMTargetInfo, LLVMInitializeARMTargetMC,
236 };
237
238 if config.base {
239 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
240 unsafe { LLVMInitializeARMTarget() };
241 }
242
243 if config.info {
244 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
245 unsafe { LLVMInitializeARMTargetInfo() };
246 }
247
248 if config.asm_printer {
249 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
250 unsafe { LLVMInitializeARMAsmPrinter() };
251 }
252
253 if config.asm_parser {
254 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
255 unsafe { LLVMInitializeARMAsmParser() };
256 }
257
258 if config.disassembler {
259 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
260 unsafe { LLVMInitializeARMDisassembler() };
261 }
262
263 if config.machine_code {
264 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
265 unsafe { LLVMInitializeARMTargetMC() };
266 }
267 }
268
269 #[cfg(feature = "target-mips")]
270 pub fn initialize_mips(config: &InitializationConfig) {
271 use llvm_sys::target::{
272 LLVMInitializeMipsAsmParser, LLVMInitializeMipsAsmPrinter, LLVMInitializeMipsDisassembler,
273 LLVMInitializeMipsTarget, LLVMInitializeMipsTargetInfo, LLVMInitializeMipsTargetMC,
274 };
275
276 if config.base {
277 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
278 unsafe { LLVMInitializeMipsTarget() };
279 }
280
281 if config.info {
282 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
283 unsafe { LLVMInitializeMipsTargetInfo() };
284 }
285
286 if config.asm_printer {
287 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
288 unsafe { LLVMInitializeMipsAsmPrinter() };
289 }
290
291 if config.asm_parser {
292 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
293 unsafe { LLVMInitializeMipsAsmParser() };
294 }
295
296 if config.disassembler {
297 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
298 unsafe { LLVMInitializeMipsDisassembler() };
299 }
300
301 if config.machine_code {
302 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
303 unsafe { LLVMInitializeMipsTargetMC() };
304 }
305 }
306
307 #[cfg(feature = "target-aarch64")]
308 pub fn initialize_aarch64(config: &InitializationConfig) {
309 use llvm_sys::target::{
310 LLVMInitializeAArch64AsmParser, LLVMInitializeAArch64AsmPrinter, LLVMInitializeAArch64Disassembler,
311 LLVMInitializeAArch64Target, LLVMInitializeAArch64TargetInfo, LLVMInitializeAArch64TargetMC,
312 };
313
314 if config.base {
315 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
316 unsafe { LLVMInitializeAArch64Target() };
317 }
318
319 if config.info {
320 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
321 unsafe { LLVMInitializeAArch64TargetInfo() };
322 }
323
324 if config.asm_printer {
325 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
326 unsafe { LLVMInitializeAArch64AsmPrinter() };
327 }
328
329 if config.asm_parser {
330 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
331 unsafe { LLVMInitializeAArch64AsmParser() };
332 }
333
334 if config.disassembler {
335 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
336 unsafe { LLVMInitializeAArch64Disassembler() };
337 }
338
339 if config.machine_code {
340 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
341 unsafe { LLVMInitializeAArch64TargetMC() };
342 }
343 }
344
345 #[cfg(feature = "target-amdgpu")]
346 pub fn initialize_amd_gpu(config: &InitializationConfig) {
347 use llvm_sys::target::{
348 LLVMInitializeAMDGPUAsmParser, LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeAMDGPUTarget,
349 LLVMInitializeAMDGPUTargetInfo, LLVMInitializeAMDGPUTargetMC,
350 };
351
352 if config.base {
353 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
354 unsafe { LLVMInitializeAMDGPUTarget() };
355 }
356
357 if config.info {
358 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
359 unsafe { LLVMInitializeAMDGPUTargetInfo() };
360 }
361
362 if config.asm_printer {
363 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
364 unsafe { LLVMInitializeAMDGPUAsmPrinter() };
365 }
366
367 if config.asm_parser {
368 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
369 unsafe { LLVMInitializeAMDGPUAsmParser() };
370 }
371
372 if config.machine_code {
373 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
374 unsafe { LLVMInitializeAMDGPUTargetMC() };
375 }
376
377 }
379
380 #[cfg(feature = "target-systemz")]
381 pub fn initialize_system_z(config: &InitializationConfig) {
382 use llvm_sys::target::{
383 LLVMInitializeSystemZAsmParser, LLVMInitializeSystemZAsmPrinter, LLVMInitializeSystemZDisassembler,
384 LLVMInitializeSystemZTarget, LLVMInitializeSystemZTargetInfo, LLVMInitializeSystemZTargetMC,
385 };
386
387 if config.base {
388 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
389 unsafe { LLVMInitializeSystemZTarget() };
390 }
391
392 if config.info {
393 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
394 unsafe { LLVMInitializeSystemZTargetInfo() };
395 }
396
397 if config.asm_printer {
398 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
399 unsafe { LLVMInitializeSystemZAsmPrinter() };
400 }
401
402 if config.asm_parser {
403 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
404 unsafe { LLVMInitializeSystemZAsmParser() };
405 }
406
407 if config.disassembler {
408 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
409 unsafe { LLVMInitializeSystemZDisassembler() };
410 }
411
412 if config.machine_code {
413 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
414 unsafe { LLVMInitializeSystemZTargetMC() };
415 }
416 }
417
418 #[cfg(feature = "target-hexagon")]
419 pub fn initialize_hexagon(config: &InitializationConfig) {
420 use llvm_sys::target::{
421 LLVMInitializeHexagonAsmPrinter, LLVMInitializeHexagonDisassembler, LLVMInitializeHexagonTarget,
422 LLVMInitializeHexagonTargetInfo, LLVMInitializeHexagonTargetMC,
423 };
424
425 if config.base {
426 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
427 unsafe { LLVMInitializeHexagonTarget() };
428 }
429
430 if config.info {
431 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
432 unsafe { LLVMInitializeHexagonTargetInfo() };
433 }
434
435 if config.asm_printer {
436 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
437 unsafe { LLVMInitializeHexagonAsmPrinter() };
438 }
439
440 if config.disassembler {
443 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
444 unsafe { LLVMInitializeHexagonDisassembler() };
445 }
446
447 if config.machine_code {
448 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
449 unsafe { LLVMInitializeHexagonTargetMC() };
450 }
451 }
452
453 #[cfg(feature = "target-nvptx")]
454 pub fn initialize_nvptx(config: &InitializationConfig) {
455 use llvm_sys::target::{
456 LLVMInitializeNVPTXAsmPrinter, LLVMInitializeNVPTXTarget, LLVMInitializeNVPTXTargetInfo,
457 LLVMInitializeNVPTXTargetMC,
458 };
459
460 if config.base {
461 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
462 unsafe { LLVMInitializeNVPTXTarget() };
463 }
464
465 if config.info {
466 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
467 unsafe { LLVMInitializeNVPTXTargetInfo() };
468 }
469
470 if config.asm_printer {
471 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
472 unsafe { LLVMInitializeNVPTXAsmPrinter() };
473 }
474
475 if config.machine_code {
478 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
479 unsafe { LLVMInitializeNVPTXTargetMC() };
480 }
481
482 }
484
485 #[cfg(feature = "target-msp430")]
486 pub fn initialize_msp430(config: &InitializationConfig) {
487 use llvm_sys::target::{
488 LLVMInitializeMSP430AsmPrinter, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetInfo,
489 LLVMInitializeMSP430TargetMC,
490 };
491
492 if config.base {
493 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
494 unsafe { LLVMInitializeMSP430Target() };
495 }
496
497 if config.info {
498 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
499 unsafe { LLVMInitializeMSP430TargetInfo() };
500 }
501
502 if config.asm_printer {
503 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
504 unsafe { LLVMInitializeMSP430AsmPrinter() };
505 }
506
507 if config.machine_code {
510 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
511 unsafe { LLVMInitializeMSP430TargetMC() };
512 }
513
514 }
516
517 #[cfg(feature = "target-xcore")]
518 pub fn initialize_x_core(config: &InitializationConfig) {
519 use llvm_sys::target::{
520 LLVMInitializeXCoreAsmPrinter, LLVMInitializeXCoreDisassembler, LLVMInitializeXCoreTarget,
521 LLVMInitializeXCoreTargetInfo, LLVMInitializeXCoreTargetMC,
522 };
523
524 if config.base {
525 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
526 unsafe { LLVMInitializeXCoreTarget() };
527 }
528
529 if config.info {
530 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
531 unsafe { LLVMInitializeXCoreTargetInfo() };
532 }
533
534 if config.asm_printer {
535 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
536 unsafe { LLVMInitializeXCoreAsmPrinter() };
537 }
538
539 if config.disassembler {
542 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
543 unsafe { LLVMInitializeXCoreDisassembler() };
544 }
545
546 if config.machine_code {
547 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
548 unsafe { LLVMInitializeXCoreTargetMC() };
549 }
550 }
551
552 #[cfg(feature = "target-powerpc")]
553 pub fn initialize_power_pc(config: &InitializationConfig) {
554 use llvm_sys::target::{
555 LLVMInitializePowerPCAsmParser, LLVMInitializePowerPCAsmPrinter, LLVMInitializePowerPCDisassembler,
556 LLVMInitializePowerPCTarget, LLVMInitializePowerPCTargetInfo, LLVMInitializePowerPCTargetMC,
557 };
558
559 if config.base {
560 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
561 unsafe { LLVMInitializePowerPCTarget() };
562 }
563
564 if config.info {
565 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
566 unsafe { LLVMInitializePowerPCTargetInfo() };
567 }
568
569 if config.asm_printer {
570 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
571 unsafe { LLVMInitializePowerPCAsmPrinter() };
572 }
573
574 if config.asm_parser {
575 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
576 unsafe { LLVMInitializePowerPCAsmParser() };
577 }
578
579 if config.disassembler {
580 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
581 unsafe { LLVMInitializePowerPCDisassembler() };
582 }
583
584 if config.machine_code {
585 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
586 unsafe { LLVMInitializePowerPCTargetMC() };
587 }
588 }
589
590 #[cfg(feature = "target-sparc")]
591 pub fn initialize_sparc(config: &InitializationConfig) {
592 use llvm_sys::target::{
593 LLVMInitializeSparcAsmParser, LLVMInitializeSparcAsmPrinter, LLVMInitializeSparcDisassembler,
594 LLVMInitializeSparcTarget, LLVMInitializeSparcTargetInfo, LLVMInitializeSparcTargetMC,
595 };
596
597 if config.base {
598 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
599 unsafe { LLVMInitializeSparcTarget() };
600 }
601
602 if config.info {
603 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
604 unsafe { LLVMInitializeSparcTargetInfo() };
605 }
606
607 if config.asm_printer {
608 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
609 unsafe { LLVMInitializeSparcAsmPrinter() };
610 }
611
612 if config.asm_parser {
613 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
614 unsafe { LLVMInitializeSparcAsmParser() };
615 }
616
617 if config.disassembler {
618 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
619 unsafe { LLVMInitializeSparcDisassembler() };
620 }
621
622 if config.machine_code {
623 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
624 unsafe { LLVMInitializeSparcTargetMC() };
625 }
626 }
627
628 #[cfg(feature = "target-bpf")]
629 pub fn initialize_bpf(config: &InitializationConfig) {
630 use llvm_sys::target::{
631 LLVMInitializeBPFAsmPrinter, LLVMInitializeBPFTarget, LLVMInitializeBPFTargetInfo,
632 LLVMInitializeBPFTargetMC,
633 };
634
635 if config.base {
636 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
637 unsafe { LLVMInitializeBPFTarget() };
638 }
639
640 if config.info {
641 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
642 unsafe { LLVMInitializeBPFTargetInfo() };
643 }
644
645 if config.asm_printer {
646 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
647 unsafe { LLVMInitializeBPFAsmPrinter() };
648 }
649
650 if config.disassembler {
653 use llvm_sys::target::LLVMInitializeBPFDisassembler;
654
655 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
656 unsafe { LLVMInitializeBPFDisassembler() };
657 }
658
659 if config.machine_code {
660 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
661 unsafe { LLVMInitializeBPFTargetMC() };
662 }
663 }
664
665 #[cfg(feature = "target-lanai")]
666 pub fn initialize_lanai(config: &InitializationConfig) {
667 use llvm_sys::target::{
668 LLVMInitializeLanaiAsmParser, LLVMInitializeLanaiAsmPrinter, LLVMInitializeLanaiDisassembler,
669 LLVMInitializeLanaiTarget, LLVMInitializeLanaiTargetInfo, LLVMInitializeLanaiTargetMC,
670 };
671
672 if config.base {
673 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
674 unsafe { LLVMInitializeLanaiTarget() };
675 }
676
677 if config.info {
678 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
679 unsafe { LLVMInitializeLanaiTargetInfo() };
680 }
681
682 if config.asm_printer {
683 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
684 unsafe { LLVMInitializeLanaiAsmPrinter() };
685 }
686
687 if config.asm_parser {
688 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
689 unsafe { LLVMInitializeLanaiAsmParser() };
690 }
691
692 if config.disassembler {
693 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
694 unsafe { LLVMInitializeLanaiDisassembler() };
695 }
696
697 if config.machine_code {
698 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
699 unsafe { LLVMInitializeLanaiTargetMC() };
700 }
701 }
702
703 #[cfg(feature = "target-riscv")]
704 pub fn initialize_riscv(config: &InitializationConfig) {
705 use llvm_sys::target::{
706 LLVMInitializeRISCVAsmParser, LLVMInitializeRISCVAsmPrinter, LLVMInitializeRISCVDisassembler,
707 LLVMInitializeRISCVTarget, LLVMInitializeRISCVTargetInfo, LLVMInitializeRISCVTargetMC,
708 };
709
710 if config.base {
711 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
712 unsafe { LLVMInitializeRISCVTarget() };
713 }
714
715 if config.info {
716 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
717 unsafe { LLVMInitializeRISCVTargetInfo() };
718 }
719
720 if config.asm_printer {
721 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
722 unsafe { LLVMInitializeRISCVAsmPrinter() };
723 }
724
725 if config.asm_parser {
726 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
727 unsafe { LLVMInitializeRISCVAsmParser() };
728 }
729
730 if config.disassembler {
731 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
732 unsafe { LLVMInitializeRISCVDisassembler() };
733 }
734
735 if config.machine_code {
736 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
737 unsafe { LLVMInitializeRISCVTargetMC() };
738 }
739 }
740
741 #[cfg(feature = "target-loongarch")]
742 #[llvm_versions(16..)]
743 pub fn initialize_loongarch(config: &InitializationConfig) {
744 use llvm_sys::target::{
745 LLVMInitializeLoongArchAsmParser, LLVMInitializeLoongArchAsmPrinter, LLVMInitializeLoongArchDisassembler,
746 LLVMInitializeLoongArchTarget, LLVMInitializeLoongArchTargetInfo, LLVMInitializeLoongArchTargetMC,
747 };
748
749 if config.base {
750 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
751 unsafe { LLVMInitializeLoongArchTarget() };
752 }
753
754 if config.info {
755 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
756 unsafe { LLVMInitializeLoongArchTargetInfo() };
757 }
758
759 if config.asm_printer {
760 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
761 unsafe { LLVMInitializeLoongArchAsmPrinter() };
762 }
763
764 if config.asm_parser {
765 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
766 unsafe { LLVMInitializeLoongArchAsmParser() };
767 }
768
769 if config.disassembler {
770 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
771 unsafe { LLVMInitializeLoongArchDisassembler() };
772 }
773
774 if config.machine_code {
775 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
776 unsafe { LLVMInitializeLoongArchTargetMC() };
777 }
778 }
779
780 #[cfg(feature = "target-webassembly")]
781 pub fn initialize_webassembly(config: &InitializationConfig) {
782 use llvm_sys::target::{
783 LLVMInitializeWebAssemblyAsmParser, LLVMInitializeWebAssemblyAsmPrinter,
784 LLVMInitializeWebAssemblyDisassembler, LLVMInitializeWebAssemblyTarget,
785 LLVMInitializeWebAssemblyTargetInfo, LLVMInitializeWebAssemblyTargetMC,
786 };
787
788 if config.base {
789 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
790 unsafe { LLVMInitializeWebAssemblyTarget() };
791 }
792
793 if config.info {
794 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
795 unsafe { LLVMInitializeWebAssemblyTargetInfo() };
796 }
797
798 if config.asm_printer {
799 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
800 unsafe { LLVMInitializeWebAssemblyAsmPrinter() };
801 }
802
803 if config.asm_parser {
804 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
805 unsafe { LLVMInitializeWebAssemblyAsmParser() };
806 }
807
808 if config.disassembler {
809 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
810 unsafe { LLVMInitializeWebAssemblyDisassembler() };
811 }
812
813 if config.machine_code {
814 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
815 unsafe { LLVMInitializeWebAssemblyTargetMC() };
816 }
817 }
818
819 pub fn initialize_native(config: &InitializationConfig) -> Result<(), String> {
820 use llvm_sys::target::{
821 LLVM_InitializeNativeAsmParser, LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeDisassembler,
822 LLVM_InitializeNativeTarget,
823 };
824
825 if config.base {
826 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
827 let code = unsafe { LLVM_InitializeNativeTarget() };
828
829 if code == 1 {
830 return Err("Unknown error in initializing native target".into());
831 }
832 }
833
834 if config.asm_printer {
835 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
836 let code = unsafe { LLVM_InitializeNativeAsmPrinter() };
837
838 if code == 1 {
839 return Err("Unknown error in initializing native asm printer".into());
840 }
841 }
842
843 if config.asm_parser {
844 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
845 let code = unsafe { LLVM_InitializeNativeAsmParser() };
846
847 if code == 1 {
848 return Err("Unknown error in initializing native asm parser".into());
850 }
851 }
852
853 if config.disassembler {
854 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
855 let code = unsafe { LLVM_InitializeNativeDisassembler() };
856
857 if code == 1 {
858 return Err("Unknown error in initializing native disassembler".into());
859 }
860 }
861
862 Ok(())
863 }
864
865 pub fn initialize_all(config: &InitializationConfig) {
866 use llvm_sys::target::{
867 LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllDisassemblers,
868 LLVM_InitializeAllTargetInfos, LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets,
869 };
870
871 if config.base {
872 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
873 unsafe { LLVM_InitializeAllTargets() };
874 }
875
876 if config.info {
877 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
878 unsafe { LLVM_InitializeAllTargetInfos() };
879 }
880
881 if config.asm_parser {
882 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
883 unsafe { LLVM_InitializeAllAsmParsers() };
884 }
885
886 if config.asm_printer {
887 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
888 unsafe { LLVM_InitializeAllAsmPrinters() };
889 }
890
891 if config.disassembler {
892 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
893 unsafe { LLVM_InitializeAllDisassemblers() };
894 }
895
896 if config.machine_code {
897 let _guard = TARGET_LOCK.write().unwrap_or_else(|e| e.into_inner());
898 unsafe { LLVM_InitializeAllTargetMCs() };
899 }
900 }
901
902 pub fn create_target_machine(
903 &self,
904 triple: &TargetTriple,
905 cpu: &str,
906 features: &str,
907 level: OptimizationLevel,
908 reloc_mode: RelocMode,
909 code_model: CodeModel,
910 ) -> Option<TargetMachine> {
911 let cpu = to_c_str(cpu);
912 let features = to_c_str(features);
913
914 let target_machine = unsafe {
915 LLVMCreateTargetMachine(
916 self.target,
917 triple.as_ptr(),
918 cpu.as_ptr(),
919 features.as_ptr(),
920 level.into(),
921 reloc_mode.into(),
922 code_model.into(),
923 )
924 };
925
926 if target_machine.is_null() {
927 return None;
928 }
929
930 unsafe { Some(TargetMachine::new(target_machine)) }
931 }
932
933 #[llvm_versions(18..)]
957 pub fn create_target_machine_from_options(
958 &self,
959 triple: &TargetTriple,
960 options: TargetMachineOptions,
961 ) -> Option<TargetMachine> {
962 options.into_target_machine(self.target, triple)
963 }
964
965 pub fn get_first() -> Option<Self> {
966 let target = {
967 let _guard = TARGET_LOCK.read().unwrap_or_else(|e| e.into_inner());
968 unsafe { LLVMGetFirstTarget() }
969 };
970
971 if target.is_null() {
972 return None;
973 }
974
975 unsafe { Some(Target::new(target)) }
976 }
977
978 pub fn get_next(&self) -> Option<Self> {
979 let target = unsafe { LLVMGetNextTarget(self.target) };
980
981 if target.is_null() {
982 return None;
983 }
984
985 unsafe { Some(Target::new(target)) }
986 }
987
988 pub fn get_name(&self) -> &CStr {
989 unsafe { CStr::from_ptr(LLVMGetTargetName(self.target)) }
990 }
991
992 pub fn get_description(&self) -> &CStr {
993 unsafe { CStr::from_ptr(LLVMGetTargetDescription(self.target)) }
994 }
995
996 pub fn from_name(name: &str) -> Option<Self> {
997 let c_string = to_c_str(name);
998
999 Self::from_name_raw(c_string.as_ptr())
1000 }
1001
1002 pub(crate) fn from_name_raw(c_string: *const ::libc::c_char) -> Option<Self> {
1003 let target = {
1004 let _guard = TARGET_LOCK.read().unwrap_or_else(|e| e.into_inner());
1005 unsafe { LLVMGetTargetFromName(c_string) }
1006 };
1007
1008 if target.is_null() {
1009 return None;
1010 }
1011
1012 unsafe { Some(Target::new(target)) }
1013 }
1014
1015 pub fn from_triple(triple: &TargetTriple) -> Result<Self, LLVMString> {
1016 let mut target = ptr::null_mut();
1017 let mut err_string = MaybeUninit::uninit();
1018
1019 let code = {
1020 let _guard = TARGET_LOCK.read().unwrap_or_else(|e| e.into_inner());
1021 unsafe { LLVMGetTargetFromTriple(triple.as_ptr(), &mut target, err_string.as_mut_ptr()) }
1022 };
1023
1024 if code == 1 {
1025 unsafe {
1026 return Err(LLVMString::new(err_string.assume_init()));
1027 }
1028 }
1029
1030 unsafe { Ok(Target::new(target)) }
1031 }
1032
1033 pub fn has_jit(&self) -> bool {
1034 unsafe { LLVMTargetHasJIT(self.target) == 1 }
1035 }
1036
1037 pub fn has_target_machine(&self) -> bool {
1038 unsafe { LLVMTargetHasTargetMachine(self.target) == 1 }
1039 }
1040
1041 pub fn has_asm_backend(&self) -> bool {
1042 unsafe { LLVMTargetHasAsmBackend(self.target) == 1 }
1043 }
1044}
1045
1046#[derive(Debug)]
1047pub struct TargetMachine {
1048 pub(crate) target_machine: LLVMTargetMachineRef,
1049}
1050
1051impl TargetMachine {
1052 pub unsafe fn new(target_machine: LLVMTargetMachineRef) -> Self {
1053 assert!(!target_machine.is_null());
1054
1055 TargetMachine { target_machine }
1056 }
1057
1058 pub fn as_mut_ptr(&self) -> LLVMTargetMachineRef {
1060 self.target_machine
1061 }
1062
1063 pub fn get_target(&self) -> Target {
1064 unsafe { Target::new(LLVMGetTargetMachineTarget(self.target_machine)) }
1065 }
1066
1067 pub fn get_triple(&self) -> TargetTriple {
1068 let str = unsafe { LLVMString::new(LLVMGetTargetMachineTriple(self.target_machine)) };
1069
1070 unsafe { TargetTriple::new(str) }
1071 }
1072
1073 pub fn get_default_triple() -> TargetTriple {
1085 let llvm_string = unsafe { LLVMString::new(LLVMGetDefaultTargetTriple()) };
1086
1087 unsafe { TargetTriple::new(llvm_string) }
1088 }
1089
1090 pub fn normalize_triple(triple: &TargetTriple) -> TargetTriple {
1091 use llvm_sys::target_machine::LLVMNormalizeTargetTriple;
1092
1093 let normalized = unsafe { LLVMString::new(LLVMNormalizeTargetTriple(triple.as_ptr())) };
1094
1095 unsafe { TargetTriple::new(normalized) }
1096 }
1097
1098 pub fn get_host_cpu_name() -> LLVMString {
1104 use llvm_sys::target_machine::LLVMGetHostCPUName;
1105
1106 unsafe { LLVMString::new(LLVMGetHostCPUName()) }
1107 }
1108
1109 pub fn get_host_cpu_features() -> LLVMString {
1115 use llvm_sys::target_machine::LLVMGetHostCPUFeatures;
1116
1117 unsafe { LLVMString::new(LLVMGetHostCPUFeatures()) }
1118 }
1119
1120 pub fn get_cpu(&self) -> LLVMString {
1121 unsafe { LLVMString::new(LLVMGetTargetMachineCPU(self.target_machine)) }
1122 }
1123
1124 pub fn get_feature_string(&self) -> &CStr {
1125 unsafe { CStr::from_ptr(LLVMGetTargetMachineFeatureString(self.target_machine)) }
1126 }
1127
1128 pub fn get_target_data(&self) -> TargetData {
1130 unsafe { TargetData::new(LLVMCreateTargetDataLayout(self.target_machine)) }
1131 }
1132
1133 pub fn set_asm_verbosity(&self, verbosity: bool) {
1134 unsafe { LLVMSetTargetMachineAsmVerbosity(self.target_machine, verbosity as i32) }
1135 }
1136
1137 pub fn add_analysis_passes<T>(&self, pass_manager: &PassManager<T>) {
1139 unsafe { LLVMAddAnalysisPasses(self.target_machine, pass_manager.pass_manager) }
1140 }
1141
1142 pub fn write_to_memory_buffer(&self, module: &Module, file_type: FileType) -> Result<MemoryBuffer, LLVMString> {
1177 let mut memory_buffer = ptr::null_mut();
1178 let mut err_string = MaybeUninit::uninit();
1179 let return_code = unsafe {
1180 let module_ptr = module.module.get();
1181 let file_type_ptr = file_type.as_llvm_file_type();
1182
1183 LLVMTargetMachineEmitToMemoryBuffer(
1184 self.target_machine,
1185 module_ptr,
1186 file_type_ptr,
1187 err_string.as_mut_ptr(),
1188 &mut memory_buffer,
1189 )
1190 };
1191
1192 if return_code == 1 {
1193 unsafe {
1194 return Err(LLVMString::new(err_string.assume_init()));
1195 }
1196 }
1197
1198 unsafe { Ok(MemoryBuffer::new(memory_buffer)) }
1199 }
1200
1201 pub fn write_to_file(&self, module: &Module, file_type: FileType, path: &Path) -> Result<(), LLVMString> {
1239 let path = path.to_str().expect("Did not find a valid Unicode path string");
1240 let path_c_string = to_c_str(path);
1241 let mut err_string = MaybeUninit::uninit();
1242 let return_code = unsafe {
1243 let module_ptr = module.module.get();
1245 let path_ptr = path_c_string.as_ptr() as *mut _;
1246 let file_type_ptr = file_type.as_llvm_file_type();
1247
1248 LLVMTargetMachineEmitToFile(
1249 self.target_machine,
1250 module_ptr,
1251 path_ptr,
1252 file_type_ptr,
1253 err_string.as_mut_ptr(),
1254 )
1255 };
1256
1257 if return_code == 1 {
1258 unsafe {
1259 return Err(LLVMString::new(err_string.assume_init()));
1260 }
1261 }
1262
1263 Ok(())
1264 }
1265}
1266
1267impl Drop for TargetMachine {
1268 fn drop(&mut self) {
1269 unsafe { LLVMDisposeTargetMachine(self.target_machine) }
1270 }
1271}
1272
1273#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1274pub enum ByteOrdering {
1275 BigEndian,
1276 LittleEndian,
1277}
1278
1279#[derive(PartialEq, Eq, Debug)]
1280pub struct TargetData {
1281 pub(crate) target_data: LLVMTargetDataRef,
1282}
1283
1284impl TargetData {
1285 pub unsafe fn new(target_data: LLVMTargetDataRef) -> TargetData {
1286 assert!(!target_data.is_null());
1287
1288 TargetData { target_data }
1289 }
1290
1291 pub fn as_mut_ptr(&self) -> LLVMTargetDataRef {
1293 self.target_data
1294 }
1295
1296 #[deprecated(note = "This method will be removed in the future. Please use Context::ptr_sized_int_type instead.")]
1314 pub fn ptr_sized_int_type_in_context<'ctx>(
1315 &self,
1316 context: impl AsContextRef<'ctx>,
1317 address_space: Option<AddressSpace>,
1318 ) -> IntType<'ctx> {
1319 let int_type_ptr = match address_space {
1320 Some(address_space) => unsafe {
1321 LLVMIntPtrTypeForASInContext(context.as_ctx_ref(), self.target_data, address_space.0)
1322 },
1323 None => unsafe { LLVMIntPtrTypeInContext(context.as_ctx_ref(), self.target_data) },
1324 };
1325
1326 unsafe { IntType::new(int_type_ptr) }
1327 }
1328
1329 pub fn get_data_layout(&self) -> DataLayout {
1330 unsafe { DataLayout::new_owned(LLVMCopyStringRepOfTargetData(self.target_data)) }
1331 }
1332
1333 pub fn get_bit_size(&self, type_: &dyn AnyType) -> u64 {
1335 unsafe { LLVMSizeOfTypeInBits(self.target_data, type_.as_type_ref()) }
1336 }
1337
1338 pub fn create(str_repr: &str) -> TargetData {
1340 let c_string = to_c_str(str_repr);
1341
1342 unsafe { TargetData::new(LLVMCreateTargetData(c_string.as_ptr())) }
1343 }
1344
1345 pub fn get_byte_ordering(&self) -> ByteOrdering {
1346 let byte_ordering = unsafe { LLVMByteOrder(self.target_data) };
1347
1348 match byte_ordering {
1349 LLVMByteOrdering::LLVMBigEndian => ByteOrdering::BigEndian,
1350 LLVMByteOrdering::LLVMLittleEndian => ByteOrdering::LittleEndian,
1351 }
1352 }
1353
1354 pub fn get_pointer_byte_size(&self, address_space: Option<AddressSpace>) -> u32 {
1355 match address_space {
1356 Some(address_space) => unsafe { LLVMPointerSizeForAS(self.target_data, address_space.0) },
1357 None => unsafe { LLVMPointerSize(self.target_data) },
1358 }
1359 }
1360
1361 pub fn get_store_size(&self, type_: &dyn AnyType) -> u64 {
1362 unsafe { LLVMStoreSizeOfType(self.target_data, type_.as_type_ref()) }
1363 }
1364
1365 pub fn get_abi_size(&self, type_: &dyn AnyType) -> u64 {
1366 unsafe { LLVMABISizeOfType(self.target_data, type_.as_type_ref()) }
1367 }
1368
1369 pub fn get_abi_alignment(&self, type_: &dyn AnyType) -> u32 {
1370 unsafe { LLVMABIAlignmentOfType(self.target_data, type_.as_type_ref()) }
1371 }
1372
1373 pub fn get_call_frame_alignment(&self, type_: &dyn AnyType) -> u32 {
1374 unsafe { LLVMCallFrameAlignmentOfType(self.target_data, type_.as_type_ref()) }
1375 }
1376
1377 pub fn get_preferred_alignment(&self, type_: &dyn AnyType) -> u32 {
1378 unsafe { LLVMPreferredAlignmentOfType(self.target_data, type_.as_type_ref()) }
1379 }
1380
1381 pub fn get_preferred_alignment_of_global(&self, value: &GlobalValue) -> u32 {
1382 unsafe { LLVMPreferredAlignmentOfGlobal(self.target_data, value.as_value_ref()) }
1383 }
1384
1385 pub fn element_at_offset(&self, struct_type: &StructType, offset: u64) -> u32 {
1386 unsafe { LLVMElementAtOffset(self.target_data, struct_type.as_type_ref(), offset) }
1387 }
1388
1389 pub fn offset_of_element(&self, struct_type: &StructType, element: u32) -> Option<u64> {
1390 if element > struct_type.count_fields() - 1 {
1391 return None;
1392 }
1393
1394 unsafe {
1395 Some(LLVMOffsetOfElement(
1396 self.target_data,
1397 struct_type.as_type_ref(),
1398 element,
1399 ))
1400 }
1401 }
1402}
1403
1404impl Drop for TargetData {
1405 fn drop(&mut self) {
1406 unsafe { LLVMDisposeTargetData(self.target_data) }
1407 }
1408}
1409
1410#[llvm_versions(18..)]
1416#[derive(Default, Debug)]
1417pub struct TargetMachineOptions(Option<LLVMTargetMachineOptionsRef>);
1418
1419#[llvm_versions(18..)]
1420impl TargetMachineOptions {
1421 pub fn new() -> Self {
1422 Default::default()
1423 }
1424
1425 pub fn set_cpu(mut self, cpu: &str) -> Self {
1426 let cpu = to_c_str(cpu);
1427 unsafe { LLVMTargetMachineOptionsSetCPU(self.inner(), cpu.as_ptr()) };
1428
1429 self
1430 }
1431
1432 pub fn set_features(mut self, features: &str) -> Self {
1433 let features = to_c_str(features);
1434 unsafe { LLVMTargetMachineOptionsSetFeatures(self.inner(), features.as_ptr()) };
1435
1436 self
1437 }
1438
1439 pub fn set_abi(mut self, abi: &str) -> Self {
1440 let abi = to_c_str(abi);
1441 unsafe { LLVMTargetMachineOptionsSetABI(self.inner(), abi.as_ptr()) };
1442
1443 self
1444 }
1445
1446 pub fn set_level(mut self, level: OptimizationLevel) -> Self {
1447 unsafe { LLVMTargetMachineOptionsSetCodeGenOptLevel(self.inner(), level.into()) };
1448
1449 self
1450 }
1451
1452 pub fn set_reloc_mode(mut self, reloc_mode: RelocMode) -> Self {
1453 unsafe { LLVMTargetMachineOptionsSetRelocMode(self.inner(), reloc_mode.into()) }
1454
1455 self
1456 }
1457
1458 pub fn set_code_model(mut self, code_model: CodeModel) -> Self {
1459 unsafe { LLVMTargetMachineOptionsSetCodeModel(self.inner(), code_model.into()) };
1460
1461 self
1462 }
1463
1464 fn into_target_machine(mut self, target: LLVMTargetRef, triple: &TargetTriple) -> Option<TargetMachine> {
1465 let target_machine = unsafe { LLVMCreateTargetMachineWithOptions(target, triple.as_ptr(), self.inner()) };
1466
1467 if target_machine.is_null() {
1468 return None;
1469 }
1470
1471 unsafe { Some(TargetMachine::new(target_machine)) }
1472 }
1473
1474 unsafe fn inner(&mut self) -> LLVMTargetMachineOptionsRef {
1480 *self.0.get_or_insert_with(|| LLVMCreateTargetMachineOptions())
1481 }
1482}
1483
1484#[llvm_versions(18..)]
1485impl Drop for TargetMachineOptions {
1486 fn drop(&mut self) {
1487 if let Some(inner) = self.0 {
1488 unsafe { LLVMDisposeTargetMachineOptions(inner) };
1489 }
1490 }
1491}