pliron_llvm/llvm_sys/
target.rs1use crate::llvm_sys::{
7 ToBool,
8 core::{LLVMType, llvm_count_struct_element_types, llvm_get_type_kind, llvm_type_is_sized},
9 cstr_to_string, to_c_str,
10};
11use llvm_sys::{
12 LLVMTypeKind,
13 core::LLVMDisposeMessage,
14 target::{
15 LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters,
16 LLVM_InitializeAllDisassemblers, LLVM_InitializeAllTargetInfos,
17 LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVM_InitializeNativeAsmParser,
18 LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeDisassembler,
19 LLVM_InitializeNativeTarget, LLVMABIAlignmentOfType, LLVMABISizeOfType,
20 LLVMCopyStringRepOfTargetData, LLVMCreateTargetData, LLVMDisposeTargetData,
21 LLVMOffsetOfElement, LLVMPointerSizeForAS, LLVMPreferredAlignmentOfType,
22 LLVMSizeOfTypeInBits, LLVMStoreSizeOfType, LLVMTargetDataRef,
23 },
24 target_machine::{
25 LLVMCodeGenOptLevel, LLVMCodeModel, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
26 LLVMDisposeTargetMachine, LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple,
27 LLVMRelocMode,
28 },
29};
30use std::{
31 mem::MaybeUninit,
32 sync::{Mutex, PoisonError},
33};
34
35static REGISTRY_LOCK: Mutex<()> = Mutex::new(());
37
38fn with_registry_lock<R>(f: impl FnOnce() -> R) -> R {
40 let _guard = REGISTRY_LOCK.lock().unwrap_or_else(PoisonError::into_inner);
43 f()
44}
45
46pub fn llvm_initialize_all_target_infos() {
48 with_registry_lock(|| unsafe {
49 LLVM_InitializeAllTargetInfos();
50 });
51}
52
53pub fn llvm_initialize_all_targets() {
55 with_registry_lock(|| unsafe {
56 LLVM_InitializeAllTargets();
57 });
58}
59
60pub fn llvm_initialize_all_target_mcs() {
62 with_registry_lock(|| unsafe {
63 LLVM_InitializeAllTargetMCs();
64 });
65}
66
67pub fn llvm_initialize_all_asm_printers() {
69 with_registry_lock(|| unsafe {
70 LLVM_InitializeAllAsmPrinters();
71 });
72}
73
74pub fn llvm_initialize_all_asm_parsers() {
76 with_registry_lock(|| unsafe {
77 LLVM_InitializeAllAsmParsers();
78 });
79}
80
81pub fn llvm_initialize_all_disassemblers() {
83 with_registry_lock(|| unsafe {
84 LLVM_InitializeAllDisassemblers();
85 });
86}
87
88pub fn llvm_initialize_native_target() -> Result<(), String> {
90 if !with_registry_lock(|| unsafe { LLVM_InitializeNativeTarget().to_bool() }) {
91 Ok(())
92 } else {
93 Err("Failed to initialize native target".to_string())
94 }
95}
96
97pub fn llvm_initialize_native_asm_parser() -> Result<(), String> {
99 if !with_registry_lock(|| unsafe { LLVM_InitializeNativeAsmParser().to_bool() }) {
100 Ok(())
101 } else {
102 Err("Failed to initialize native asm parser".to_string())
103 }
104}
105
106pub fn llvm_initialize_native_asm_printer() -> Result<(), String> {
108 if !with_registry_lock(|| unsafe { LLVM_InitializeNativeAsmPrinter().to_bool() }) {
109 Ok(())
110 } else {
111 Err("Failed to initialize native asm printer".to_string())
112 }
113}
114
115pub fn llvm_initialize_native_disassembler() -> Result<(), String> {
117 if !with_registry_lock(|| unsafe { LLVM_InitializeNativeDisassembler().to_bool() }) {
118 Ok(())
119 } else {
120 Err("Failed to initialize native disassembler".to_string())
121 }
122}
123
124pub fn initialize_native() -> Result<(), String> {
126 llvm_initialize_native_target()?;
127 llvm_initialize_native_asm_printer()?;
128 llvm_initialize_native_asm_parser()?;
129 llvm_initialize_native_disassembler()?;
130 Ok(())
131}
132
133pub fn initialize_all() {
135 llvm_initialize_all_target_infos();
136 llvm_initialize_all_targets();
137 llvm_initialize_all_target_mcs();
138 llvm_initialize_all_asm_printers();
139 llvm_initialize_all_asm_parsers();
140 llvm_initialize_all_disassemblers();
141}
142
143mod llvm_target_data {
145 use super::*;
146
147 pub struct LLVMTargetData(LLVMTargetDataRef);
149
150 impl Drop for LLVMTargetData {
151 fn drop(&mut self) {
152 unsafe { LLVMDisposeTargetData(self.0) }
153 }
154 }
155
156 impl LLVMTargetData {
157 pub fn new(layout: &str) -> Self {
161 LLVMTargetData(unsafe { LLVMCreateTargetData(to_c_str(layout).as_ptr()) })
162 }
163
164 pub fn host() -> Result<Self, String> {
166 llvm_initialize_native_target()?;
168
169 let triple_ptr = unsafe { LLVMGetDefaultTargetTriple() };
170 let triple = cstr_to_string(triple_ptr).unwrap_or_default();
171 unsafe { LLVMDisposeMessage(triple_ptr) };
172
173 let mut target = MaybeUninit::uninit();
174 let mut err_string = MaybeUninit::uninit();
175 let failed = unsafe {
176 LLVMGetTargetFromTriple(
177 to_c_str(&triple).as_ptr(),
178 target.as_mut_ptr(),
179 err_string.as_mut_ptr(),
180 )
181 .to_bool()
182 };
183 if failed {
184 unsafe {
185 let err_ptr = err_string.assume_init();
186 let err = cstr_to_string(err_ptr).unwrap_or_default();
187 LLVMDisposeMessage(err_ptr);
188 return Err(err);
189 }
190 }
191
192 let machine = unsafe {
193 LLVMCreateTargetMachine(
194 target.assume_init(),
195 to_c_str(&triple).as_ptr(),
196 to_c_str("").as_ptr(),
198 to_c_str("").as_ptr(),
199 LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
200 LLVMRelocMode::LLVMRelocDefault,
201 LLVMCodeModel::LLVMCodeModelDefault,
202 )
203 };
204 if machine.is_null() {
205 return Err(format!("Failed to create a target machine for {triple}"));
206 }
207
208 let target_data = unsafe { LLVMCreateTargetDataLayout(machine) };
209 unsafe { LLVMDisposeTargetMachine(machine) };
210 Ok(LLVMTargetData(target_data))
211 }
212
213 pub fn copy_string_rep_of_target_data(&self) -> String {
215 let buf_ptr = unsafe { LLVMCopyStringRepOfTargetData(self.0) };
216 let layout = cstr_to_string(buf_ptr).unwrap_or_default();
217 unsafe { LLVMDisposeMessage(buf_ptr) };
218 layout
219 }
220
221 pub fn size_of_type_in_bits(&self, ty: LLVMType) -> u64 {
223 assert!(llvm_type_is_sized(ty));
224 unsafe { LLVMSizeOfTypeInBits(self.0, ty.into()) }
225 }
226
227 pub fn store_size_of_type(&self, ty: LLVMType) -> u64 {
229 assert!(llvm_type_is_sized(ty));
230 unsafe { LLVMStoreSizeOfType(self.0, ty.into()) }
231 }
232
233 pub fn abi_size_of_type(&self, ty: LLVMType) -> u64 {
235 assert!(llvm_type_is_sized(ty));
236 unsafe { LLVMABISizeOfType(self.0, ty.into()) }
237 }
238
239 pub fn abi_alignment_of_type(&self, ty: LLVMType) -> u32 {
241 assert!(llvm_type_is_sized(ty));
242 unsafe { LLVMABIAlignmentOfType(self.0, ty.into()) }
243 }
244
245 pub fn preferred_alignment_of_type(&self, ty: LLVMType) -> u32 {
247 assert!(llvm_type_is_sized(ty));
248 unsafe { LLVMPreferredAlignmentOfType(self.0, ty.into()) }
249 }
250
251 pub fn offset_of_element(&self, struct_ty: LLVMType, index: u32) -> u64 {
253 assert!(llvm_get_type_kind(struct_ty) == LLVMTypeKind::LLVMStructTypeKind);
254 assert!(llvm_type_is_sized(struct_ty));
255 assert!(index < llvm_count_struct_element_types(struct_ty));
256 unsafe { LLVMOffsetOfElement(self.0, struct_ty.into(), index) }
257 }
258
259 pub fn pointer_size_for_as(&self, addr_space: u32) -> u32 {
261 unsafe { LLVMPointerSizeForAS(self.0, addr_space) }
262 }
263 }
264}
265pub use llvm_target_data::LLVMTargetData;