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