llvm_plugin_inkwell/
targets.rs

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};
8#[llvm_versions(4.0..=latest)]
9use llvm_sys::target_machine::LLVMCreateTargetDataLayout;
10use llvm_sys::target_machine::{
11    LLVMAddAnalysisPasses, LLVMCodeGenFileType, LLVMCodeGenOptLevel, LLVMCodeModel, LLVMCreateTargetMachine,
12    LLVMDisposeTargetMachine, LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMGetNextTarget,
13    LLVMGetTargetDescription, LLVMGetTargetFromName, LLVMGetTargetFromTriple, LLVMGetTargetMachineCPU,
14    LLVMGetTargetMachineFeatureString, LLVMGetTargetMachineTarget, LLVMGetTargetMachineTriple, LLVMGetTargetName,
15    LLVMRelocMode, LLVMSetTargetMachineAsmVerbosity, LLVMTargetHasAsmBackend, LLVMTargetHasJIT,
16    LLVMTargetHasTargetMachine, LLVMTargetMachineEmitToFile, LLVMTargetMachineEmitToMemoryBuffer, LLVMTargetMachineRef,
17    LLVMTargetRef,
18};
19use once_cell::sync::Lazy;
20use parking_lot::RwLock;
21
22use crate::context::AsContextRef;
23use crate::data_layout::DataLayout;
24use crate::memory_buffer::MemoryBuffer;
25use crate::module::Module;
26use crate::passes::PassManager;
27use crate::support::{to_c_str, LLVMString};
28use crate::types::{AnyType, AsTypeRef, IntType, StructType};
29use crate::values::{AsValueRef, GlobalValue};
30use crate::{AddressSpace, OptimizationLevel};
31
32use std::default::Default;
33use std::ffi::CStr;
34use std::fmt;
35use std::mem::MaybeUninit;
36use std::path::Path;
37use std::ptr;
38
39#[derive(Debug, PartialEq, Eq, Copy, Clone)]
40pub enum CodeModel {
41    Default,
42    JITDefault,
43    Small,
44    Kernel,
45    Medium,
46    Large,
47}
48
49#[derive(Debug, PartialEq, Eq, Copy, Clone)]
50pub enum RelocMode {
51    Default,
52    Static,
53    PIC,
54    DynamicNoPic,
55}
56
57#[derive(Debug, PartialEq, Eq, Copy, Clone)]
58pub enum FileType {
59    Assembly,
60    Object,
61}
62
63impl FileType {
64    fn as_llvm_file_type(&self) -> LLVMCodeGenFileType {
65        match *self {
66            FileType::Assembly => LLVMCodeGenFileType::LLVMAssemblyFile,
67            FileType::Object => LLVMCodeGenFileType::LLVMObjectFile,
68        }
69    }
70}
71
72// TODO: Doc: Base gets you TargetMachine support, machine_code gets you asm_backend
73#[derive(Copy, Clone, Debug, PartialEq, Eq)]
74pub struct InitializationConfig {
75    pub asm_parser: bool,
76    pub asm_printer: bool,
77    pub base: bool,
78    pub disassembler: bool,
79    pub info: bool,
80    pub machine_code: bool,
81}
82
83impl Default for InitializationConfig {
84    fn default() -> Self {
85        InitializationConfig {
86            asm_parser: true,
87            asm_printer: true,
88            base: true,
89            disassembler: true,
90            info: true,
91            machine_code: true,
92        }
93    }
94}
95
96#[derive(Eq)]
97pub struct TargetTriple {
98    pub(crate) triple: LLVMString,
99}
100
101impl TargetTriple {
102    pub unsafe fn new(triple: LLVMString) -> TargetTriple {
103        TargetTriple { triple }
104    }
105
106    pub fn create(triple: &str) -> TargetTriple {
107        let c_string = to_c_str(triple);
108
109        TargetTriple {
110            triple: LLVMString::create_from_c_str(&c_string),
111        }
112    }
113
114    pub fn as_str(&self) -> &CStr {
115        unsafe { CStr::from_ptr(self.as_ptr()) }
116    }
117
118    pub fn as_ptr(&self) -> *const ::libc::c_char {
119        self.triple.as_ptr()
120    }
121}
122
123impl PartialEq for TargetTriple {
124    fn eq(&self, other: &TargetTriple) -> bool {
125        self.triple == other.triple
126    }
127}
128
129impl fmt::Debug for TargetTriple {
130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        write!(f, "TargetTriple({:?})", self.triple)
132    }
133}
134
135impl fmt::Display for TargetTriple {
136    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
137        write!(f, "TargetTriple({:?})", self.triple)
138    }
139}
140
141static TARGET_LOCK: Lazy<RwLock<()>> = Lazy::new(|| RwLock::new(()));
142
143// NOTE: Versions verified as target-complete: 3.6, 3.7, 3.8, 3.9, 4.0
144#[derive(Debug, Eq, PartialEq)]
145pub struct Target {
146    target: LLVMTargetRef,
147}
148
149impl Target {
150    pub unsafe fn new(target: LLVMTargetRef) -> Self {
151        assert!(!target.is_null());
152
153        Target { target }
154    }
155
156    /// Acquires the underlying raw pointer belonging to this `Target` type.
157    pub fn as_mut_ptr(&self) -> LLVMTargetRef {
158        self.target
159    }
160
161    // REVIEW: Should this just initialize all? Is opt into each a good idea?
162    #[cfg(feature = "target-x86")]
163    pub fn initialize_x86(config: &InitializationConfig) {
164        use llvm_sys::target::{
165            LLVMInitializeX86AsmParser, LLVMInitializeX86AsmPrinter, LLVMInitializeX86Disassembler,
166            LLVMInitializeX86Target, LLVMInitializeX86TargetInfo, LLVMInitializeX86TargetMC,
167        };
168
169        if config.base {
170            let _guard = TARGET_LOCK.write();
171            unsafe { LLVMInitializeX86Target() };
172        }
173
174        if config.info {
175            let _guard = TARGET_LOCK.write();
176            unsafe { LLVMInitializeX86TargetInfo() };
177        }
178
179        if config.asm_printer {
180            let _guard = TARGET_LOCK.write();
181            unsafe { LLVMInitializeX86AsmPrinter() };
182        }
183
184        if config.asm_parser {
185            let _guard = TARGET_LOCK.write();
186            unsafe { LLVMInitializeX86AsmParser() };
187        }
188
189        if config.disassembler {
190            let _guard = TARGET_LOCK.write();
191            unsafe { LLVMInitializeX86Disassembler() };
192        }
193
194        if config.machine_code {
195            let _guard = TARGET_LOCK.write();
196            unsafe { LLVMInitializeX86TargetMC() };
197        }
198    }
199
200    #[cfg(feature = "target-arm")]
201    pub fn initialize_arm(config: &InitializationConfig) {
202        use llvm_sys::target::{
203            LLVMInitializeARMAsmParser, LLVMInitializeARMAsmPrinter, LLVMInitializeARMDisassembler,
204            LLVMInitializeARMTarget, LLVMInitializeARMTargetInfo, LLVMInitializeARMTargetMC,
205        };
206
207        if config.base {
208            let _guard = TARGET_LOCK.write();
209            unsafe { LLVMInitializeARMTarget() };
210        }
211
212        if config.info {
213            let _guard = TARGET_LOCK.write();
214            unsafe { LLVMInitializeARMTargetInfo() };
215        }
216
217        if config.asm_printer {
218            let _guard = TARGET_LOCK.write();
219            unsafe { LLVMInitializeARMAsmPrinter() };
220        }
221
222        if config.asm_parser {
223            let _guard = TARGET_LOCK.write();
224            unsafe { LLVMInitializeARMAsmParser() };
225        }
226
227        if config.disassembler {
228            let _guard = TARGET_LOCK.write();
229            unsafe { LLVMInitializeARMDisassembler() };
230        }
231
232        if config.machine_code {
233            let _guard = TARGET_LOCK.write();
234            unsafe { LLVMInitializeARMTargetMC() };
235        }
236    }
237
238    #[cfg(feature = "target-mips")]
239    pub fn initialize_mips(config: &InitializationConfig) {
240        use llvm_sys::target::{
241            LLVMInitializeMipsAsmParser, LLVMInitializeMipsAsmPrinter, LLVMInitializeMipsDisassembler,
242            LLVMInitializeMipsTarget, LLVMInitializeMipsTargetInfo, LLVMInitializeMipsTargetMC,
243        };
244
245        if config.base {
246            let _guard = TARGET_LOCK.write();
247            unsafe { LLVMInitializeMipsTarget() };
248        }
249
250        if config.info {
251            let _guard = TARGET_LOCK.write();
252            unsafe { LLVMInitializeMipsTargetInfo() };
253        }
254
255        if config.asm_printer {
256            let _guard = TARGET_LOCK.write();
257            unsafe { LLVMInitializeMipsAsmPrinter() };
258        }
259
260        if config.asm_parser {
261            let _guard = TARGET_LOCK.write();
262            unsafe { LLVMInitializeMipsAsmParser() };
263        }
264
265        if config.disassembler {
266            let _guard = TARGET_LOCK.write();
267            unsafe { LLVMInitializeMipsDisassembler() };
268        }
269
270        if config.machine_code {
271            let _guard = TARGET_LOCK.write();
272            unsafe { LLVMInitializeMipsTargetMC() };
273        }
274    }
275
276    #[cfg(feature = "target-aarch64")]
277    pub fn initialize_aarch64(config: &InitializationConfig) {
278        use llvm_sys::target::{
279            LLVMInitializeAArch64AsmParser, LLVMInitializeAArch64AsmPrinter, LLVMInitializeAArch64Disassembler,
280            LLVMInitializeAArch64Target, LLVMInitializeAArch64TargetInfo, LLVMInitializeAArch64TargetMC,
281        };
282
283        if config.base {
284            let _guard = TARGET_LOCK.write();
285            unsafe { LLVMInitializeAArch64Target() };
286        }
287
288        if config.info {
289            let _guard = TARGET_LOCK.write();
290            unsafe { LLVMInitializeAArch64TargetInfo() };
291        }
292
293        if config.asm_printer {
294            let _guard = TARGET_LOCK.write();
295            unsafe { LLVMInitializeAArch64AsmPrinter() };
296        }
297
298        if config.asm_parser {
299            let _guard = TARGET_LOCK.write();
300            unsafe { LLVMInitializeAArch64AsmParser() };
301        }
302
303        if config.disassembler {
304            let _guard = TARGET_LOCK.write();
305            unsafe { LLVMInitializeAArch64Disassembler() };
306        }
307
308        if config.machine_code {
309            let _guard = TARGET_LOCK.write();
310            unsafe { LLVMInitializeAArch64TargetMC() };
311        }
312    }
313
314    #[cfg(feature = "target-amdgpu")]
315    #[llvm_versions(4.0..=latest)]
316    pub fn initialize_amd_gpu(config: &InitializationConfig) {
317        use llvm_sys::target::{
318            LLVMInitializeAMDGPUAsmParser, LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeAMDGPUTarget,
319            LLVMInitializeAMDGPUTargetInfo, LLVMInitializeAMDGPUTargetMC,
320        };
321
322        if config.base {
323            let _guard = TARGET_LOCK.write();
324            unsafe { LLVMInitializeAMDGPUTarget() };
325        }
326
327        if config.info {
328            let _guard = TARGET_LOCK.write();
329            unsafe { LLVMInitializeAMDGPUTargetInfo() };
330        }
331
332        if config.asm_printer {
333            let _guard = TARGET_LOCK.write();
334            unsafe { LLVMInitializeAMDGPUAsmPrinter() };
335        }
336
337        if config.asm_parser {
338            let _guard = TARGET_LOCK.write();
339            unsafe { LLVMInitializeAMDGPUAsmParser() };
340        }
341
342        if config.machine_code {
343            let _guard = TARGET_LOCK.write();
344            unsafe { LLVMInitializeAMDGPUTargetMC() };
345        }
346
347        // Disassembler Status Unknown
348    }
349
350    #[cfg(feature = "target-systemz")]
351    pub fn initialize_system_z(config: &InitializationConfig) {
352        use llvm_sys::target::{
353            LLVMInitializeSystemZAsmParser, LLVMInitializeSystemZAsmPrinter, LLVMInitializeSystemZDisassembler,
354            LLVMInitializeSystemZTarget, LLVMInitializeSystemZTargetInfo, LLVMInitializeSystemZTargetMC,
355        };
356
357        if config.base {
358            let _guard = TARGET_LOCK.write();
359            unsafe { LLVMInitializeSystemZTarget() };
360        }
361
362        if config.info {
363            let _guard = TARGET_LOCK.write();
364            unsafe { LLVMInitializeSystemZTargetInfo() };
365        }
366
367        if config.asm_printer {
368            let _guard = TARGET_LOCK.write();
369            unsafe { LLVMInitializeSystemZAsmPrinter() };
370        }
371
372        if config.asm_parser {
373            let _guard = TARGET_LOCK.write();
374            unsafe { LLVMInitializeSystemZAsmParser() };
375        }
376
377        if config.disassembler {
378            let _guard = TARGET_LOCK.write();
379            unsafe { LLVMInitializeSystemZDisassembler() };
380        }
381
382        if config.machine_code {
383            let _guard = TARGET_LOCK.write();
384            unsafe { LLVMInitializeSystemZTargetMC() };
385        }
386    }
387
388    #[cfg(feature = "target-hexagon")]
389    pub fn initialize_hexagon(config: &InitializationConfig) {
390        use llvm_sys::target::{
391            LLVMInitializeHexagonAsmPrinter, LLVMInitializeHexagonDisassembler, LLVMInitializeHexagonTarget,
392            LLVMInitializeHexagonTargetInfo, LLVMInitializeHexagonTargetMC,
393        };
394
395        if config.base {
396            let _guard = TARGET_LOCK.write();
397            unsafe { LLVMInitializeHexagonTarget() };
398        }
399
400        if config.info {
401            let _guard = TARGET_LOCK.write();
402            unsafe { LLVMInitializeHexagonTargetInfo() };
403        }
404
405        if config.asm_printer {
406            let _guard = TARGET_LOCK.write();
407            unsafe { LLVMInitializeHexagonAsmPrinter() };
408        }
409
410        // Asm parser status unknown
411
412        if config.disassembler {
413            let _guard = TARGET_LOCK.write();
414            unsafe { LLVMInitializeHexagonDisassembler() };
415        }
416
417        if config.machine_code {
418            let _guard = TARGET_LOCK.write();
419            unsafe { LLVMInitializeHexagonTargetMC() };
420        }
421    }
422
423    #[cfg(feature = "target-nvptx")]
424    pub fn initialize_nvptx(config: &InitializationConfig) {
425        use llvm_sys::target::{
426            LLVMInitializeNVPTXAsmPrinter, LLVMInitializeNVPTXTarget, LLVMInitializeNVPTXTargetInfo,
427            LLVMInitializeNVPTXTargetMC,
428        };
429
430        if config.base {
431            let _guard = TARGET_LOCK.write();
432            unsafe { LLVMInitializeNVPTXTarget() };
433        }
434
435        if config.info {
436            let _guard = TARGET_LOCK.write();
437            unsafe { LLVMInitializeNVPTXTargetInfo() };
438        }
439
440        if config.asm_printer {
441            let _guard = TARGET_LOCK.write();
442            unsafe { LLVMInitializeNVPTXAsmPrinter() };
443        }
444
445        // Asm parser status unknown
446
447        if config.machine_code {
448            let _guard = TARGET_LOCK.write();
449            unsafe { LLVMInitializeNVPTXTargetMC() };
450        }
451
452        // Disassembler status unknown
453    }
454
455    #[cfg(feature = "target-msp430")]
456    pub fn initialize_msp430(config: &InitializationConfig) {
457        use llvm_sys::target::{
458            LLVMInitializeMSP430AsmPrinter, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetInfo,
459            LLVMInitializeMSP430TargetMC,
460        };
461
462        if config.base {
463            let _guard = TARGET_LOCK.write();
464            unsafe { LLVMInitializeMSP430Target() };
465        }
466
467        if config.info {
468            let _guard = TARGET_LOCK.write();
469            unsafe { LLVMInitializeMSP430TargetInfo() };
470        }
471
472        if config.asm_printer {
473            let _guard = TARGET_LOCK.write();
474            unsafe { LLVMInitializeMSP430AsmPrinter() };
475        }
476
477        // Asm parser status unknown
478
479        if config.machine_code {
480            let _guard = TARGET_LOCK.write();
481            unsafe { LLVMInitializeMSP430TargetMC() };
482        }
483
484        // Disassembler status unknown
485    }
486
487    #[cfg(feature = "target-xcore")]
488    pub fn initialize_x_core(config: &InitializationConfig) {
489        use llvm_sys::target::{
490            LLVMInitializeXCoreAsmPrinter, LLVMInitializeXCoreDisassembler, LLVMInitializeXCoreTarget,
491            LLVMInitializeXCoreTargetInfo, LLVMInitializeXCoreTargetMC,
492        };
493
494        if config.base {
495            let _guard = TARGET_LOCK.write();
496            unsafe { LLVMInitializeXCoreTarget() };
497        }
498
499        if config.info {
500            let _guard = TARGET_LOCK.write();
501            unsafe { LLVMInitializeXCoreTargetInfo() };
502        }
503
504        if config.asm_printer {
505            let _guard = TARGET_LOCK.write();
506            unsafe { LLVMInitializeXCoreAsmPrinter() };
507        }
508
509        // Asm parser status unknown
510
511        if config.disassembler {
512            let _guard = TARGET_LOCK.write();
513            unsafe { LLVMInitializeXCoreDisassembler() };
514        }
515
516        if config.machine_code {
517            let _guard = TARGET_LOCK.write();
518            unsafe { LLVMInitializeXCoreTargetMC() };
519        }
520    }
521
522    #[cfg(feature = "target-powerpc")]
523    pub fn initialize_power_pc(config: &InitializationConfig) {
524        use llvm_sys::target::{
525            LLVMInitializePowerPCAsmParser, LLVMInitializePowerPCAsmPrinter, LLVMInitializePowerPCDisassembler,
526            LLVMInitializePowerPCTarget, LLVMInitializePowerPCTargetInfo, LLVMInitializePowerPCTargetMC,
527        };
528
529        if config.base {
530            let _guard = TARGET_LOCK.write();
531            unsafe { LLVMInitializePowerPCTarget() };
532        }
533
534        if config.info {
535            let _guard = TARGET_LOCK.write();
536            unsafe { LLVMInitializePowerPCTargetInfo() };
537        }
538
539        if config.asm_printer {
540            let _guard = TARGET_LOCK.write();
541            unsafe { LLVMInitializePowerPCAsmPrinter() };
542        }
543
544        if config.asm_parser {
545            let _guard = TARGET_LOCK.write();
546            unsafe { LLVMInitializePowerPCAsmParser() };
547        }
548
549        if config.disassembler {
550            let _guard = TARGET_LOCK.write();
551            unsafe { LLVMInitializePowerPCDisassembler() };
552        }
553
554        if config.machine_code {
555            let _guard = TARGET_LOCK.write();
556            unsafe { LLVMInitializePowerPCTargetMC() };
557        }
558    }
559
560    #[cfg(feature = "target-sparc")]
561    pub fn initialize_sparc(config: &InitializationConfig) {
562        use llvm_sys::target::{
563            LLVMInitializeSparcAsmParser, LLVMInitializeSparcAsmPrinter, LLVMInitializeSparcDisassembler,
564            LLVMInitializeSparcTarget, LLVMInitializeSparcTargetInfo, LLVMInitializeSparcTargetMC,
565        };
566
567        if config.base {
568            let _guard = TARGET_LOCK.write();
569            unsafe { LLVMInitializeSparcTarget() };
570        }
571
572        if config.info {
573            let _guard = TARGET_LOCK.write();
574            unsafe { LLVMInitializeSparcTargetInfo() };
575        }
576
577        if config.asm_printer {
578            let _guard = TARGET_LOCK.write();
579            unsafe { LLVMInitializeSparcAsmPrinter() };
580        }
581
582        if config.asm_parser {
583            let _guard = TARGET_LOCK.write();
584            unsafe { LLVMInitializeSparcAsmParser() };
585        }
586
587        if config.disassembler {
588            let _guard = TARGET_LOCK.write();
589            unsafe { LLVMInitializeSparcDisassembler() };
590        }
591
592        if config.machine_code {
593            let _guard = TARGET_LOCK.write();
594            unsafe { LLVMInitializeSparcTargetMC() };
595        }
596    }
597
598    #[cfg(feature = "target-bpf")]
599    pub fn initialize_bpf(config: &InitializationConfig) {
600        use llvm_sys::target::{
601            LLVMInitializeBPFAsmPrinter, LLVMInitializeBPFTarget, LLVMInitializeBPFTargetInfo,
602            LLVMInitializeBPFTargetMC,
603        };
604
605        if config.base {
606            let _guard = TARGET_LOCK.write();
607            unsafe { LLVMInitializeBPFTarget() };
608        }
609
610        if config.info {
611            let _guard = TARGET_LOCK.write();
612            unsafe { LLVMInitializeBPFTargetInfo() };
613        }
614
615        if config.asm_printer {
616            let _guard = TARGET_LOCK.write();
617            unsafe { LLVMInitializeBPFAsmPrinter() };
618        }
619
620        // No asm parser
621
622        if config.disassembler {
623            use llvm_sys::target::LLVMInitializeBPFDisassembler;
624
625            let _guard = TARGET_LOCK.write();
626            unsafe { LLVMInitializeBPFDisassembler() };
627        }
628
629        if config.machine_code {
630            let _guard = TARGET_LOCK.write();
631            unsafe { LLVMInitializeBPFTargetMC() };
632        }
633    }
634
635    #[cfg(feature = "target-lanai")]
636    #[llvm_versions(4.0..=latest)]
637    pub fn initialize_lanai(config: &InitializationConfig) {
638        use llvm_sys::target::{
639            LLVMInitializeLanaiAsmParser, LLVMInitializeLanaiAsmPrinter, LLVMInitializeLanaiDisassembler,
640            LLVMInitializeLanaiTarget, LLVMInitializeLanaiTargetInfo, LLVMInitializeLanaiTargetMC,
641        };
642
643        if config.base {
644            let _guard = TARGET_LOCK.write();
645            unsafe { LLVMInitializeLanaiTarget() };
646        }
647
648        if config.info {
649            let _guard = TARGET_LOCK.write();
650            unsafe { LLVMInitializeLanaiTargetInfo() };
651        }
652
653        if config.asm_printer {
654            let _guard = TARGET_LOCK.write();
655            unsafe { LLVMInitializeLanaiAsmPrinter() };
656        }
657
658        if config.asm_parser {
659            let _guard = TARGET_LOCK.write();
660            unsafe { LLVMInitializeLanaiAsmParser() };
661        }
662
663        if config.disassembler {
664            let _guard = TARGET_LOCK.write();
665            unsafe { LLVMInitializeLanaiDisassembler() };
666        }
667
668        if config.machine_code {
669            let _guard = TARGET_LOCK.write();
670            unsafe { LLVMInitializeLanaiTargetMC() };
671        }
672    }
673
674    // RISCV was accidentally built by default in 4.0 since it was meant to be marked
675    // experimental and so it was later removed from default builds in 5.0 until it was
676    // officially released in 9.0 Since llvm-sys doesn't officially support any experimental
677    // targets we're going to make this 9.0+ only. See
678    // https://lists.llvm.org/pipermail/llvm-dev/2017-August/116347.html for more info.
679    #[cfg(feature = "target-riscv")]
680    #[llvm_versions(9.0..=latest)]
681    pub fn initialize_riscv(config: &InitializationConfig) {
682        use llvm_sys::target::{
683            LLVMInitializeRISCVAsmParser, LLVMInitializeRISCVAsmPrinter, LLVMInitializeRISCVDisassembler,
684            LLVMInitializeRISCVTarget, LLVMInitializeRISCVTargetInfo, LLVMInitializeRISCVTargetMC,
685        };
686
687        if config.base {
688            let _guard = TARGET_LOCK.write();
689            unsafe { LLVMInitializeRISCVTarget() };
690        }
691
692        if config.info {
693            let _guard = TARGET_LOCK.write();
694            unsafe { LLVMInitializeRISCVTargetInfo() };
695        }
696
697        if config.asm_printer {
698            let _guard = TARGET_LOCK.write();
699            unsafe { LLVMInitializeRISCVAsmPrinter() };
700        }
701
702        if config.asm_parser {
703            let _guard = TARGET_LOCK.write();
704            unsafe { LLVMInitializeRISCVAsmParser() };
705        }
706
707        if config.disassembler {
708            let _guard = TARGET_LOCK.write();
709            unsafe { LLVMInitializeRISCVDisassembler() };
710        }
711
712        if config.machine_code {
713            let _guard = TARGET_LOCK.write();
714            unsafe { LLVMInitializeRISCVTargetMC() };
715        }
716    }
717
718    #[cfg(feature = "target-webassembly")]
719    #[llvm_versions(8.0..=latest)]
720    pub fn initialize_webassembly(config: &InitializationConfig) {
721        use llvm_sys::target::{
722            LLVMInitializeWebAssemblyAsmParser, LLVMInitializeWebAssemblyAsmPrinter,
723            LLVMInitializeWebAssemblyDisassembler, LLVMInitializeWebAssemblyTarget,
724            LLVMInitializeWebAssemblyTargetInfo, LLVMInitializeWebAssemblyTargetMC,
725        };
726
727        if config.base {
728            let _guard = TARGET_LOCK.write();
729            unsafe { LLVMInitializeWebAssemblyTarget() };
730        }
731
732        if config.info {
733            let _guard = TARGET_LOCK.write();
734            unsafe { LLVMInitializeWebAssemblyTargetInfo() };
735        }
736
737        if config.asm_printer {
738            let _guard = TARGET_LOCK.write();
739            unsafe { LLVMInitializeWebAssemblyAsmPrinter() };
740        }
741
742        if config.asm_parser {
743            let _guard = TARGET_LOCK.write();
744            unsafe { LLVMInitializeWebAssemblyAsmParser() };
745        }
746
747        if config.disassembler {
748            let _guard = TARGET_LOCK.write();
749            unsafe { LLVMInitializeWebAssemblyDisassembler() };
750        }
751
752        if config.machine_code {
753            let _guard = TARGET_LOCK.write();
754            unsafe { LLVMInitializeWebAssemblyTargetMC() };
755        }
756    }
757
758    pub fn initialize_native(config: &InitializationConfig) -> Result<(), String> {
759        use llvm_sys::target::{
760            LLVM_InitializeNativeAsmParser, LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeDisassembler,
761            LLVM_InitializeNativeTarget,
762        };
763
764        if config.base {
765            let _guard = TARGET_LOCK.write();
766            let code = unsafe { LLVM_InitializeNativeTarget() };
767
768            if code == 1 {
769                return Err("Unknown error in initializing native target".into());
770            }
771        }
772
773        if config.asm_printer {
774            let _guard = TARGET_LOCK.write();
775            let code = unsafe { LLVM_InitializeNativeAsmPrinter() };
776
777            if code == 1 {
778                return Err("Unknown error in initializing native asm printer".into());
779            }
780        }
781
782        if config.asm_parser {
783            let _guard = TARGET_LOCK.write();
784            let code = unsafe { LLVM_InitializeNativeAsmParser() };
785
786            if code == 1 {
787                // REVIEW: Does parser need to go before printer?
788                return Err("Unknown error in initializing native asm parser".into());
789            }
790        }
791
792        if config.disassembler {
793            let _guard = TARGET_LOCK.write();
794            let code = unsafe { LLVM_InitializeNativeDisassembler() };
795
796            if code == 1 {
797                return Err("Unknown error in initializing native disassembler".into());
798            }
799        }
800
801        Ok(())
802    }
803
804    pub fn initialize_all(config: &InitializationConfig) {
805        use llvm_sys::target::{
806            LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllDisassemblers,
807            LLVM_InitializeAllTargetInfos, LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets,
808        };
809
810        if config.base {
811            let _guard = TARGET_LOCK.write();
812            unsafe { LLVM_InitializeAllTargets() };
813        }
814
815        if config.info {
816            let _guard = TARGET_LOCK.write();
817            unsafe { LLVM_InitializeAllTargetInfos() };
818        }
819
820        if config.asm_parser {
821            let _guard = TARGET_LOCK.write();
822            unsafe { LLVM_InitializeAllAsmParsers() };
823        }
824
825        if config.asm_printer {
826            let _guard = TARGET_LOCK.write();
827            unsafe { LLVM_InitializeAllAsmPrinters() };
828        }
829
830        if config.disassembler {
831            let _guard = TARGET_LOCK.write();
832            unsafe { LLVM_InitializeAllDisassemblers() };
833        }
834
835        if config.machine_code {
836            let _guard = TARGET_LOCK.write();
837            unsafe { LLVM_InitializeAllTargetMCs() };
838        }
839    }
840
841    pub fn create_target_machine(
842        &self,
843        triple: &TargetTriple,
844        cpu: &str,
845        features: &str,
846        level: OptimizationLevel,
847        reloc_mode: RelocMode,
848        code_model: CodeModel,
849    ) -> Option<TargetMachine> {
850        let cpu = to_c_str(cpu);
851        let features = to_c_str(features);
852        let level = match level {
853            OptimizationLevel::None => LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
854            OptimizationLevel::Less => LLVMCodeGenOptLevel::LLVMCodeGenLevelLess,
855            OptimizationLevel::Default => LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
856            OptimizationLevel::Aggressive => LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive,
857        };
858        let code_model = match code_model {
859            CodeModel::Default => LLVMCodeModel::LLVMCodeModelDefault,
860            CodeModel::JITDefault => LLVMCodeModel::LLVMCodeModelJITDefault,
861            CodeModel::Small => LLVMCodeModel::LLVMCodeModelSmall,
862            CodeModel::Kernel => LLVMCodeModel::LLVMCodeModelKernel,
863            CodeModel::Medium => LLVMCodeModel::LLVMCodeModelMedium,
864            CodeModel::Large => LLVMCodeModel::LLVMCodeModelLarge,
865        };
866        let reloc_mode = match reloc_mode {
867            RelocMode::Default => LLVMRelocMode::LLVMRelocDefault,
868            RelocMode::Static => LLVMRelocMode::LLVMRelocStatic,
869            RelocMode::PIC => LLVMRelocMode::LLVMRelocPIC,
870            RelocMode::DynamicNoPic => LLVMRelocMode::LLVMRelocDynamicNoPic,
871        };
872        let target_machine = unsafe {
873            LLVMCreateTargetMachine(
874                self.target,
875                triple.as_ptr(),
876                cpu.as_ptr(),
877                features.as_ptr(),
878                level,
879                reloc_mode,
880                code_model,
881            )
882        };
883
884        if target_machine.is_null() {
885            return None;
886        }
887
888        unsafe { Some(TargetMachine::new(target_machine)) }
889    }
890
891    pub fn get_first() -> Option<Self> {
892        let target = {
893            let _guard = TARGET_LOCK.read();
894            unsafe { LLVMGetFirstTarget() }
895        };
896
897        if target.is_null() {
898            return None;
899        }
900
901        unsafe { Some(Target::new(target)) }
902    }
903
904    pub fn get_next(&self) -> Option<Self> {
905        let target = unsafe { LLVMGetNextTarget(self.target) };
906
907        if target.is_null() {
908            return None;
909        }
910
911        unsafe { Some(Target::new(target)) }
912    }
913
914    pub fn get_name(&self) -> &CStr {
915        unsafe { CStr::from_ptr(LLVMGetTargetName(self.target)) }
916    }
917
918    pub fn get_description(&self) -> &CStr {
919        unsafe { CStr::from_ptr(LLVMGetTargetDescription(self.target)) }
920    }
921
922    pub fn from_name(name: &str) -> Option<Self> {
923        let c_string = to_c_str(name);
924
925        Self::from_name_raw(c_string.as_ptr())
926    }
927
928    pub(crate) fn from_name_raw(c_string: *const ::libc::c_char) -> Option<Self> {
929        let target = {
930            let _guard = TARGET_LOCK.read();
931            unsafe { LLVMGetTargetFromName(c_string) }
932        };
933
934        if target.is_null() {
935            return None;
936        }
937
938        unsafe { Some(Target::new(target)) }
939    }
940
941    pub fn from_triple(triple: &TargetTriple) -> Result<Self, LLVMString> {
942        let mut target = ptr::null_mut();
943        let mut err_string = MaybeUninit::uninit();
944
945        let code = {
946            let _guard = TARGET_LOCK.read();
947            unsafe { LLVMGetTargetFromTriple(triple.as_ptr(), &mut target, err_string.as_mut_ptr()) }
948        };
949
950        if code == 1 {
951            unsafe {
952                return Err(LLVMString::new(err_string.assume_init()));
953            }
954        }
955
956        unsafe { Ok(Target::new(target)) }
957    }
958
959    pub fn has_jit(&self) -> bool {
960        unsafe { LLVMTargetHasJIT(self.target) == 1 }
961    }
962
963    pub fn has_target_machine(&self) -> bool {
964        unsafe { LLVMTargetHasTargetMachine(self.target) == 1 }
965    }
966
967    pub fn has_asm_backend(&self) -> bool {
968        unsafe { LLVMTargetHasAsmBackend(self.target) == 1 }
969    }
970}
971
972#[derive(Debug)]
973pub struct TargetMachine {
974    pub(crate) target_machine: LLVMTargetMachineRef,
975}
976
977impl TargetMachine {
978    pub unsafe fn new(target_machine: LLVMTargetMachineRef) -> Self {
979        assert!(!target_machine.is_null());
980
981        TargetMachine { target_machine }
982    }
983
984    /// Acquires the underlying raw pointer belonging to this `TargetMachine` type.
985    pub fn as_mut_ptr(&self) -> LLVMTargetMachineRef {
986        self.target_machine
987    }
988
989    pub fn get_target(&self) -> Target {
990        unsafe { Target::new(LLVMGetTargetMachineTarget(self.target_machine)) }
991    }
992
993    pub fn get_triple(&self) -> TargetTriple {
994        let str = unsafe { LLVMString::new(LLVMGetTargetMachineTriple(self.target_machine)) };
995
996        unsafe { TargetTriple::new(str) }
997    }
998
999    /// Gets the default triple for the current system.
1000    ///
1001    /// # Example
1002    ///
1003    /// ```no_run
1004    /// use inkwell::targets::TargetMachine;
1005    ///
1006    /// let default_triple = TargetMachine::get_default_triple();
1007    ///
1008    /// assert_eq!(default_triple.as_str().to_str(), Ok("x86_64-pc-linux-gnu"));
1009    /// ```
1010    pub fn get_default_triple() -> TargetTriple {
1011        let llvm_string = unsafe { LLVMString::new(LLVMGetDefaultTargetTriple()) };
1012
1013        unsafe { TargetTriple::new(llvm_string) }
1014    }
1015
1016    #[llvm_versions(7.0..=latest)]
1017    pub fn normalize_triple(triple: &TargetTriple) -> TargetTriple {
1018        use llvm_sys::target_machine::LLVMNormalizeTargetTriple;
1019
1020        let normalized = unsafe { LLVMString::new(LLVMNormalizeTargetTriple(triple.as_ptr())) };
1021
1022        unsafe { TargetTriple::new(normalized) }
1023    }
1024
1025    /// Gets a string containing the host CPU's name (triple).
1026    ///
1027    /// # Example Output
1028    ///
1029    /// `x86_64-pc-linux-gnu`
1030    #[llvm_versions(7.0..=latest)]
1031    pub fn get_host_cpu_name() -> LLVMString {
1032        use llvm_sys::target_machine::LLVMGetHostCPUName;
1033
1034        unsafe { LLVMString::new(LLVMGetHostCPUName()) }
1035    }
1036
1037    /// Gets a comma separated list of supported features by the host CPU.
1038    ///
1039    /// # Example Output
1040    ///
1041    /// `+sse2,+cx16,+sahf,-tbm`
1042    #[llvm_versions(7.0..=latest)]
1043    pub fn get_host_cpu_features() -> LLVMString {
1044        use llvm_sys::target_machine::LLVMGetHostCPUFeatures;
1045
1046        unsafe { LLVMString::new(LLVMGetHostCPUFeatures()) }
1047    }
1048
1049    pub fn get_cpu(&self) -> LLVMString {
1050        unsafe { LLVMString::new(LLVMGetTargetMachineCPU(self.target_machine)) }
1051    }
1052
1053    pub fn get_feature_string(&self) -> &CStr {
1054        unsafe { CStr::from_ptr(LLVMGetTargetMachineFeatureString(self.target_machine)) }
1055    }
1056
1057    /// Create TargetData from this target machine
1058    #[llvm_versions(4.0..=latest)]
1059    pub fn get_target_data(&self) -> TargetData {
1060        unsafe { TargetData::new(LLVMCreateTargetDataLayout(self.target_machine)) }
1061    }
1062
1063    pub fn set_asm_verbosity(&self, verbosity: bool) {
1064        unsafe { LLVMSetTargetMachineAsmVerbosity(self.target_machine, verbosity as i32) }
1065    }
1066
1067    // TODO: Move to PassManager?
1068    pub fn add_analysis_passes<T>(&self, pass_manager: &PassManager<T>) {
1069        unsafe { LLVMAddAnalysisPasses(self.target_machine, pass_manager.pass_manager) }
1070    }
1071
1072    /// Writes a `TargetMachine` to a `MemoryBuffer`.
1073    ///
1074    /// # Example
1075    ///
1076    /// ```no_run
1077    /// use inkwell::OptimizationLevel;
1078    /// use inkwell::context::Context;
1079    /// use inkwell::targets::{CodeModel, RelocMode, FileType, Target, TargetMachine, TargetTriple, InitializationConfig};
1080    ///
1081    /// Target::initialize_x86(&InitializationConfig::default());
1082    ///
1083    /// let opt = OptimizationLevel::Default;
1084    /// let reloc = RelocMode::Default;
1085    /// let model = CodeModel::Default;
1086    /// let target = Target::from_name("x86-64").unwrap();
1087    /// let target_machine = target.create_target_machine(
1088    ///     &TargetTriple::create("x86_64-pc-linux-gnu"),
1089    ///     "x86-64",
1090    ///     "+avx2",
1091    ///     opt,
1092    ///     reloc,
1093    ///     model
1094    /// )
1095    /// .unwrap();
1096    ///
1097    /// let context = Context::create();
1098    /// let module = context.create_module("my_module");
1099    /// let void_type = context.void_type();
1100    /// let fn_type = void_type.fn_type(&[], false);
1101    ///
1102    /// module.add_function("my_fn", fn_type, None);
1103    ///
1104    /// let buffer = target_machine.write_to_memory_buffer(&module, FileType::Assembly).unwrap();
1105    /// ```
1106    pub fn write_to_memory_buffer(&self, module: &Module, file_type: FileType) -> Result<MemoryBuffer, LLVMString> {
1107        let mut memory_buffer = ptr::null_mut();
1108        let mut err_string = MaybeUninit::uninit();
1109        let return_code = unsafe {
1110            let module_ptr = module.module.get();
1111            let file_type_ptr = file_type.as_llvm_file_type();
1112
1113            LLVMTargetMachineEmitToMemoryBuffer(
1114                self.target_machine,
1115                module_ptr,
1116                file_type_ptr,
1117                err_string.as_mut_ptr(),
1118                &mut memory_buffer,
1119            )
1120        };
1121
1122        if return_code == 1 {
1123            unsafe {
1124                return Err(LLVMString::new(err_string.assume_init()));
1125            }
1126        }
1127
1128        unsafe { Ok(MemoryBuffer::new(memory_buffer)) }
1129    }
1130
1131    /// Saves a `TargetMachine` to a file.
1132    ///
1133    /// # Example
1134    ///
1135    /// ```no_run
1136    /// use inkwell::OptimizationLevel;
1137    /// use inkwell::context::Context;
1138    /// use inkwell::targets::{CodeModel, RelocMode, FileType, Target, TargetMachine, TargetTriple, InitializationConfig};
1139    ///
1140    /// use std::path::Path;
1141    ///
1142    /// Target::initialize_x86(&InitializationConfig::default());
1143    ///
1144    /// let opt = OptimizationLevel::Default;
1145    /// let reloc = RelocMode::Default;
1146    /// let model = CodeModel::Default;
1147    /// let path = Path::new("/tmp/some/path/main.asm");
1148    /// let target = Target::from_name("x86-64").unwrap();
1149    /// let target_machine = target.create_target_machine(
1150    ///     &TargetTriple::create("x86_64-pc-linux-gnu"),
1151    ///     "x86-64",
1152    ///     "+avx2",
1153    ///     opt,
1154    ///     reloc,
1155    ///     model
1156    /// )
1157    /// .unwrap();
1158    ///
1159    /// let context = Context::create();
1160    /// let module = context.create_module("my_module");
1161    /// let void_type = context.void_type();
1162    /// let fn_type = void_type.fn_type(&[], false);
1163    ///
1164    /// module.add_function("my_fn", fn_type, None);
1165    ///
1166    /// assert!(target_machine.write_to_file(&module, FileType::Object, &path).is_ok());
1167    /// ```
1168    pub fn write_to_file(&self, module: &Module, file_type: FileType, path: &Path) -> Result<(), LLVMString> {
1169        let path = path.to_str().expect("Did not find a valid Unicode path string");
1170        let path_c_string = to_c_str(path);
1171        let mut err_string = MaybeUninit::uninit();
1172        let return_code = unsafe {
1173            // REVIEW: Why does LLVM need a mutable ptr to path...?
1174            let module_ptr = module.module.get();
1175            let path_ptr = path_c_string.as_ptr() as *mut _;
1176            let file_type_ptr = file_type.as_llvm_file_type();
1177
1178            LLVMTargetMachineEmitToFile(
1179                self.target_machine,
1180                module_ptr,
1181                path_ptr,
1182                file_type_ptr,
1183                err_string.as_mut_ptr(),
1184            )
1185        };
1186
1187        if return_code == 1 {
1188            unsafe {
1189                return Err(LLVMString::new(err_string.assume_init()));
1190            }
1191        }
1192
1193        Ok(())
1194    }
1195}
1196
1197impl Drop for TargetMachine {
1198    fn drop(&mut self) {
1199        unsafe { LLVMDisposeTargetMachine(self.target_machine) }
1200    }
1201}
1202
1203#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1204pub enum ByteOrdering {
1205    BigEndian,
1206    LittleEndian,
1207}
1208
1209#[derive(PartialEq, Eq, Debug)]
1210pub struct TargetData {
1211    pub(crate) target_data: LLVMTargetDataRef,
1212}
1213
1214impl TargetData {
1215    pub unsafe fn new(target_data: LLVMTargetDataRef) -> TargetData {
1216        assert!(!target_data.is_null());
1217
1218        TargetData { target_data }
1219    }
1220
1221    /// Acquires the underlying raw pointer belonging to this `TargetData` type.
1222    pub fn as_mut_ptr(&self) -> LLVMTargetDataRef {
1223        self.target_data
1224    }
1225
1226    /// Gets the `IntType` representing a bit width of a pointer. It will be assigned the referenced context.
1227    ///
1228    /// # Example
1229    ///
1230    /// ```no_run
1231    /// use inkwell::OptimizationLevel;
1232    /// use inkwell::context::Context;
1233    /// use inkwell::targets::{InitializationConfig, Target};
1234    ///
1235    /// Target::initialize_native(&InitializationConfig::default()).expect("Failed to initialize native target");
1236    ///
1237    /// let context = Context::create();
1238    /// let module = context.create_module("sum");
1239    /// let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
1240    /// let target_data = execution_engine.get_target_data();
1241    /// let int_type = target_data.ptr_sized_int_type_in_context(&context, None);
1242    /// ```
1243    #[deprecated(note = "This method will be removed in the future. Please use Context::ptr_sized_int_type instead.")]
1244    pub fn ptr_sized_int_type_in_context<'ctx>(
1245        &self,
1246        context: impl AsContextRef<'ctx>,
1247        address_space: Option<AddressSpace>,
1248    ) -> IntType<'ctx> {
1249        let int_type_ptr = match address_space {
1250            Some(address_space) => unsafe {
1251                LLVMIntPtrTypeForASInContext(context.as_ctx_ref(), self.target_data, address_space.0)
1252            },
1253            None => unsafe { LLVMIntPtrTypeInContext(context.as_ctx_ref(), self.target_data) },
1254        };
1255
1256        unsafe { IntType::new(int_type_ptr) }
1257    }
1258
1259    pub fn get_data_layout(&self) -> DataLayout {
1260        unsafe { DataLayout::new_owned(LLVMCopyStringRepOfTargetData(self.target_data)) }
1261    }
1262
1263    // REVIEW: Does this only work if Sized?
1264    pub fn get_bit_size(&self, type_: &dyn AnyType) -> u64 {
1265        unsafe { LLVMSizeOfTypeInBits(self.target_data, type_.as_type_ref()) }
1266    }
1267
1268    // TODOC: This can fail on LLVM's side(exit?), but it doesn't seem like we have any way to check this in rust
1269    pub fn create(str_repr: &str) -> TargetData {
1270        let c_string = to_c_str(str_repr);
1271
1272        unsafe { TargetData::new(LLVMCreateTargetData(c_string.as_ptr())) }
1273    }
1274
1275    pub fn get_byte_ordering(&self) -> ByteOrdering {
1276        let byte_ordering = unsafe { LLVMByteOrder(self.target_data) };
1277
1278        match byte_ordering {
1279            LLVMByteOrdering::LLVMBigEndian => ByteOrdering::BigEndian,
1280            LLVMByteOrdering::LLVMLittleEndian => ByteOrdering::LittleEndian,
1281        }
1282    }
1283
1284    pub fn get_pointer_byte_size(&self, address_space: Option<AddressSpace>) -> u32 {
1285        match address_space {
1286            Some(address_space) => unsafe { LLVMPointerSizeForAS(self.target_data, address_space.0) },
1287            None => unsafe { LLVMPointerSize(self.target_data) },
1288        }
1289    }
1290
1291    pub fn get_store_size(&self, type_: &dyn AnyType) -> u64 {
1292        unsafe { LLVMStoreSizeOfType(self.target_data, type_.as_type_ref()) }
1293    }
1294
1295    pub fn get_abi_size(&self, type_: &dyn AnyType) -> u64 {
1296        unsafe { LLVMABISizeOfType(self.target_data, type_.as_type_ref()) }
1297    }
1298
1299    pub fn get_abi_alignment(&self, type_: &dyn AnyType) -> u32 {
1300        unsafe { LLVMABIAlignmentOfType(self.target_data, type_.as_type_ref()) }
1301    }
1302
1303    pub fn get_call_frame_alignment(&self, type_: &dyn AnyType) -> u32 {
1304        unsafe { LLVMCallFrameAlignmentOfType(self.target_data, type_.as_type_ref()) }
1305    }
1306
1307    pub fn get_preferred_alignment(&self, type_: &dyn AnyType) -> u32 {
1308        unsafe { LLVMPreferredAlignmentOfType(self.target_data, type_.as_type_ref()) }
1309    }
1310
1311    pub fn get_preferred_alignment_of_global(&self, value: &GlobalValue) -> u32 {
1312        unsafe { LLVMPreferredAlignmentOfGlobal(self.target_data, value.as_value_ref()) }
1313    }
1314
1315    pub fn element_at_offset(&self, struct_type: &StructType, offset: u64) -> u32 {
1316        unsafe { LLVMElementAtOffset(self.target_data, struct_type.as_type_ref(), offset) }
1317    }
1318
1319    pub fn offset_of_element(&self, struct_type: &StructType, element: u32) -> Option<u64> {
1320        if element > struct_type.count_fields() - 1 {
1321            return None;
1322        }
1323
1324        unsafe {
1325            Some(LLVMOffsetOfElement(
1326                self.target_data,
1327                struct_type.as_type_ref(),
1328                element,
1329            ))
1330        }
1331    }
1332}
1333
1334impl Drop for TargetData {
1335    fn drop(&mut self) {
1336        unsafe { LLVMDisposeTargetData(self.target_data) }
1337    }
1338}