• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(non_snake_case)]
2 
3 pub use self::AtomicRmwBinOp::*;
4 pub use self::CallConv::*;
5 pub use self::CodeGenOptSize::*;
6 pub use self::IntPredicate::*;
7 pub use self::Linkage::*;
8 pub use self::MetadataType::*;
9 pub use self::RealPredicate::*;
10 
11 use libc::c_uint;
12 use rustc_data_structures::small_c_str::SmallCStr;
13 use rustc_llvm::RustString;
14 use std::cell::RefCell;
15 use std::ffi::{CStr, CString};
16 use std::str::FromStr;
17 use std::string::FromUtf8Error;
18 
19 pub mod archive_ro;
20 pub mod diagnostic;
21 mod ffi;
22 
23 pub use self::ffi::*;
24 
25 impl LLVMRustResult {
into_result(self) -> Result<(), ()>26     pub fn into_result(self) -> Result<(), ()> {
27         match self {
28             LLVMRustResult::Success => Ok(()),
29             LLVMRustResult::Failure => Err(()),
30         }
31     }
32 }
33 
AddFunctionAttributes<'ll>(llfn: &'ll Value, idx: AttributePlace, attrs: &[&'ll Attribute])34 pub fn AddFunctionAttributes<'ll>(llfn: &'ll Value, idx: AttributePlace, attrs: &[&'ll Attribute]) {
35     unsafe {
36         LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len());
37     }
38 }
39 
AddCallSiteAttributes<'ll>( callsite: &'ll Value, idx: AttributePlace, attrs: &[&'ll Attribute], )40 pub fn AddCallSiteAttributes<'ll>(
41     callsite: &'ll Value,
42     idx: AttributePlace,
43     attrs: &[&'ll Attribute],
44 ) {
45     unsafe {
46         LLVMRustAddCallSiteAttributes(callsite, idx.as_uint(), attrs.as_ptr(), attrs.len());
47     }
48 }
49 
CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute50 pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute {
51     unsafe {
52         LLVMCreateStringAttribute(
53             llcx,
54             attr.as_ptr().cast(),
55             attr.len().try_into().unwrap(),
56             value.as_ptr().cast(),
57             value.len().try_into().unwrap(),
58         )
59     }
60 }
61 
CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute62 pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
63     unsafe {
64         LLVMCreateStringAttribute(
65             llcx,
66             attr.as_ptr().cast(),
67             attr.len().try_into().unwrap(),
68             std::ptr::null(),
69             0,
70         )
71     }
72 }
73 
CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute74 pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
75     unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) }
76 }
77 
CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute78 pub fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
79     unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) }
80 }
81 
CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute82 pub fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
83     unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) }
84 }
85 
CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute86 pub fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
87     unsafe { LLVMRustCreateByValAttr(llcx, ty) }
88 }
89 
CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute90 pub fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
91     unsafe { LLVMRustCreateStructRetAttr(llcx, ty) }
92 }
93 
CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute94 pub fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
95     unsafe { LLVMRustCreateUWTableAttr(llcx, async_) }
96 }
97 
CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute98 pub fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
99     unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) }
100 }
101 
CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute102 pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
103     unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) }
104 }
105 
106 #[derive(Copy, Clone)]
107 pub enum AttributePlace {
108     ReturnValue,
109     Argument(u32),
110     Function,
111 }
112 
113 impl AttributePlace {
as_uint(self) -> c_uint114     pub fn as_uint(self) -> c_uint {
115         match self {
116             AttributePlace::ReturnValue => 0,
117             AttributePlace::Argument(i) => 1 + i,
118             AttributePlace::Function => !0,
119         }
120     }
121 }
122 
123 #[derive(Copy, Clone, PartialEq)]
124 #[repr(C)]
125 pub enum CodeGenOptSize {
126     CodeGenOptSizeNone = 0,
127     CodeGenOptSizeDefault = 1,
128     CodeGenOptSizeAggressive = 2,
129 }
130 
131 impl FromStr for ArchiveKind {
132     type Err = ();
133 
from_str(s: &str) -> Result<Self, Self::Err>134     fn from_str(s: &str) -> Result<Self, Self::Err> {
135         match s {
136             "gnu" => Ok(ArchiveKind::K_GNU),
137             "bsd" => Ok(ArchiveKind::K_BSD),
138             "darwin" => Ok(ArchiveKind::K_DARWIN),
139             "coff" => Ok(ArchiveKind::K_COFF),
140             "aix_big" => Ok(ArchiveKind::K_AIXBIG),
141             _ => Err(()),
142         }
143     }
144 }
145 
SetInstructionCallConv(instr: &Value, cc: CallConv)146 pub fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
147     unsafe {
148         LLVMSetInstructionCallConv(instr, cc as c_uint);
149     }
150 }
SetFunctionCallConv(fn_: &Value, cc: CallConv)151 pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
152     unsafe {
153         LLVMSetFunctionCallConv(fn_, cc as c_uint);
154     }
155 }
156 
157 // Externally visible symbols that might appear in multiple codegen units need to appear in
158 // their own comdat section so that the duplicates can be discarded at link time. This can for
159 // example happen for generics when using multiple codegen units. This function simply uses the
160 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
161 // function.
162 // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
SetUniqueComdat(llmod: &Module, val: &Value)163 pub fn SetUniqueComdat(llmod: &Module, val: &Value) {
164     unsafe {
165         let name = get_value_name(val);
166         LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
167     }
168 }
169 
SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr)170 pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
171     unsafe {
172         LLVMSetUnnamedAddress(global, unnamed);
173     }
174 }
175 
set_thread_local_mode(global: &Value, mode: ThreadLocalMode)176 pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
177     unsafe {
178         LLVMSetThreadLocalMode(global, mode);
179     }
180 }
181 
182 impl AttributeKind {
183     /// Create an LLVM Attribute with no associated value.
create_attr(self, llcx: &Context) -> &Attribute184     pub fn create_attr(self, llcx: &Context) -> &Attribute {
185         unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
186     }
187 }
188 
189 impl MemoryEffects {
190     /// Create an LLVM Attribute with these memory effects.
create_attr(self, llcx: &Context) -> &Attribute191     pub fn create_attr(self, llcx: &Context) -> &Attribute {
192         unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
193     }
194 }
195 
set_section(llglobal: &Value, section_name: &str)196 pub fn set_section(llglobal: &Value, section_name: &str) {
197     let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
198     unsafe {
199         LLVMSetSection(llglobal, section_name_cstr.as_ptr());
200     }
201 }
202 
add_global<'a>(llmod: &'a Module, ty: &'a Type, name: &str) -> &'a Value203 pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name: &str) -> &'a Value {
204     let name_cstr = CString::new(name).expect("unexpected CString error");
205     unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
206 }
207 
set_initializer(llglobal: &Value, constant_val: &Value)208 pub fn set_initializer(llglobal: &Value, constant_val: &Value) {
209     unsafe {
210         LLVMSetInitializer(llglobal, constant_val);
211     }
212 }
213 
set_global_constant(llglobal: &Value, is_constant: bool)214 pub fn set_global_constant(llglobal: &Value, is_constant: bool) {
215     unsafe {
216         LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
217     }
218 }
219 
set_linkage(llglobal: &Value, linkage: Linkage)220 pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
221     unsafe {
222         LLVMRustSetLinkage(llglobal, linkage);
223     }
224 }
225 
set_visibility(llglobal: &Value, visibility: Visibility)226 pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
227     unsafe {
228         LLVMRustSetVisibility(llglobal, visibility);
229     }
230 }
231 
set_alignment(llglobal: &Value, bytes: usize)232 pub fn set_alignment(llglobal: &Value, bytes: usize) {
233     unsafe {
234         ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
235     }
236 }
237 
set_comdat(llmod: &Module, llglobal: &Value, name: &str)238 pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &str) {
239     unsafe {
240         LLVMRustSetComdat(llmod, llglobal, name.as_ptr().cast(), name.len());
241     }
242 }
243 
244 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
get_param(llfn: &Value, index: c_uint) -> &Value245 pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
246     unsafe {
247         assert!(
248             index < LLVMCountParams(llfn),
249             "out of bounds argument access: {} out of {} arguments",
250             index,
251             LLVMCountParams(llfn)
252         );
253         LLVMGetParam(llfn, index)
254     }
255 }
256 
257 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
get_value_name(value: &Value) -> &[u8]258 pub fn get_value_name(value: &Value) -> &[u8] {
259     unsafe {
260         let mut len = 0;
261         let data = LLVMGetValueName2(value, &mut len);
262         std::slice::from_raw_parts(data.cast(), len)
263     }
264 }
265 
266 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
set_value_name(value: &Value, name: &[u8])267 pub fn set_value_name(value: &Value, name: &[u8]) {
268     unsafe {
269         let data = name.as_ptr().cast();
270         LLVMSetValueName2(value, data, name.len());
271     }
272 }
273 
build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error>274 pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
275     let sr = RustString { bytes: RefCell::new(Vec::new()) };
276     f(&sr);
277     String::from_utf8(sr.bytes.into_inner())
278 }
279 
build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8>280 pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
281     let sr = RustString { bytes: RefCell::new(Vec::new()) };
282     f(&sr);
283     sr.bytes.into_inner()
284 }
285 
twine_to_string(tr: &Twine) -> String286 pub fn twine_to_string(tr: &Twine) -> String {
287     unsafe {
288         build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
289     }
290 }
291 
last_error() -> Option<String>292 pub fn last_error() -> Option<String> {
293     unsafe {
294         let cstr = LLVMRustGetLastError();
295         if cstr.is_null() {
296             None
297         } else {
298             let err = CStr::from_ptr(cstr).to_bytes();
299             let err = String::from_utf8_lossy(err).to_string();
300             libc::free(cstr as *mut _);
301             Some(err)
302         }
303     }
304 }
305 
306 pub struct OperandBundleDef<'a> {
307     pub raw: &'a mut ffi::OperandBundleDef<'a>,
308 }
309 
310 impl<'a> OperandBundleDef<'a> {
new(name: &str, vals: &[&'a Value]) -> Self311     pub fn new(name: &str, vals: &[&'a Value]) -> Self {
312         let name = SmallCStr::new(name);
313         let def = unsafe {
314             LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
315         };
316         OperandBundleDef { raw: def }
317     }
318 }
319 
320 impl Drop for OperandBundleDef<'_> {
drop(&mut self)321     fn drop(&mut self) {
322         unsafe {
323             LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
324         }
325     }
326 }
327