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#[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#[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 pub fn as_mut_ptr(&self) -> LLVMTargetRef {
158 self.target
159 }
160
161 #[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 }
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 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 if config.machine_code {
448 let _guard = TARGET_LOCK.write();
449 unsafe { LLVMInitializeNVPTXTargetMC() };
450 }
451
452 }
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 if config.machine_code {
480 let _guard = TARGET_LOCK.write();
481 unsafe { LLVMInitializeMSP430TargetMC() };
482 }
483
484 }
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 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 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 #[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 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 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 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 #[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 #[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 #[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 pub fn add_analysis_passes<T>(&self, pass_manager: &PassManager<T>) {
1069 unsafe { LLVMAddAnalysisPasses(self.target_machine, pass_manager.pass_manager) }
1070 }
1071
1072 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 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 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 pub fn as_mut_ptr(&self) -> LLVMTargetDataRef {
1223 self.target_data
1224 }
1225
1226 #[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 pub fn get_bit_size(&self, type_: &dyn AnyType) -> u64 {
1265 unsafe { LLVMSizeOfTypeInBits(self.target_data, type_.as_type_ref()) }
1266 }
1267
1268 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}