]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/llvm/mod.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / compiler / rustc_codegen_llvm / src / llvm / mod.rs
CommitLineData
b7449926 1#![allow(non_snake_case)]
b7449926 2
b7449926 3pub use self::AtomicRmwBinOp::*;
b7449926 4pub use self::CallConv::*;
dfeec247
XL
5pub use self::CodeGenOptSize::*;
6pub use self::IntPredicate::*;
b7449926 7pub use self::Linkage::*;
dfeec247
XL
8pub use self::MetadataType::*;
9pub use self::RealPredicate::*;
b7449926 10
60c5eb7d 11use libc::c_uint;
b7449926 12use rustc_data_structures::small_c_str::SmallCStr;
60c5eb7d 13use rustc_llvm::RustString;
dfeec247 14use std::cell::RefCell;
3dfed10e 15use std::ffi::{CStr, CString};
dfeec247
XL
16use std::str::FromStr;
17use std::string::FromUtf8Error;
b7449926
XL
18
19pub mod archive_ro;
20pub mod diagnostic;
21mod ffi;
22
23pub use self::ffi::*;
24
25impl LLVMRustResult {
26 pub fn into_result(self) -> Result<(), ()> {
27 match self {
28 LLVMRustResult::Success => Ok(()),
29 LLVMRustResult::Failure => Err(()),
30 }
31 }
32}
33
dfeec247 34pub fn AddFunctionAttrStringValue(llfn: &'a Value, idx: AttributePlace, attr: &CStr, value: &CStr) {
b7449926 35 unsafe {
dfeec247 36 LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), value.as_ptr())
b7449926
XL
37 }
38}
39
1b1a35ee
XL
40pub fn AddFunctionAttrString(llfn: &'a Value, idx: AttributePlace, attr: &CStr) {
41 unsafe {
42 LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), std::ptr::null())
43 }
44}
45
b7449926
XL
46#[derive(Copy, Clone)]
47pub enum AttributePlace {
48 ReturnValue,
49 Argument(u32),
50 Function,
51}
52
53impl AttributePlace {
54 pub fn as_uint(self) -> c_uint {
55 match self {
56 AttributePlace::ReturnValue => 0,
57 AttributePlace::Argument(i) => 1 + i,
58 AttributePlace::Function => !0,
59 }
60 }
61}
62
63#[derive(Copy, Clone, PartialEq)]
64#[repr(C)]
65pub enum CodeGenOptSize {
66 CodeGenOptSizeNone = 0,
67 CodeGenOptSizeDefault = 1,
68 CodeGenOptSizeAggressive = 2,
69}
70
71impl FromStr for ArchiveKind {
72 type Err = ();
73
74 fn from_str(s: &str) -> Result<Self, Self::Err> {
75 match s {
76 "gnu" => Ok(ArchiveKind::K_GNU),
77 "bsd" => Ok(ArchiveKind::K_BSD),
74b04a01 78 "darwin" => Ok(ArchiveKind::K_DARWIN),
b7449926
XL
79 "coff" => Ok(ArchiveKind::K_COFF),
80 _ => Err(()),
81 }
82 }
83}
84
b7449926
XL
85pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
86 unsafe {
87 LLVMSetInstructionCallConv(instr, cc as c_uint);
88 }
89}
90pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
91 unsafe {
92 LLVMSetFunctionCallConv(fn_, cc as c_uint);
93 }
94}
95
96// Externally visible symbols that might appear in multiple codegen units need to appear in
97// their own comdat section so that the duplicates can be discarded at link time. This can for
98// example happen for generics when using multiple codegen units. This function simply uses the
99// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
100// function.
0731742a 101// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
b7449926
XL
102pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
103 unsafe {
60c5eb7d
XL
104 let name = get_value_name(val);
105 LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
b7449926
XL
106 }
107}
108
109pub fn UnsetComdat(val: &'a Value) {
110 unsafe {
111 LLVMRustUnsetComdat(val);
112 }
113}
114
ba9703b0 115pub fn SetUnnamedAddress(global: &'a Value, unnamed: UnnamedAddr) {
b7449926 116 unsafe {
ba9703b0 117 LLVMSetUnnamedAddress(global, unnamed);
b7449926
XL
118 }
119}
120
b7449926
XL
121pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
122 unsafe {
123 LLVMSetThreadLocalMode(global, mode);
124 }
125}
126
127impl Attribute {
128 pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
129 unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
130 }
131
132 pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
133 unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
134 }
135
136 pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
137 unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
138 }
139
140 pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
141 if set {
142 self.apply_llfn(idx, llfn);
143 } else {
144 self.unapply_llfn(idx, llfn);
145 }
146 }
147}
148
149// Memory-managed interface to object files.
150
151pub struct ObjectFile {
152 pub llof: &'static mut ffi::ObjectFile,
153}
154
155unsafe impl Send for ObjectFile {}
156
157impl ObjectFile {
158 // This will take ownership of llmb
159 pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
160 unsafe {
161 let llof = LLVMCreateObjectFile(llmb)?;
a1dfa0c6 162 Some(ObjectFile { llof })
b7449926
XL
163 }
164 }
165}
166
167impl Drop for ObjectFile {
168 fn drop(&mut self) {
169 unsafe {
170 LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
171 }
172 }
173}
174
175// Memory-managed interface to section iterators.
176
177pub struct SectionIter<'a> {
178 pub llsi: &'a mut SectionIterator<'a>,
179}
180
181impl Drop for SectionIter<'a> {
182 fn drop(&mut self) {
183 unsafe {
184 LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
185 }
186 }
187}
188
ba9703b0 189pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> {
b7449926
XL
190 unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
191}
192
3dfed10e
XL
193pub fn set_section(llglobal: &Value, section_name: &str) {
194 let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
195 unsafe {
196 LLVMSetSection(llglobal, section_name_cstr.as_ptr());
197 }
198}
199
200pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name: &str) -> &'a Value {
201 let name_cstr = CString::new(name).expect("unexpected CString error");
202 unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
203}
204
205pub fn set_initializer(llglobal: &Value, constant_val: &Value) {
206 unsafe {
207 LLVMSetInitializer(llglobal, constant_val);
208 }
209}
210
211pub fn set_global_constant(llglobal: &Value, is_constant: bool) {
212 unsafe {
213 LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
214 }
215}
216
217pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
218 unsafe {
219 LLVMRustSetLinkage(llglobal, linkage);
220 }
221}
222
fc512014
XL
223pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
224 unsafe {
225 LLVMRustSetVisibility(llglobal, visibility);
226 }
227}
228
3dfed10e
XL
229pub fn set_alignment(llglobal: &Value, bytes: usize) {
230 unsafe {
231 ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
232 }
233}
234
fc512014
XL
235pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &str) {
236 unsafe {
237 LLVMRustSetComdat(llmod, llglobal, name.as_ptr().cast(), name.len());
238 }
239}
240
b7449926 241/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
ba9703b0 242pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
b7449926 243 unsafe {
dfeec247
XL
244 assert!(
245 index < LLVMCountParams(llfn),
246 "out of bounds argument access: {} out of {} arguments",
247 index,
248 LLVMCountParams(llfn)
249 );
b7449926
XL
250 LLVMGetParam(llfn, index)
251 }
252}
253
60c5eb7d 254/// Safe wrapper for `LLVMGetValueName2` into a byte slice
ba9703b0 255pub fn get_value_name(value: &Value) -> &[u8] {
60c5eb7d
XL
256 unsafe {
257 let mut len = 0;
258 let data = LLVMGetValueName2(value, &mut len);
259 std::slice::from_raw_parts(data.cast(), len)
260 }
261}
262
263/// Safe wrapper for `LLVMSetValueName2` from a byte slice
264pub fn set_value_name(value: &Value, name: &[u8]) {
265 unsafe {
266 let data = name.as_ptr().cast();
267 LLVMSetValueName2(value, data, name.len());
268 }
269}
270
b7449926 271pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
dfeec247 272 let sr = RustString { bytes: RefCell::new(Vec::new()) };
b7449926
XL
273 f(&sr);
274 String::from_utf8(sr.bytes.into_inner())
275}
276
3dfed10e
XL
277pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
278 let sr = RustString { bytes: RefCell::new(Vec::new()) };
279 f(&sr);
280 sr.bytes.into_inner()
281}
282
b7449926
XL
283pub fn twine_to_string(tr: &Twine) -> String {
284 unsafe {
dfeec247 285 build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
b7449926
XL
286 }
287}
288
289pub fn last_error() -> Option<String> {
290 unsafe {
291 let cstr = LLVMRustGetLastError();
292 if cstr.is_null() {
293 None
294 } else {
295 let err = CStr::from_ptr(cstr).to_bytes();
296 let err = String::from_utf8_lossy(err).to_string();
297 libc::free(cstr as *mut _);
298 Some(err)
299 }
300 }
301}
302
303pub struct OperandBundleDef<'a> {
304 pub raw: &'a mut ffi::OperandBundleDef<'a>,
305}
306
307impl OperandBundleDef<'a> {
308 pub fn new(name: &str, vals: &[&'a Value]) -> Self {
309 let name = SmallCStr::new(name);
310 let def = unsafe {
311 LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
312 };
313 OperandBundleDef { raw: def }
314 }
315}
316
317impl Drop for OperandBundleDef<'a> {
318 fn drop(&mut self) {
319 unsafe {
320 LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
321 }
322 }
323}