1 #![allow(non_snake_case)]
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
::*;
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
;
26 pub fn into_result(self) -> Result
<(), ()> {
28 LLVMRustResult
::Success
=> Ok(()),
29 LLVMRustResult
::Failure
=> Err(()),
34 pub fn AddFunctionAttrStringValue(llfn
: &'a Value
, idx
: AttributePlace
, attr
: &CStr
, value
: &CStr
) {
36 LLVMRustAddFunctionAttrStringValue(llfn
, idx
.as_uint(), attr
.as_ptr(), value
.as_ptr())
40 pub fn AddFunctionAttrString(llfn
: &'a Value
, idx
: AttributePlace
, attr
: &CStr
) {
42 LLVMRustAddFunctionAttrStringValue(llfn
, idx
.as_uint(), attr
.as_ptr(), std
::ptr
::null())
46 pub fn AddCallSiteAttrString(callsite
: &Value
, idx
: AttributePlace
, attr
: &CStr
) {
47 unsafe { LLVMRustAddCallSiteAttrString(callsite, idx.as_uint(), attr.as_ptr()) }
50 #[derive(Copy, Clone)]
51 pub enum AttributePlace
{
58 pub fn as_uint(self) -> c_uint
{
60 AttributePlace
::ReturnValue
=> 0,
61 AttributePlace
::Argument(i
) => 1 + i
,
62 AttributePlace
::Function
=> !0,
67 #[derive(Copy, Clone, PartialEq)]
69 pub enum CodeGenOptSize
{
70 CodeGenOptSizeNone
= 0,
71 CodeGenOptSizeDefault
= 1,
72 CodeGenOptSizeAggressive
= 2,
75 impl FromStr
for ArchiveKind
{
78 fn from_str(s
: &str) -> Result
<Self, Self::Err
> {
80 "gnu" => Ok(ArchiveKind
::K_GNU
),
81 "bsd" => Ok(ArchiveKind
::K_BSD
),
82 "darwin" => Ok(ArchiveKind
::K_DARWIN
),
83 "coff" => Ok(ArchiveKind
::K_COFF
),
89 pub fn SetInstructionCallConv(instr
: &'a Value
, cc
: CallConv
) {
91 LLVMSetInstructionCallConv(instr
, cc
as c_uint
);
94 pub fn SetFunctionCallConv(fn_
: &'a Value
, cc
: CallConv
) {
96 LLVMSetFunctionCallConv(fn_
, cc
as c_uint
);
100 // Externally visible symbols that might appear in multiple codegen units need to appear in
101 // their own comdat section so that the duplicates can be discarded at link time. This can for
102 // example happen for generics when using multiple codegen units. This function simply uses the
103 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
105 // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
106 pub fn SetUniqueComdat(llmod
: &Module
, val
: &'a Value
) {
108 let name
= get_value_name(val
);
109 LLVMRustSetComdat(llmod
, val
, name
.as_ptr().cast(), name
.len());
113 pub fn UnsetComdat(val
: &'a Value
) {
115 LLVMRustUnsetComdat(val
);
119 pub fn SetUnnamedAddress(global
: &'a Value
, unnamed
: UnnamedAddr
) {
121 LLVMSetUnnamedAddress(global
, unnamed
);
125 pub fn set_thread_local_mode(global
: &'a Value
, mode
: ThreadLocalMode
) {
127 LLVMSetThreadLocalMode(global
, mode
);
132 pub fn apply_llfn(&self, idx
: AttributePlace
, llfn
: &Value
) {
133 unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
136 pub fn apply_callsite(&self, idx
: AttributePlace
, callsite
: &Value
) {
137 unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
140 pub fn unapply_llfn(&self, idx
: AttributePlace
, llfn
: &Value
) {
141 unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
144 pub fn toggle_llfn(&self, idx
: AttributePlace
, llfn
: &Value
, set
: bool
) {
146 self.apply_llfn(idx
, llfn
);
148 self.unapply_llfn(idx
, llfn
);
153 pub fn set_section(llglobal
: &Value
, section_name
: &str) {
154 let section_name_cstr
= CString
::new(section_name
).expect("unexpected CString error");
156 LLVMSetSection(llglobal
, section_name_cstr
.as_ptr());
160 pub fn add_global
<'a
>(llmod
: &'a Module
, ty
: &'a Type
, name
: &str) -> &'a Value
{
161 let name_cstr
= CString
::new(name
).expect("unexpected CString error");
162 unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
165 pub fn set_initializer(llglobal
: &Value
, constant_val
: &Value
) {
167 LLVMSetInitializer(llglobal
, constant_val
);
171 pub fn set_global_constant(llglobal
: &Value
, is_constant
: bool
) {
173 LLVMSetGlobalConstant(llglobal
, if is_constant { ffi::True }
else { ffi::False }
);
177 pub fn set_linkage(llglobal
: &Value
, linkage
: Linkage
) {
179 LLVMRustSetLinkage(llglobal
, linkage
);
183 pub fn set_visibility(llglobal
: &Value
, visibility
: Visibility
) {
185 LLVMRustSetVisibility(llglobal
, visibility
);
189 pub fn set_alignment(llglobal
: &Value
, bytes
: usize) {
191 ffi
::LLVMSetAlignment(llglobal
, bytes
as c_uint
);
195 pub fn set_comdat(llmod
: &Module
, llglobal
: &Value
, name
: &str) {
197 LLVMRustSetComdat(llmod
, llglobal
, name
.as_ptr().cast(), name
.len());
201 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
202 pub fn get_param(llfn
: &Value
, index
: c_uint
) -> &Value
{
205 index
< LLVMCountParams(llfn
),
206 "out of bounds argument access: {} out of {} arguments",
208 LLVMCountParams(llfn
)
210 LLVMGetParam(llfn
, index
)
214 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
215 pub fn get_value_name(value
: &Value
) -> &[u8] {
218 let data
= LLVMGetValueName2(value
, &mut len
);
219 std
::slice
::from_raw_parts(data
.cast(), len
)
223 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
224 pub fn set_value_name(value
: &Value
, name
: &[u8]) {
226 let data
= name
.as_ptr().cast();
227 LLVMSetValueName2(value
, data
, name
.len());
231 pub fn build_string(f
: impl FnOnce(&RustString
)) -> Result
<String
, FromUtf8Error
> {
232 let sr
= RustString { bytes: RefCell::new(Vec::new()) }
;
234 String
::from_utf8(sr
.bytes
.into_inner())
237 pub fn build_byte_buffer(f
: impl FnOnce(&RustString
)) -> Vec
<u8> {
238 let sr
= RustString { bytes: RefCell::new(Vec::new()) }
;
240 sr
.bytes
.into_inner()
243 pub fn twine_to_string(tr
: &Twine
) -> String
{
245 build_string(|s
| LLVMRustWriteTwineToString(tr
, s
)).expect("got a non-UTF8 Twine from LLVM")
249 pub fn last_error() -> Option
<String
> {
251 let cstr
= LLVMRustGetLastError();
255 let err
= CStr
::from_ptr(cstr
).to_bytes();
256 let err
= String
::from_utf8_lossy(err
).to_string();
257 libc
::free(cstr
as *mut _
);
263 pub struct OperandBundleDef
<'a
> {
264 pub raw
: &'a
mut ffi
::OperandBundleDef
<'a
>,
267 impl OperandBundleDef
<'a
> {
268 pub fn new(name
: &str, vals
: &[&'a Value
]) -> Self {
269 let name
= SmallCStr
::new(name
);
271 LLVMRustBuildOperandBundleDef(name
.as_ptr(), vals
.as_ptr(), vals
.len() as c_uint
)
273 OperandBundleDef { raw: def }
277 impl Drop
for OperandBundleDef
<'a
> {
280 LLVMRustFreeOperandBundleDef(&mut *(self.raw
as *mut _
));