1use super::*;
3use super::c_api::*;
4
5use std::path::Path;
6use std::ptr::null_mut;
7use llvm_sys::target::*;
8use llvm_sys::target_machine::*;
9
10static mut UNINITIALIZED: bool = true;
11
12unsafe fn initialize() {
13 if UNINITIALIZED {
14 UNINITIALIZED = false;
15 LLVM_InitializeAllTargets();
16 LLVM_InitializeAllTargetInfos();
17 LLVM_InitializeAllTargetMCs();
18 }
19}
20
21pub fn default_triple() -> String {
23 from_c(unsafe {
24 LLVMGetDefaultTargetTriple()
25 }).unwrap_or(String::new())
26}
27
28#[derive(Copy, Clone, Debug, Eq, PartialEq)]
30pub enum OptLevel {
31 None = 0,
33 Less = 1,
35 Default = 2,
37 Aggressive = 3,
39}
40
41impl OptLevel {
42 pub unsafe fn inner(&self) -> LLVMCodeGenOptLevel {
44 use llvm_sys::target_machine::LLVMCodeGenOptLevel::*;
45 use self::OptLevel::*;
46 match self {
47 &None => LLVMCodeGenLevelNone,
48 &Less => LLVMCodeGenLevelLess,
49 &Default => LLVMCodeGenLevelDefault,
50 &Aggressive => LLVMCodeGenLevelAggressive,
51 }
52 }
53}
54
55#[derive(Copy, Clone, Debug, Eq, PartialEq)]
57pub enum FileType {
58 Assembly,
60 Object,
62}
63
64impl FileType {
65 pub fn inner(&self) -> LLVMCodeGenFileType {
67 use llvm_sys::target_machine::LLVMCodeGenFileType::*;
68 use self::FileType::*;
69 match self {
70 &Assembly => LLVMAssemblyFile,
71 &Object => LLVMObjectFile,
72 }
73 }
74}
75
76#[derive(Copy, Clone, Debug, Eq, PartialEq)]
78pub enum ByteOrdering {
79 BigEndian,
81 LittleEndian,
83}
84
85impl ByteOrdering {
86 pub fn inner(&self) -> LLVMByteOrdering {
88 use llvm_sys::target::LLVMByteOrdering::*;
89 use self::ByteOrdering::*;
90 match self {
91 &BigEndian => LLVMBigEndian,
92 &LittleEndian => LLVMLittleEndian,
93 }
94 }
95}
96
97#[derive(Copy, Clone)]
99pub struct Target {
100 target: LLVMTargetRef,
101}
102
103impl Target {
104 pub fn from_triple(triple: String) -> Result<Target, String> {
106 unsafe {
107 initialize();
108 let mut target: LLVMTargetRef = null_mut();
109 let mut error = null_mut();
110 if LLVMGetTargetFromTriple(
111 into_c(triple).as_ptr(),
112 &mut target as *mut LLVMTargetRef,
113 &mut error as *mut *mut i8,
114 ) == 1 || target.is_null() {
115 Err(from_c(error).unwrap_or(String::new()))
116 } else {
117 Ok(Target {
118 target,
119 })
120 }
121 }
122 }
123
124 pub fn create_machine(&self, triple: String) -> TargetMachine {
126 self.create_machine_with_options(triple, "generic".to_owned(), String::new(), OptLevel::Default)
127 }
128
129 pub fn create_machine_with_options(&self, triple: String, cpu: String, features: String,
131 level: OptLevel) -> TargetMachine {
132 TargetMachine {
133 machine: unsafe {
134 LLVMCreateTargetMachine(
135 self.target,
136 into_c(triple).as_ptr(),
137 into_c(cpu).as_ptr(),
138 into_c(features).as_ptr(),
139 level.inner(),
140 LLVMRelocMode::LLVMRelocDefault,
141 LLVMCodeModel::LLVMCodeModelDefault,
142 )
143 }
144 }
145 }
146
147 pub fn name(&self) -> String {
149 unsafe {
150 from_c(LLVMGetTargetName(self.target)).unwrap_or(String::new())
151 }
152 }
153
154 pub fn description(&self) -> String {
156 unsafe {
157 from_c(LLVMGetTargetDescription(self.target)).unwrap_or(String::new())
158 }
159 }
160}
161
162impl Debug for Target {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 write!(f, "Target({:?}, {:?})", self.name(), self.description())
165 }
166}
167
168impl Display for Target {
169 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
170 write!(f, "{}", self.name())
171 }
172}
173
174#[derive(Clone)]
176pub struct TargetMachine {
177 machine: LLVMTargetMachineRef,
178}
179
180impl TargetMachine {
181 pub fn native() -> Result<TargetMachine, String> {
183 TargetMachine::new(default_triple())
184 }
185
186 pub fn new(triple: String) -> Result<TargetMachine, String> {
188 Ok(Target::from_triple(triple.clone())?.create_machine(triple))
189 }
190
191 pub fn new_with_options(triple: String, cpu: String, features: String,
193 level: OptLevel) -> Result<TargetMachine, String> {
194 Ok(Target::from_triple(triple.clone())?.create_machine_with_options(triple, cpu, features, level))
195 }
196
197 pub fn emit_module_to_file<P>(&self, module: &Module, file: P, file_type: FileType) -> Result<(), String>
199 where P: AsRef<Path> {
200 unsafe {
201 LLVM_InitializeAllAsmPrinters();
202 let file_str = into_c(file.as_ref().to_str().expect("invalid path")).into_raw();
203 let mut error = null_mut();
204 let flag = LLVMTargetMachineEmitToFile(
205 self.machine,
206 module.module.unwrap(),
207 file_str,
208 file_type.inner(),
209 &mut error as *mut *mut i8,
210 ) == 1;
211 CString::from_raw(file_str);
212 if flag {
213 Err(from_c(error).unwrap_or(String::new()))
214 } else {
215 Ok(())
216 }
217 }
218 }
219
220 pub fn data_layout(&self) -> TargetData {
222 TargetData {
223 data: unsafe {
224 LLVMCreateTargetDataLayout(self.machine)
225 }
226 }
227 }
228
229 pub fn target(&self) -> Target {
231 Target {
232 target: unsafe{
233 LLVMGetTargetMachineTarget(self.machine)
234 }
235 }
236 }
237
238 pub fn triple(&self) -> String {
240 unsafe {
241 from_c(LLVMGetTargetMachineTriple(self.machine)).unwrap_or(String::new())
242 }
243 }
244
245 pub fn cpu(&self) -> String {
247 unsafe {
248 from_c(LLVMGetTargetMachineCPU(self.machine)).unwrap_or(String::new())
249 }
250 }
251
252 pub fn features(&self) -> String {
254 unsafe {
255 from_c(LLVMGetTargetMachineFeatureString(self.machine)).unwrap_or(String::new())
256 }
257 }
258}
259
260impl Debug for TargetMachine {
261 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262 write!(f, "TargetMachine({:?}, {:?}, {:?}, {:?})", self.target(), self.triple(), self.cpu(), self.features())
263 }
264}
265
266impl Drop for TargetMachine {
267 fn drop(&mut self) {
268 unsafe {
269 LLVMDisposeTargetMachine(self.machine);
270 }
271 }
272}
273
274#[derive(Clone)]
276pub struct TargetData {
277 pub(crate) data: LLVMTargetDataRef,
278}
279
280impl TargetData {
281 pub fn byte_order(&self) -> ByteOrdering {
283 unsafe {
284 use llvm_sys::target::LLVMByteOrdering::*;
285 use self::ByteOrdering::*;
286 match LLVMByteOrder(self.data) {
287 LLVMBigEndian => BigEndian,
288 LLVMLittleEndian => LittleEndian,
289 }
290 }
291 }
292
293 pub fn size_of_ptr(&self) -> u64 {
295 unsafe {
296 LLVMPointerSize(self.data) as u64
297 }
298 }
299
300 pub fn bit_size_of_ptr(&self) -> u64 {
302 unsafe {
303 LLVMPointerSize(self.data) as u64 * 8
304 }
305 }
306
307 pub fn offset_of_element(&self, ty: Type, index: u32) -> u64 {
309 unsafe {
310 LLVMOffsetOfElement(self.data, ty.ty, index)
311 }
312 }
313
314 pub fn element_at_offset(&self, ty: Type, offset: u64) -> u32 {
316 unsafe {
317 LLVMElementAtOffset(self.data, ty.ty, offset)
318 }
319 }
320
321 pub fn size_of(&self, ty: Type) -> u64 {
323 unsafe {
324 LLVMABISizeOfType(self.data, ty.ty)
325 }
326 }
327
328 pub fn bit_size_of(&self, ty: Type) -> u64 {
330 unsafe {
331 LLVMSizeOfTypeInBits(self.data, ty.ty)
332 }
333 }
334
335 pub fn store_size_of(&self, ty: Type) -> u64 {
337 unsafe {
338 LLVMStoreSizeOfType(self.data, ty.ty)
339 }
340 }
341
342 pub fn abi_alignment_of(&self, ty: Type) -> u32 {
344 unsafe {
345 LLVMABIAlignmentOfType(self.data, ty.ty)
346 }
347 }
348
349 pub fn call_frame_alignment_of(&self, ty: Type) -> u32 {
351 unsafe {
352 LLVMCallFrameAlignmentOfType(self.data, ty.ty)
353 }
354 }
355
356 pub fn preferred_alignment_of(&self, ty: Type) -> u32 {
358 unsafe {
359 LLVMPreferredAlignmentOfType(self.data, ty.ty)
360 }
361 }
362}
363
364impl Debug for TargetData {
365 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366 write!(f, "TargetData({:?})", self.to_string())
367 }
368}
369
370impl Display for TargetData {
371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372 write!(f, "{}", unsafe {
373 from_c(LLVMCopyStringRepOfTargetData(self.data)).unwrap_or(String::new())
374 })
375 }
376}
377
378impl Drop for TargetData {
379 fn drop(&mut self) {
380 unsafe {
381 LLVMDisposeTargetData(self.data);
382 }
383 }
384}