]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_llvm/llvm/mod.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_codegen_llvm / llvm / mod.rs
CommitLineData
b7449926 1#![allow(non_snake_case)]
b7449926
XL
2
3pub use self::IntPredicate::*;
4pub use self::RealPredicate::*;
5pub use self::AtomicRmwBinOp::*;
6pub use self::MetadataType::*;
7pub use self::CodeGenOptSize::*;
8pub use self::CallConv::*;
9pub use self::Linkage::*;
10
11use std::str::FromStr;
12use std::string::FromUtf8Error;
b7449926
XL
13use std::ffi::CStr;
14use std::cell::RefCell;
60c5eb7d 15use libc::c_uint;
b7449926 16use rustc_data_structures::small_c_str::SmallCStr;
60c5eb7d 17use rustc_llvm::RustString;
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
34pub fn AddFunctionAttrStringValue(llfn: &'a Value,
35 idx: AttributePlace,
36 attr: &CStr,
37 value: &CStr) {
38 unsafe {
39 LLVMRustAddFunctionAttrStringValue(llfn,
40 idx.as_uint(),
41 attr.as_ptr(),
42 value.as_ptr())
43 }
44}
45
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),
78 "coff" => Ok(ArchiveKind::K_COFF),
79 _ => Err(()),
80 }
81 }
82}
83
b7449926
XL
84pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
85 unsafe {
86 LLVMSetInstructionCallConv(instr, cc as c_uint);
87 }
88}
89pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
90 unsafe {
91 LLVMSetFunctionCallConv(fn_, cc as c_uint);
92 }
93}
94
95// Externally visible symbols that might appear in multiple codegen units need to appear in
96// their own comdat section so that the duplicates can be discarded at link time. This can for
97// example happen for generics when using multiple codegen units. This function simply uses the
98// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
99// function.
0731742a 100// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
b7449926
XL
101pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
102 unsafe {
60c5eb7d
XL
103 let name = get_value_name(val);
104 LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
b7449926
XL
105 }
106}
107
108pub fn UnsetComdat(val: &'a Value) {
109 unsafe {
110 LLVMRustUnsetComdat(val);
111 }
112}
113
114pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
115 unsafe {
116 LLVMSetUnnamedAddr(global, unnamed as Bool);
117 }
118}
119
120pub fn set_thread_local(global: &'a Value, is_thread_local: bool) {
121 unsafe {
122 LLVMSetThreadLocal(global, is_thread_local as Bool);
123 }
124}
125pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
126 unsafe {
127 LLVMSetThreadLocalMode(global, mode);
128 }
129}
130
131impl Attribute {
132 pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
133 unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
134 }
135
136 pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
137 unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
138 }
139
140 pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
141 unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
142 }
143
144 pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
145 if set {
146 self.apply_llfn(idx, llfn);
147 } else {
148 self.unapply_llfn(idx, llfn);
149 }
150 }
151}
152
153// Memory-managed interface to object files.
154
155pub struct ObjectFile {
156 pub llof: &'static mut ffi::ObjectFile,
157}
158
159unsafe impl Send for ObjectFile {}
160
161impl ObjectFile {
162 // This will take ownership of llmb
163 pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
164 unsafe {
165 let llof = LLVMCreateObjectFile(llmb)?;
a1dfa0c6 166 Some(ObjectFile { llof })
b7449926
XL
167 }
168 }
169}
170
171impl Drop for ObjectFile {
172 fn drop(&mut self) {
173 unsafe {
174 LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
175 }
176 }
177}
178
179// Memory-managed interface to section iterators.
180
181pub struct SectionIter<'a> {
182 pub llsi: &'a mut SectionIterator<'a>,
183}
184
185impl Drop for SectionIter<'a> {
186 fn drop(&mut self) {
187 unsafe {
188 LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
189 }
190 }
191}
192
193pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
194 unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
195}
196
197/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
198pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
199 unsafe {
200 assert!(index < LLVMCountParams(llfn),
201 "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
202 LLVMGetParam(llfn, index)
203 }
204}
205
60c5eb7d
XL
206/// Safe wrapper for `LLVMGetValueName2` into a byte slice
207pub fn get_value_name(value: &'a Value) -> &'a [u8] {
208 unsafe {
209 let mut len = 0;
210 let data = LLVMGetValueName2(value, &mut len);
211 std::slice::from_raw_parts(data.cast(), len)
212 }
213}
214
215/// Safe wrapper for `LLVMSetValueName2` from a byte slice
216pub fn set_value_name(value: &Value, name: &[u8]) {
217 unsafe {
218 let data = name.as_ptr().cast();
219 LLVMSetValueName2(value, data, name.len());
220 }
221}
222
b7449926
XL
223pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
224 let sr = RustString {
225 bytes: RefCell::new(Vec::new()),
226 };
227 f(&sr);
228 String::from_utf8(sr.bytes.into_inner())
229}
230
231pub fn twine_to_string(tr: &Twine) -> String {
232 unsafe {
233 build_string(|s| LLVMRustWriteTwineToString(tr, s))
234 .expect("got a non-UTF8 Twine from LLVM")
235 }
236}
237
238pub fn last_error() -> Option<String> {
239 unsafe {
240 let cstr = LLVMRustGetLastError();
241 if cstr.is_null() {
242 None
243 } else {
244 let err = CStr::from_ptr(cstr).to_bytes();
245 let err = String::from_utf8_lossy(err).to_string();
246 libc::free(cstr as *mut _);
247 Some(err)
248 }
249 }
250}
251
252pub struct OperandBundleDef<'a> {
253 pub raw: &'a mut ffi::OperandBundleDef<'a>,
254}
255
256impl OperandBundleDef<'a> {
257 pub fn new(name: &str, vals: &[&'a Value]) -> Self {
258 let name = SmallCStr::new(name);
259 let def = unsafe {
260 LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
261 };
262 OperandBundleDef { raw: def }
263 }
264}
265
266impl Drop for OperandBundleDef<'a> {
267 fn drop(&mut self) {
268 unsafe {
269 LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
270 }
271 }
272}