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