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 AddFunctionAttributes
<'ll
>(llfn
: &'ll Value
, idx
: AttributePlace
, attrs
: &[&'ll Attribute
]) {
36 LLVMRustAddFunctionAttributes(llfn
, idx
.as_uint(), attrs
.as_ptr(), attrs
.len());
40 pub fn AddCallSiteAttributes
<'ll
>(
43 attrs
: &[&'ll Attribute
],
46 LLVMRustAddCallSiteAttributes(callsite
, idx
.as_uint(), attrs
.as_ptr(), attrs
.len());
50 pub fn CreateAttrStringValue
<'ll
>(llcx
: &'ll Context
, attr
: &str, value
: &str) -> &'ll Attribute
{
52 LLVMCreateStringAttribute(
55 attr
.len().try_into().unwrap(),
56 value
.as_ptr().cast(),
57 value
.len().try_into().unwrap(),
62 pub fn CreateAttrString
<'ll
>(llcx
: &'ll Context
, attr
: &str) -> &'ll Attribute
{
64 LLVMCreateStringAttribute(
67 attr
.len().try_into().unwrap(),
74 pub fn CreateAlignmentAttr(llcx
: &Context
, bytes
: u64) -> &Attribute
{
75 unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) }
78 pub fn CreateDereferenceableAttr(llcx
: &Context
, bytes
: u64) -> &Attribute
{
79 unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) }
82 pub fn CreateDereferenceableOrNullAttr(llcx
: &Context
, bytes
: u64) -> &Attribute
{
83 unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) }
86 pub fn CreateByValAttr
<'ll
>(llcx
: &'ll Context
, ty
: &'ll Type
) -> &'ll Attribute
{
87 unsafe { LLVMRustCreateByValAttr(llcx, ty) }
90 pub fn CreateStructRetAttr
<'ll
>(llcx
: &'ll Context
, ty
: &'ll Type
) -> &'ll Attribute
{
91 unsafe { LLVMRustCreateStructRetAttr(llcx, ty) }
94 pub fn CreateUWTableAttr(llcx
: &Context
, async_
: bool
) -> &Attribute
{
95 unsafe { LLVMRustCreateUWTableAttr(llcx, async_) }
98 #[derive(Copy, Clone)]
99 pub enum AttributePlace
{
105 impl AttributePlace
{
106 pub fn as_uint(self) -> c_uint
{
108 AttributePlace
::ReturnValue
=> 0,
109 AttributePlace
::Argument(i
) => 1 + i
,
110 AttributePlace
::Function
=> !0,
115 #[derive(Copy, Clone, PartialEq)]
117 pub enum CodeGenOptSize
{
118 CodeGenOptSizeNone
= 0,
119 CodeGenOptSizeDefault
= 1,
120 CodeGenOptSizeAggressive
= 2,
123 impl FromStr
for ArchiveKind
{
126 fn from_str(s
: &str) -> Result
<Self, Self::Err
> {
128 "gnu" => Ok(ArchiveKind
::K_GNU
),
129 "bsd" => Ok(ArchiveKind
::K_BSD
),
130 "darwin" => Ok(ArchiveKind
::K_DARWIN
),
131 "coff" => Ok(ArchiveKind
::K_COFF
),
137 pub fn SetInstructionCallConv(instr
: &Value
, cc
: CallConv
) {
139 LLVMSetInstructionCallConv(instr
, cc
as c_uint
);
142 pub fn SetFunctionCallConv(fn_
: &Value
, cc
: CallConv
) {
144 LLVMSetFunctionCallConv(fn_
, cc
as c_uint
);
148 // Externally visible symbols that might appear in multiple codegen units need to appear in
149 // their own comdat section so that the duplicates can be discarded at link time. This can for
150 // example happen for generics when using multiple codegen units. This function simply uses the
151 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
153 // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
154 pub fn SetUniqueComdat(llmod
: &Module
, val
: &Value
) {
156 let name
= get_value_name(val
);
157 LLVMRustSetComdat(llmod
, val
, name
.as_ptr().cast(), name
.len());
161 pub fn UnsetComdat(val
: &Value
) {
163 LLVMRustUnsetComdat(val
);
167 pub fn SetUnnamedAddress(global
: &Value
, unnamed
: UnnamedAddr
) {
169 LLVMSetUnnamedAddress(global
, unnamed
);
173 pub fn set_thread_local_mode(global
: &Value
, mode
: ThreadLocalMode
) {
175 LLVMSetThreadLocalMode(global
, mode
);
180 /// Create an LLVM Attribute with no associated value.
181 pub fn create_attr(self, llcx
: &Context
) -> &Attribute
{
182 unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
186 pub fn set_section(llglobal
: &Value
, section_name
: &str) {
187 let section_name_cstr
= CString
::new(section_name
).expect("unexpected CString error");
189 LLVMSetSection(llglobal
, section_name_cstr
.as_ptr());
193 pub fn add_global
<'a
>(llmod
: &'a Module
, ty
: &'a Type
, name
: &str) -> &'a Value
{
194 let name_cstr
= CString
::new(name
).expect("unexpected CString error");
195 unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
198 pub fn set_initializer(llglobal
: &Value
, constant_val
: &Value
) {
200 LLVMSetInitializer(llglobal
, constant_val
);
204 pub fn set_global_constant(llglobal
: &Value
, is_constant
: bool
) {
206 LLVMSetGlobalConstant(llglobal
, if is_constant { ffi::True }
else { ffi::False }
);
210 pub fn set_linkage(llglobal
: &Value
, linkage
: Linkage
) {
212 LLVMRustSetLinkage(llglobal
, linkage
);
216 pub fn set_visibility(llglobal
: &Value
, visibility
: Visibility
) {
218 LLVMRustSetVisibility(llglobal
, visibility
);
222 pub fn set_alignment(llglobal
: &Value
, bytes
: usize) {
224 ffi
::LLVMSetAlignment(llglobal
, bytes
as c_uint
);
228 pub fn set_comdat(llmod
: &Module
, llglobal
: &Value
, name
: &str) {
230 LLVMRustSetComdat(llmod
, llglobal
, name
.as_ptr().cast(), name
.len());
234 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
235 pub fn get_param(llfn
: &Value
, index
: c_uint
) -> &Value
{
238 index
< LLVMCountParams(llfn
),
239 "out of bounds argument access: {} out of {} arguments",
241 LLVMCountParams(llfn
)
243 LLVMGetParam(llfn
, index
)
247 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
248 pub fn get_value_name(value
: &Value
) -> &[u8] {
251 let data
= LLVMGetValueName2(value
, &mut len
);
252 std
::slice
::from_raw_parts(data
.cast(), len
)
256 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
257 pub fn set_value_name(value
: &Value
, name
: &[u8]) {
259 let data
= name
.as_ptr().cast();
260 LLVMSetValueName2(value
, data
, name
.len());
264 pub fn build_string(f
: impl FnOnce(&RustString
)) -> Result
<String
, FromUtf8Error
> {
265 let sr
= RustString { bytes: RefCell::new(Vec::new()) }
;
267 String
::from_utf8(sr
.bytes
.into_inner())
270 pub fn build_byte_buffer(f
: impl FnOnce(&RustString
)) -> Vec
<u8> {
271 let sr
= RustString { bytes: RefCell::new(Vec::new()) }
;
273 sr
.bytes
.into_inner()
276 pub fn twine_to_string(tr
: &Twine
) -> String
{
278 build_string(|s
| LLVMRustWriteTwineToString(tr
, s
)).expect("got a non-UTF8 Twine from LLVM")
282 pub fn last_error() -> Option
<String
> {
284 let cstr
= LLVMRustGetLastError();
288 let err
= CStr
::from_ptr(cstr
).to_bytes();
289 let err
= String
::from_utf8_lossy(err
).to_string();
290 libc
::free(cstr
as *mut _
);
296 pub struct OperandBundleDef
<'a
> {
297 pub raw
: &'a
mut ffi
::OperandBundleDef
<'a
>,
300 impl<'a
> OperandBundleDef
<'a
> {
301 pub fn new(name
: &str, vals
: &[&'a Value
]) -> Self {
302 let name
= SmallCStr
::new(name
);
304 LLVMRustBuildOperandBundleDef(name
.as_ptr(), vals
.as_ptr(), vals
.len() as c_uint
)
306 OperandBundleDef { raw: def }
310 impl Drop
for OperandBundleDef
<'_
> {
313 LLVMRustFreeOperandBundleDef(&mut *(self.raw
as *mut _
));