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