/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/targets.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use 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)] |
9 | | use llvm_sys::target_machine::LLVMCreateTargetDataLayout; |
10 | | use 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 | | }; |
19 | | use once_cell::sync::Lazy; |
20 | | use parking_lot::RwLock; |
21 | | |
22 | | use crate::context::AsContextRef; |
23 | | use crate::data_layout::DataLayout; |
24 | | use crate::memory_buffer::MemoryBuffer; |
25 | | use crate::module::Module; |
26 | | use crate::passes::PassManager; |
27 | | use crate::support::{to_c_str, LLVMString}; |
28 | | use crate::types::{AnyType, AsTypeRef, IntType, StructType}; |
29 | | use crate::values::{AsValueRef, GlobalValue}; |
30 | | use crate::{AddressSpace, OptimizationLevel}; |
31 | | |
32 | | use std::default::Default; |
33 | | use std::ffi::CStr; |
34 | | use std::fmt; |
35 | | use std::mem::MaybeUninit; |
36 | | use std::path::Path; |
37 | | use std::ptr; |
38 | | |
39 | | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
40 | | pub enum CodeModel { |
41 | | Default, |
42 | | JITDefault, |
43 | | Small, |
44 | | Kernel, |
45 | | Medium, |
46 | | Large, |
47 | | } |
48 | | |
49 | | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
50 | | pub enum RelocMode { |
51 | | Default, |
52 | | Static, |
53 | | PIC, |
54 | | DynamicNoPic, |
55 | | } |
56 | | |
57 | | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
58 | | pub enum FileType { |
59 | | Assembly, |
60 | | Object, |
61 | | } |
62 | | |
63 | | impl FileType { |
64 | 159k | fn as_llvm_file_type(&self) -> LLVMCodeGenFileType { |
65 | 159k | match *self { |
66 | 0 | FileType::Assembly => LLVMCodeGenFileType::LLVMAssemblyFile, |
67 | 159k | FileType::Object => LLVMCodeGenFileType::LLVMObjectFile, |
68 | | } |
69 | 159k | } |
70 | | } |
71 | | |
72 | | // TODO: Doc: Base gets you TargetMachine support, machine_code gets you asm_backend |
73 | | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
74 | | pub 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 | | |
83 | | impl Default for InitializationConfig { |
84 | 0 | fn default() -> Self { |
85 | 0 | InitializationConfig { |
86 | 0 | asm_parser: true, |
87 | 0 | asm_printer: true, |
88 | 0 | base: true, |
89 | 0 | disassembler: true, |
90 | 0 | info: true, |
91 | 0 | machine_code: true, |
92 | 0 | } |
93 | 0 | } |
94 | | } |
95 | | |
96 | | #[derive(Eq)] |
97 | | pub struct TargetTriple { |
98 | | pub(crate) triple: LLVMString, |
99 | | } |
100 | | |
101 | | impl TargetTriple { |
102 | 331k | pub unsafe fn new(triple: LLVMString) -> TargetTriple { |
103 | 331k | TargetTriple { triple } |
104 | 331k | } |
105 | | |
106 | 171k | pub fn create(triple: &str) -> TargetTriple { |
107 | 171k | let c_string = to_c_str(triple); |
108 | 171k | |
109 | 171k | TargetTriple { |
110 | 171k | triple: LLVMString::create_from_c_str(&c_string), |
111 | 171k | } |
112 | 171k | } |
113 | | |
114 | 171k | pub fn as_str(&self) -> &CStr { |
115 | 171k | unsafe { CStr::from_ptr(self.as_ptr()) } |
116 | 171k | } |
117 | | |
118 | 674k | pub fn as_ptr(&self) -> *const ::libc::c_char { |
119 | 674k | self.triple.as_ptr() |
120 | 674k | } |
121 | | } |
122 | | |
123 | | impl PartialEq for TargetTriple { |
124 | 0 | fn eq(&self, other: &TargetTriple) -> bool { |
125 | 0 | self.triple == other.triple |
126 | 0 | } |
127 | | } |
128 | | |
129 | | impl fmt::Debug for TargetTriple { |
130 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
131 | 0 | write!(f, "TargetTriple({:?})", self.triple) |
132 | 0 | } |
133 | | } |
134 | | |
135 | | impl fmt::Display for TargetTriple { |
136 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
137 | 0 | write!(f, "TargetTriple({:?})", self.triple) |
138 | 0 | } |
139 | | } |
140 | | |
141 | 2 | static 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)] |
145 | | pub struct Target { |
146 | | target: LLVMTargetRef, |
147 | | } |
148 | | |
149 | | impl Target { |
150 | 171k | pub unsafe fn new(target: LLVMTargetRef) -> Self { |
151 | 171k | assert!(!target.is_null()); |
152 | | |
153 | 171k | Target { target } |
154 | 171k | } |
155 | | |
156 | | /// Acquires the underlying raw pointer belonging to this `Target` type. |
157 | 0 | pub fn as_mut_ptr(&self) -> LLVMTargetRef { |
158 | 0 | self.target |
159 | 0 | } |
160 | | |
161 | | // REVIEW: Should this just initialize all? Is opt into each a good idea? |
162 | | #[cfg(feature = "target-x86")] |
163 | 171k | pub fn initialize_x86(config: &InitializationConfig) { |
164 | 171k | use llvm_sys::target::{ |
165 | 171k | LLVMInitializeX86AsmParser, LLVMInitializeX86AsmPrinter, LLVMInitializeX86Disassembler, |
166 | 171k | LLVMInitializeX86Target, LLVMInitializeX86TargetInfo, LLVMInitializeX86TargetMC, |
167 | 171k | }; |
168 | 171k | |
169 | 171k | if config.base { |
170 | 171k | let _guard = TARGET_LOCK.write(); |
171 | 171k | unsafe { LLVMInitializeX86Target() }; |
172 | 171k | } |
173 | | |
174 | 171k | if config.info { |
175 | 171k | let _guard = TARGET_LOCK.write(); |
176 | 171k | unsafe { LLVMInitializeX86TargetInfo() }; |
177 | 171k | } |
178 | | |
179 | 171k | if config.asm_printer { |
180 | 171k | let _guard = TARGET_LOCK.write(); |
181 | 171k | unsafe { LLVMInitializeX86AsmPrinter() }; |
182 | 171k | } |
183 | | |
184 | 171k | if config.asm_parser { |
185 | 171k | let _guard = TARGET_LOCK.write(); |
186 | 171k | unsafe { LLVMInitializeX86AsmParser() }; |
187 | 171k | } |
188 | | |
189 | 171k | if config.disassembler { |
190 | 171k | let _guard = TARGET_LOCK.write(); |
191 | 171k | unsafe { LLVMInitializeX86Disassembler() }; |
192 | 171k | } |
193 | | |
194 | 171k | if config.machine_code { |
195 | 171k | let _guard = TARGET_LOCK.write(); |
196 | 171k | unsafe { LLVMInitializeX86TargetMC() }; |
197 | 171k | } |
198 | 171k | } |
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 | 0 | pub fn initialize_aarch64(config: &InitializationConfig) { |
278 | 0 | use llvm_sys::target::{ |
279 | 0 | LLVMInitializeAArch64AsmParser, LLVMInitializeAArch64AsmPrinter, LLVMInitializeAArch64Disassembler, |
280 | 0 | LLVMInitializeAArch64Target, LLVMInitializeAArch64TargetInfo, LLVMInitializeAArch64TargetMC, |
281 | 0 | }; |
282 | 0 |
|
283 | 0 | if config.base { |
284 | 0 | let _guard = TARGET_LOCK.write(); |
285 | 0 | unsafe { LLVMInitializeAArch64Target() }; |
286 | 0 | } |
287 | | |
288 | 0 | if config.info { |
289 | 0 | let _guard = TARGET_LOCK.write(); |
290 | 0 | unsafe { LLVMInitializeAArch64TargetInfo() }; |
291 | 0 | } |
292 | | |
293 | 0 | if config.asm_printer { |
294 | 0 | let _guard = TARGET_LOCK.write(); |
295 | 0 | unsafe { LLVMInitializeAArch64AsmPrinter() }; |
296 | 0 | } |
297 | | |
298 | 0 | if config.asm_parser { |
299 | 0 | let _guard = TARGET_LOCK.write(); |
300 | 0 | unsafe { LLVMInitializeAArch64AsmParser() }; |
301 | 0 | } |
302 | | |
303 | 0 | if config.disassembler { |
304 | 0 | let _guard = TARGET_LOCK.write(); |
305 | 0 | unsafe { LLVMInitializeAArch64Disassembler() }; |
306 | 0 | } |
307 | | |
308 | 0 | if config.machine_code { |
309 | 0 | let _guard = TARGET_LOCK.write(); |
310 | 0 | unsafe { LLVMInitializeAArch64TargetMC() }; |
311 | 0 | } |
312 | 0 | } |
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 | 0 | pub fn initialize_riscv(config: &InitializationConfig) { |
682 | 0 | use llvm_sys::target::{ |
683 | 0 | LLVMInitializeRISCVAsmParser, LLVMInitializeRISCVAsmPrinter, LLVMInitializeRISCVDisassembler, |
684 | 0 | LLVMInitializeRISCVTarget, LLVMInitializeRISCVTargetInfo, LLVMInitializeRISCVTargetMC, |
685 | 0 | }; |
686 | 0 |
|
687 | 0 | if config.base { |
688 | 0 | let _guard = TARGET_LOCK.write(); |
689 | 0 | unsafe { LLVMInitializeRISCVTarget() }; |
690 | 0 | } |
691 | | |
692 | 0 | if config.info { |
693 | 0 | let _guard = TARGET_LOCK.write(); |
694 | 0 | unsafe { LLVMInitializeRISCVTargetInfo() }; |
695 | 0 | } |
696 | | |
697 | 0 | if config.asm_printer { |
698 | 0 | let _guard = TARGET_LOCK.write(); |
699 | 0 | unsafe { LLVMInitializeRISCVAsmPrinter() }; |
700 | 0 | } |
701 | | |
702 | 0 | if config.asm_parser { |
703 | 0 | let _guard = TARGET_LOCK.write(); |
704 | 0 | unsafe { LLVMInitializeRISCVAsmParser() }; |
705 | 0 | } |
706 | | |
707 | 0 | if config.disassembler { |
708 | 0 | let _guard = TARGET_LOCK.write(); |
709 | 0 | unsafe { LLVMInitializeRISCVDisassembler() }; |
710 | 0 | } |
711 | | |
712 | 0 | if config.machine_code { |
713 | 0 | let _guard = TARGET_LOCK.write(); |
714 | 0 | unsafe { LLVMInitializeRISCVTargetMC() }; |
715 | 0 | } |
716 | 0 | } |
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 | 0 | pub fn initialize_native(config: &InitializationConfig) -> Result<(), String> { |
759 | 0 | use llvm_sys::target::{ |
760 | 0 | LLVM_InitializeNativeAsmParser, LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeDisassembler, |
761 | 0 | LLVM_InitializeNativeTarget, |
762 | 0 | }; |
763 | 0 |
|
764 | 0 | if config.base { |
765 | 0 | let _guard = TARGET_LOCK.write(); |
766 | 0 | let code = unsafe { LLVM_InitializeNativeTarget() }; |
767 | 0 |
|
768 | 0 | if code == 1 { |
769 | 0 | return Err("Unknown error in initializing native target".into()); |
770 | 0 | } |
771 | 0 | } |
772 | | |
773 | 0 | if config.asm_printer { |
774 | 0 | let _guard = TARGET_LOCK.write(); |
775 | 0 | let code = unsafe { LLVM_InitializeNativeAsmPrinter() }; |
776 | 0 |
|
777 | 0 | if code == 1 { |
778 | 0 | return Err("Unknown error in initializing native asm printer".into()); |
779 | 0 | } |
780 | 0 | } |
781 | | |
782 | 0 | if config.asm_parser { |
783 | 0 | let _guard = TARGET_LOCK.write(); |
784 | 0 | let code = unsafe { LLVM_InitializeNativeAsmParser() }; |
785 | 0 |
|
786 | 0 | if code == 1 { |
787 | | // REVIEW: Does parser need to go before printer? |
788 | 0 | return Err("Unknown error in initializing native asm parser".into()); |
789 | 0 | } |
790 | 0 | } |
791 | | |
792 | 0 | if config.disassembler { |
793 | 0 | let _guard = TARGET_LOCK.write(); |
794 | 0 | let code = unsafe { LLVM_InitializeNativeDisassembler() }; |
795 | 0 |
|
796 | 0 | if code == 1 { |
797 | 0 | return Err("Unknown error in initializing native disassembler".into()); |
798 | 0 | } |
799 | 0 | } |
800 | | |
801 | 0 | Ok(()) |
802 | 0 | } |
803 | | |
804 | 0 | pub fn initialize_all(config: &InitializationConfig) { |
805 | 0 | use llvm_sys::target::{ |
806 | 0 | LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllDisassemblers, |
807 | 0 | LLVM_InitializeAllTargetInfos, LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, |
808 | 0 | }; |
809 | 0 |
|
810 | 0 | if config.base { |
811 | 0 | let _guard = TARGET_LOCK.write(); |
812 | 0 | unsafe { LLVM_InitializeAllTargets() }; |
813 | 0 | } |
814 | | |
815 | 0 | if config.info { |
816 | 0 | let _guard = TARGET_LOCK.write(); |
817 | 0 | unsafe { LLVM_InitializeAllTargetInfos() }; |
818 | 0 | } |
819 | | |
820 | 0 | if config.asm_parser { |
821 | 0 | let _guard = TARGET_LOCK.write(); |
822 | 0 | unsafe { LLVM_InitializeAllAsmParsers() }; |
823 | 0 | } |
824 | | |
825 | 0 | if config.asm_printer { |
826 | 0 | let _guard = TARGET_LOCK.write(); |
827 | 0 | unsafe { LLVM_InitializeAllAsmPrinters() }; |
828 | 0 | } |
829 | | |
830 | 0 | if config.disassembler { |
831 | 0 | let _guard = TARGET_LOCK.write(); |
832 | 0 | unsafe { LLVM_InitializeAllDisassemblers() }; |
833 | 0 | } |
834 | | |
835 | 0 | if config.machine_code { |
836 | 0 | let _guard = TARGET_LOCK.write(); |
837 | 0 | unsafe { LLVM_InitializeAllTargetMCs() }; |
838 | 0 | } |
839 | 0 | } |
840 | | |
841 | 171k | pub fn create_target_machine( |
842 | 171k | &self, |
843 | 171k | triple: &TargetTriple, |
844 | 171k | cpu: &str, |
845 | 171k | features: &str, |
846 | 171k | level: OptimizationLevel, |
847 | 171k | reloc_mode: RelocMode, |
848 | 171k | code_model: CodeModel, |
849 | 171k | ) -> Option<TargetMachine> { |
850 | 171k | let cpu = to_c_str(cpu); |
851 | 171k | let features = to_c_str(features); |
852 | 171k | let level = match level { |
853 | 0 | OptimizationLevel::None => LLVMCodeGenOptLevel::LLVMCodeGenLevelNone, |
854 | 0 | OptimizationLevel::Less => LLVMCodeGenOptLevel::LLVMCodeGenLevelLess, |
855 | 0 | OptimizationLevel::Default => LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault, |
856 | 171k | OptimizationLevel::Aggressive => LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive, |
857 | | }; |
858 | 171k | let code_model = match code_model { |
859 | 0 | CodeModel::Default => LLVMCodeModel::LLVMCodeModelDefault, |
860 | 0 | CodeModel::JITDefault => LLVMCodeModel::LLVMCodeModelJITDefault, |
861 | 0 | CodeModel::Small => LLVMCodeModel::LLVMCodeModelSmall, |
862 | 0 | CodeModel::Kernel => LLVMCodeModel::LLVMCodeModelKernel, |
863 | 0 | CodeModel::Medium => LLVMCodeModel::LLVMCodeModelMedium, |
864 | 171k | CodeModel::Large => LLVMCodeModel::LLVMCodeModelLarge, |
865 | | }; |
866 | 171k | let reloc_mode = match reloc_mode { |
867 | 0 | RelocMode::Default => LLVMRelocMode::LLVMRelocDefault, |
868 | 171k | RelocMode::Static => LLVMRelocMode::LLVMRelocStatic, |
869 | 0 | RelocMode::PIC => LLVMRelocMode::LLVMRelocPIC, |
870 | 0 | RelocMode::DynamicNoPic => LLVMRelocMode::LLVMRelocDynamicNoPic, |
871 | | }; |
872 | 171k | let target_machine = unsafe { |
873 | 171k | LLVMCreateTargetMachine( |
874 | 171k | self.target, |
875 | 171k | triple.as_ptr(), |
876 | 171k | cpu.as_ptr(), |
877 | 171k | features.as_ptr(), |
878 | 171k | level, |
879 | 171k | reloc_mode, |
880 | 171k | code_model, |
881 | 171k | ) |
882 | 171k | }; |
883 | 171k | |
884 | 171k | if target_machine.is_null() { |
885 | 0 | return None; |
886 | 171k | } |
887 | 171k | |
888 | 171k | unsafe { Some(TargetMachine::new(target_machine)) } |
889 | 171k | } |
890 | | |
891 | 0 | pub fn get_first() -> Option<Self> { |
892 | 0 | let target = { |
893 | 0 | let _guard = TARGET_LOCK.read(); |
894 | 0 | unsafe { LLVMGetFirstTarget() } |
895 | 0 | }; |
896 | 0 |
|
897 | 0 | if target.is_null() { |
898 | 0 | return None; |
899 | 0 | } |
900 | 0 |
|
901 | 0 | unsafe { Some(Target::new(target)) } |
902 | 0 | } |
903 | | |
904 | 0 | pub fn get_next(&self) -> Option<Self> { |
905 | 0 | let target = unsafe { LLVMGetNextTarget(self.target) }; |
906 | 0 |
|
907 | 0 | if target.is_null() { |
908 | 0 | return None; |
909 | 0 | } |
910 | 0 |
|
911 | 0 | unsafe { Some(Target::new(target)) } |
912 | 0 | } |
913 | | |
914 | 0 | pub fn get_name(&self) -> &CStr { |
915 | 0 | unsafe { CStr::from_ptr(LLVMGetTargetName(self.target)) } |
916 | 0 | } |
917 | | |
918 | 0 | pub fn get_description(&self) -> &CStr { |
919 | 0 | unsafe { CStr::from_ptr(LLVMGetTargetDescription(self.target)) } |
920 | 0 | } |
921 | | |
922 | 0 | pub fn from_name(name: &str) -> Option<Self> { |
923 | 0 | let c_string = to_c_str(name); |
924 | 0 |
|
925 | 0 | Self::from_name_raw(c_string.as_ptr()) |
926 | 0 | } |
927 | | |
928 | 0 | pub(crate) fn from_name_raw(c_string: *const ::libc::c_char) -> Option<Self> { |
929 | 0 | let target = { |
930 | 0 | let _guard = TARGET_LOCK.read(); |
931 | 0 | unsafe { LLVMGetTargetFromName(c_string) } |
932 | 0 | }; |
933 | 0 |
|
934 | 0 | if target.is_null() { |
935 | 0 | return None; |
936 | 0 | } |
937 | 0 |
|
938 | 0 | unsafe { Some(Target::new(target)) } |
939 | 0 | } |
940 | | |
941 | 171k | pub fn from_triple(triple: &TargetTriple) -> Result<Self, LLVMString> { |
942 | 171k | let mut target = ptr::null_mut(); |
943 | 171k | let mut err_string = MaybeUninit::uninit(); |
944 | 171k | |
945 | 171k | let code = { |
946 | 171k | let _guard = TARGET_LOCK.read(); |
947 | 171k | unsafe { LLVMGetTargetFromTriple(triple.as_ptr(), &mut target, err_string.as_mut_ptr()) } |
948 | 171k | }; |
949 | 171k | |
950 | 171k | if code == 1 { |
951 | | unsafe { |
952 | 0 | return Err(LLVMString::new(err_string.assume_init())); |
953 | | } |
954 | 171k | } |
955 | 171k | |
956 | 171k | unsafe { Ok(Target::new(target)) } |
957 | 171k | } |
958 | | |
959 | 0 | pub fn has_jit(&self) -> bool { |
960 | 0 | unsafe { LLVMTargetHasJIT(self.target) == 1 } |
961 | 0 | } |
962 | | |
963 | 0 | pub fn has_target_machine(&self) -> bool { |
964 | 0 | unsafe { LLVMTargetHasTargetMachine(self.target) == 1 } |
965 | 0 | } |
966 | | |
967 | 0 | pub fn has_asm_backend(&self) -> bool { |
968 | 0 | unsafe { LLVMTargetHasAsmBackend(self.target) == 1 } |
969 | 0 | } |
970 | | } |
971 | | |
972 | | #[derive(Debug)] |
973 | | pub struct TargetMachine { |
974 | | pub(crate) target_machine: LLVMTargetMachineRef, |
975 | | } |
976 | | |
977 | | impl TargetMachine { |
978 | 171k | pub unsafe fn new(target_machine: LLVMTargetMachineRef) -> Self { |
979 | 171k | assert!(!target_machine.is_null()); |
980 | | |
981 | 171k | TargetMachine { target_machine } |
982 | 171k | } |
983 | | |
984 | | /// Acquires the underlying raw pointer belonging to this `TargetMachine` type. |
985 | 0 | pub fn as_mut_ptr(&self) -> LLVMTargetMachineRef { |
986 | 0 | self.target_machine |
987 | 0 | } |
988 | | |
989 | 0 | pub fn get_target(&self) -> Target { |
990 | 0 | unsafe { Target::new(LLVMGetTargetMachineTarget(self.target_machine)) } |
991 | 0 | } |
992 | | |
993 | 331k | pub fn get_triple(&self) -> TargetTriple { |
994 | 331k | let str = unsafe { LLVMString::new(LLVMGetTargetMachineTriple(self.target_machine)) }; |
995 | 331k | |
996 | 331k | unsafe { TargetTriple::new(str) } |
997 | 331k | } |
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 | 0 | pub fn get_default_triple() -> TargetTriple { |
1011 | 0 | let llvm_string = unsafe { LLVMString::new(LLVMGetDefaultTargetTriple()) }; |
1012 | 0 |
|
1013 | 0 | unsafe { TargetTriple::new(llvm_string) } |
1014 | 0 | } |
1015 | | |
1016 | | #[llvm_versions(7.0..=latest)] |
1017 | 0 | pub fn normalize_triple(triple: &TargetTriple) -> TargetTriple { |
1018 | 0 | use llvm_sys::target_machine::LLVMNormalizeTargetTriple; |
1019 | 0 |
|
1020 | 0 | let normalized = unsafe { LLVMString::new(LLVMNormalizeTargetTriple(triple.as_ptr())) }; |
1021 | 0 |
|
1022 | 0 | unsafe { TargetTriple::new(normalized) } |
1023 | 0 | } |
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 | 0 | pub fn get_host_cpu_name() -> LLVMString { |
1032 | 0 | use llvm_sys::target_machine::LLVMGetHostCPUName; |
1033 | 0 |
|
1034 | 0 | unsafe { LLVMString::new(LLVMGetHostCPUName()) } |
1035 | 0 | } |
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 | 0 | pub fn get_host_cpu_features() -> LLVMString { |
1044 | 0 | use llvm_sys::target_machine::LLVMGetHostCPUFeatures; |
1045 | 0 |
|
1046 | 0 | unsafe { LLVMString::new(LLVMGetHostCPUFeatures()) } |
1047 | 0 | } |
1048 | | |
1049 | 0 | pub fn get_cpu(&self) -> LLVMString { |
1050 | 0 | unsafe { LLVMString::new(LLVMGetTargetMachineCPU(self.target_machine)) } |
1051 | 0 | } |
1052 | | |
1053 | 0 | pub fn get_feature_string(&self) -> &CStr { |
1054 | 0 | unsafe { CStr::from_ptr(LLVMGetTargetMachineFeatureString(self.target_machine)) } |
1055 | 0 | } |
1056 | | |
1057 | | /// Create TargetData from this target machine |
1058 | | #[llvm_versions(4.0..=latest)] |
1059 | 159k | pub fn get_target_data(&self) -> TargetData { |
1060 | 159k | unsafe { TargetData::new(LLVMCreateTargetDataLayout(self.target_machine)) } |
1061 | 159k | } |
1062 | | |
1063 | 0 | pub fn set_asm_verbosity(&self, verbosity: bool) { |
1064 | 0 | unsafe { LLVMSetTargetMachineAsmVerbosity(self.target_machine, verbosity as i32) } |
1065 | 0 | } |
1066 | | |
1067 | | // TODO: Move to PassManager? |
1068 | 0 | pub fn add_analysis_passes<T>(&self, pass_manager: &PassManager<T>) { |
1069 | 0 | unsafe { LLVMAddAnalysisPasses(self.target_machine, pass_manager.pass_manager) } |
1070 | 0 | } |
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 | 159k | pub fn write_to_memory_buffer(&self, module: &Module, file_type: FileType) -> Result<MemoryBuffer, LLVMString> { |
1107 | 159k | let mut memory_buffer = ptr::null_mut(); |
1108 | 159k | let mut err_string = MaybeUninit::uninit(); |
1109 | 159k | let return_code = unsafe { |
1110 | 159k | let module_ptr = module.module.get(); |
1111 | 159k | let file_type_ptr = file_type.as_llvm_file_type(); |
1112 | 159k | |
1113 | 159k | LLVMTargetMachineEmitToMemoryBuffer( |
1114 | 159k | self.target_machine, |
1115 | 159k | module_ptr, |
1116 | 159k | file_type_ptr, |
1117 | 159k | err_string.as_mut_ptr(), |
1118 | 159k | &mut memory_buffer, |
1119 | 159k | ) |
1120 | 159k | }; |
1121 | 159k | |
1122 | 159k | if return_code == 1 { |
1123 | | unsafe { |
1124 | 0 | return Err(LLVMString::new(err_string.assume_init())); |
1125 | | } |
1126 | 159k | } |
1127 | 159k | |
1128 | 159k | unsafe { Ok(MemoryBuffer::new(memory_buffer)) } |
1129 | 159k | } |
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 | 0 | pub fn write_to_file(&self, module: &Module, file_type: FileType, path: &Path) -> Result<(), LLVMString> { |
1169 | 0 | let path = path.to_str().expect("Did not find a valid Unicode path string"); |
1170 | 0 | let path_c_string = to_c_str(path); |
1171 | 0 | let mut err_string = MaybeUninit::uninit(); |
1172 | 0 | let return_code = unsafe { |
1173 | 0 | // REVIEW: Why does LLVM need a mutable ptr to path...? |
1174 | 0 | let module_ptr = module.module.get(); |
1175 | 0 | let path_ptr = path_c_string.as_ptr() as *mut _; |
1176 | 0 | let file_type_ptr = file_type.as_llvm_file_type(); |
1177 | 0 |
|
1178 | 0 | LLVMTargetMachineEmitToFile( |
1179 | 0 | self.target_machine, |
1180 | 0 | module_ptr, |
1181 | 0 | path_ptr, |
1182 | 0 | file_type_ptr, |
1183 | 0 | err_string.as_mut_ptr(), |
1184 | 0 | ) |
1185 | 0 | }; |
1186 | 0 |
|
1187 | 0 | if return_code == 1 { |
1188 | | unsafe { |
1189 | 0 | return Err(LLVMString::new(err_string.assume_init())); |
1190 | | } |
1191 | 0 | } |
1192 | 0 |
|
1193 | 0 | Ok(()) |
1194 | 0 | } |
1195 | | } |
1196 | | |
1197 | | impl Drop for TargetMachine { |
1198 | 171k | fn drop(&mut self) { |
1199 | 171k | unsafe { LLVMDisposeTargetMachine(self.target_machine) } |
1200 | 171k | } |
1201 | | } |
1202 | | |
1203 | | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
1204 | | pub enum ByteOrdering { |
1205 | | BigEndian, |
1206 | | LittleEndian, |
1207 | | } |
1208 | | |
1209 | | #[derive(PartialEq, Eq, Debug)] |
1210 | | pub struct TargetData { |
1211 | | pub(crate) target_data: LLVMTargetDataRef, |
1212 | | } |
1213 | | |
1214 | | impl TargetData { |
1215 | 159k | pub unsafe fn new(target_data: LLVMTargetDataRef) -> TargetData { |
1216 | 159k | assert!(!target_data.is_null()); |
1217 | | |
1218 | 159k | TargetData { target_data } |
1219 | 159k | } |
1220 | | |
1221 | | /// Acquires the underlying raw pointer belonging to this `TargetData` type. |
1222 | 0 | pub fn as_mut_ptr(&self) -> LLVMTargetDataRef { |
1223 | 0 | self.target_data |
1224 | 0 | } |
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 | 0 | pub fn ptr_sized_int_type_in_context<'ctx>( |
1245 | 0 | &self, |
1246 | 0 | context: impl AsContextRef<'ctx>, |
1247 | 0 | address_space: Option<AddressSpace>, |
1248 | 0 | ) -> IntType<'ctx> { |
1249 | 0 | let int_type_ptr = match address_space { |
1250 | 0 | Some(address_space) => unsafe { |
1251 | 0 | LLVMIntPtrTypeForASInContext(context.as_ctx_ref(), self.target_data, address_space.0) |
1252 | | }, |
1253 | 0 | None => unsafe { LLVMIntPtrTypeInContext(context.as_ctx_ref(), self.target_data) }, |
1254 | | }; |
1255 | | |
1256 | 0 | unsafe { IntType::new(int_type_ptr) } |
1257 | 0 | } |
1258 | | |
1259 | 159k | pub fn get_data_layout(&self) -> DataLayout { |
1260 | 159k | unsafe { DataLayout::new_owned(LLVMCopyStringRepOfTargetData(self.target_data)) } |
1261 | 159k | } |
1262 | | |
1263 | | // REVIEW: Does this only work if Sized? |
1264 | 0 | pub fn get_bit_size(&self, type_: &dyn AnyType) -> u64 { |
1265 | 0 | unsafe { LLVMSizeOfTypeInBits(self.target_data, type_.as_type_ref()) } |
1266 | 0 | } |
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 | 0 | pub fn create(str_repr: &str) -> TargetData { |
1270 | 0 | let c_string = to_c_str(str_repr); |
1271 | 0 |
|
1272 | 0 | unsafe { TargetData::new(LLVMCreateTargetData(c_string.as_ptr())) } |
1273 | 0 | } |
1274 | | |
1275 | 0 | pub fn get_byte_ordering(&self) -> ByteOrdering { |
1276 | 0 | let byte_ordering = unsafe { LLVMByteOrder(self.target_data) }; |
1277 | 0 |
|
1278 | 0 | match byte_ordering { |
1279 | 0 | LLVMByteOrdering::LLVMBigEndian => ByteOrdering::BigEndian, |
1280 | 0 | LLVMByteOrdering::LLVMLittleEndian => ByteOrdering::LittleEndian, |
1281 | | } |
1282 | 0 | } |
1283 | | |
1284 | 0 | pub fn get_pointer_byte_size(&self, address_space: Option<AddressSpace>) -> u32 { |
1285 | 0 | match address_space { |
1286 | 0 | Some(address_space) => unsafe { LLVMPointerSizeForAS(self.target_data, address_space.0) }, |
1287 | 0 | None => unsafe { LLVMPointerSize(self.target_data) }, |
1288 | | } |
1289 | 0 | } |
1290 | | |
1291 | 0 | pub fn get_store_size(&self, type_: &dyn AnyType) -> u64 { |
1292 | 0 | unsafe { LLVMStoreSizeOfType(self.target_data, type_.as_type_ref()) } |
1293 | 0 | } |
1294 | | |
1295 | 0 | pub fn get_abi_size(&self, type_: &dyn AnyType) -> u64 { |
1296 | 0 | unsafe { LLVMABISizeOfType(self.target_data, type_.as_type_ref()) } |
1297 | 0 | } |
1298 | | |
1299 | 0 | pub fn get_abi_alignment(&self, type_: &dyn AnyType) -> u32 { |
1300 | 0 | unsafe { LLVMABIAlignmentOfType(self.target_data, type_.as_type_ref()) } |
1301 | 0 | } |
1302 | | |
1303 | 0 | pub fn get_call_frame_alignment(&self, type_: &dyn AnyType) -> u32 { |
1304 | 0 | unsafe { LLVMCallFrameAlignmentOfType(self.target_data, type_.as_type_ref()) } |
1305 | 0 | } |
1306 | | |
1307 | 0 | pub fn get_preferred_alignment(&self, type_: &dyn AnyType) -> u32 { |
1308 | 0 | unsafe { LLVMPreferredAlignmentOfType(self.target_data, type_.as_type_ref()) } |
1309 | 0 | } |
1310 | | |
1311 | 0 | pub fn get_preferred_alignment_of_global(&self, value: &GlobalValue) -> u32 { |
1312 | 0 | unsafe { LLVMPreferredAlignmentOfGlobal(self.target_data, value.as_value_ref()) } |
1313 | 0 | } |
1314 | | |
1315 | 0 | pub fn element_at_offset(&self, struct_type: &StructType, offset: u64) -> u32 { |
1316 | 0 | unsafe { LLVMElementAtOffset(self.target_data, struct_type.as_type_ref(), offset) } |
1317 | 0 | } |
1318 | | |
1319 | 0 | pub fn offset_of_element(&self, struct_type: &StructType, element: u32) -> Option<u64> { |
1320 | 0 | if element > struct_type.count_fields() - 1 { |
1321 | 0 | return None; |
1322 | 0 | } |
1323 | 0 |
|
1324 | 0 | unsafe { |
1325 | 0 | Some(LLVMOffsetOfElement( |
1326 | 0 | self.target_data, |
1327 | 0 | struct_type.as_type_ref(), |
1328 | 0 | element, |
1329 | 0 | )) |
1330 | | } |
1331 | 0 | } |
1332 | | } |
1333 | | |
1334 | | impl Drop for TargetData { |
1335 | 159k | fn drop(&mut self) { |
1336 | 159k | unsafe { LLVMDisposeTargetData(self.target_data) } |
1337 | 159k | } |
1338 | | } |