inkwell/
memory_buffer.rs
1use llvm_sys::core::{
2 LLVMCreateMemoryBufferWithContentsOfFile, LLVMCreateMemoryBufferWithMemoryRange,
3 LLVMCreateMemoryBufferWithMemoryRangeCopy, LLVMCreateMemoryBufferWithSTDIN, LLVMDisposeMemoryBuffer,
4 LLVMGetBufferSize, LLVMGetBufferStart,
5};
6#[allow(deprecated)]
7use llvm_sys::object::LLVMCreateObjectFile;
8use llvm_sys::prelude::LLVMMemoryBufferRef;
9
10use crate::object_file::ObjectFile;
11use crate::support::{to_c_str, LLVMString};
12
13use std::mem::{forget, MaybeUninit};
14use std::path::Path;
15use std::ptr;
16use std::slice;
17
18#[derive(Debug)]
19pub struct MemoryBuffer {
20 pub(crate) memory_buffer: LLVMMemoryBufferRef,
21}
22
23impl MemoryBuffer {
24 pub unsafe fn new(memory_buffer: LLVMMemoryBufferRef) -> Self {
25 assert!(!memory_buffer.is_null());
26
27 MemoryBuffer { memory_buffer }
28 }
29
30 pub fn as_mut_ptr(&self) -> LLVMMemoryBufferRef {
31 self.memory_buffer
32 }
33
34 pub fn create_from_file(path: &Path) -> Result<Self, LLVMString> {
35 let path = to_c_str(path.to_str().expect("Did not find a valid Unicode path string"));
36 let mut memory_buffer = ptr::null_mut();
37 let mut err_string = MaybeUninit::uninit();
38
39 let return_code = unsafe {
40 LLVMCreateMemoryBufferWithContentsOfFile(
41 path.as_ptr() as *const ::libc::c_char,
42 &mut memory_buffer,
43 err_string.as_mut_ptr(),
44 )
45 };
46
47 if return_code == 1 {
49 unsafe {
50 return Err(LLVMString::new(err_string.assume_init()));
51 }
52 }
53
54 unsafe { Ok(MemoryBuffer::new(memory_buffer)) }
55 }
56
57 pub fn create_from_stdin() -> Result<Self, LLVMString> {
58 let mut memory_buffer = ptr::null_mut();
59 let mut err_string = MaybeUninit::uninit();
60
61 let return_code = unsafe { LLVMCreateMemoryBufferWithSTDIN(&mut memory_buffer, err_string.as_mut_ptr()) };
62
63 if return_code == 1 {
65 unsafe {
66 return Err(LLVMString::new(err_string.assume_init()));
67 }
68 }
69
70 unsafe { Ok(MemoryBuffer::new(memory_buffer)) }
71 }
72
73 pub fn create_from_memory_range(input: &[u8], name: &str) -> Self {
77 let name_c_string = to_c_str(name);
78
79 let memory_buffer = unsafe {
80 LLVMCreateMemoryBufferWithMemoryRange(
81 input.as_ptr() as *const ::libc::c_char,
82 input.len(),
83 name_c_string.as_ptr(),
84 false as i32,
85 )
86 };
87
88 unsafe { MemoryBuffer::new(memory_buffer) }
89 }
90
91 pub fn create_from_memory_range_copy(input: &[u8], name: &str) -> Self {
97 let name_c_string = to_c_str(name);
98
99 let memory_buffer = unsafe {
100 LLVMCreateMemoryBufferWithMemoryRangeCopy(
101 input.as_ptr() as *const ::libc::c_char,
102 input.len(),
103 name_c_string.as_ptr(),
104 )
105 };
106
107 unsafe { MemoryBuffer::new(memory_buffer) }
108 }
109
110 pub fn as_slice(&self) -> &[u8] {
112 unsafe {
113 let start = LLVMGetBufferStart(self.memory_buffer);
114
115 slice::from_raw_parts(start as *const _, self.get_size())
116 }
117 }
118
119 pub fn get_size(&self) -> usize {
121 unsafe { LLVMGetBufferSize(self.memory_buffer) }
122 }
123
124 pub fn create_object_file(self) -> Result<ObjectFile, ()> {
127 #[allow(deprecated)]
128 let object_file = unsafe { LLVMCreateObjectFile(self.memory_buffer) };
129
130 forget(self);
131
132 if object_file.is_null() {
133 return Err(());
134 }
135
136 unsafe { Ok(ObjectFile::new(object_file)) }
137 }
138}
139
140impl Drop for MemoryBuffer {
141 fn drop(&mut self) {
142 unsafe {
143 LLVMDisposeMemoryBuffer(self.memory_buffer);
144 }
145 }
146}