gccjit/
lib.rs

1//! # gccjit.rs - Idiomatic Rust bindings to gccjit
2//!
3//! This library aims to provide idiomatic Rust bindings to gccjit,
4//! the embeddable shared library that provides JIT compilation utilizing
5//! GCC's backend. See https://gcc.gnu.org/wiki/JIT for more information
6//! and for documentation of gccjit itself.
7//!
8//! Each one of the types provided in this crate corresponds to a pointer
9//! type provided by the libgccjit C API. Type conversions are handled by
10//! the ToRValue and ToLValue types, which represent values that can be
11//! rvalues and values that can be lvalues, respectively.
12//!
13//! In addition, these types are all statically verified by the Rust compiler to
14//! never outlive the Context object from which they came, a requirement
15//! to using libgccjit correctly.
16
17#![allow(clippy::needless_lifetimes)]
18
19extern crate gccjit_sys;
20
21mod asm;
22mod types;
23mod context;
24mod object;
25mod location;
26mod field;
27mod structs;
28mod lvalue;
29mod rvalue;
30mod parameter;
31mod function;
32mod block;
33#[cfg(feature="master")]
34mod target_info;
35
36#[cfg(feature="dlopen")]
37use std::ffi::CStr;
38#[cfg(feature="dlopen")]
39use std::sync::OnceLock;
40
41pub use context::Context;
42pub use context::CType;
43pub use context::GlobalKind;
44pub use context::OptimizationLevel;
45pub use context::CompileResult;
46pub use context::OutputKind;
47pub use location::Location;
48pub use object::Object;
49pub use object::ToObject;
50pub use types::FunctionPtrType;
51pub use types::Type;
52pub use types::Typeable;
53pub use field::Field;
54pub use structs::Struct;
55#[cfg(feature="master")]
56pub use lvalue::{VarAttribute, Visibility};
57pub use lvalue::{LValue, TlsModel, ToLValue};
58pub use rvalue::{RValue, ToRValue};
59pub use parameter::Parameter;
60#[cfg(feature="master")]
61pub use function::FnAttribute;
62pub use function::{Function, FunctionType};
63pub use block::{Block, BinaryOp, UnaryOp, ComparisonOp};
64#[cfg(feature="master")]
65pub use target_info::TargetInfo;
66
67use gccjit_sys::Libgccjit;
68
69#[cfg(feature="master")]
70pub fn set_global_personality_function_name(name: &'static [u8]) {
71    debug_assert!(name.ends_with(b"\0"), "Expecting a NUL-terminated C string");
72    with_lib(|lib| {
73        unsafe {
74            lib.gcc_jit_set_global_personality_function_name(name.as_ptr() as *const _);
75        }
76    })
77}
78
79#[derive(Debug)]
80pub struct Version {
81    pub major: i32,
82    pub minor: i32,
83    pub patch: i32,
84}
85
86impl Version {
87    pub fn get() -> Self {
88        with_lib(|lib| {
89            unsafe {
90                Self {
91                    major: lib.gcc_jit_version_major(),
92                    minor: lib.gcc_jit_version_minor(),
93                    patch: lib.gcc_jit_version_patchlevel(),
94                }
95            }
96        })
97    }
98}
99
100#[cfg(feature="master")]
101pub fn is_lto_supported() -> bool {
102    with_lib(|lib| {
103        unsafe {
104            lib.gcc_jit_is_lto_supported()
105        }
106    })
107}
108
109#[cfg(not(feature="dlopen"))]
110fn with_lib<T, F: Fn(&Libgccjit) -> T>(callback: F) -> T {
111    callback(&LIB)
112}
113
114#[cfg(feature="dlopen")]
115fn with_lib<T, F: Fn(&Libgccjit) -> T>(callback: F) -> T {
116    let lib = LIB.get().and_then(|lib| lib.as_ref());
117    match lib {
118        Some(lib) => callback(lib),
119        None => panic!("libgccjit needs to be loaded by calling load() before attempting to do any operation"),
120    }
121}
122
123/// Returns true if the library was loaded correctly, false otherwise.
124#[cfg(feature="dlopen")]
125pub fn load(path: &CStr) -> Result<(), String> {
126    let mut result = Ok(());
127    LIB.get_or_init(|| {
128        let lib = unsafe { Libgccjit::open(path) };
129        match lib {
130            Ok(lib) => Some(lib),
131            Err(error) => {
132                result = Err(error);
133                None
134            },
135        }
136    });
137    result
138}
139
140#[cfg(feature="dlopen")]
141pub fn is_loaded() -> bool {
142    LIB.get().is_some()
143}
144
145#[cfg(feature="dlopen")]
146pub static LIB: OnceLock<Option<Libgccjit>> = OnceLock::new();
147
148// Without the dlopen feature, we avoid using OnceLock as to not have any performance impact.
149#[cfg(not(feature="dlopen"))]
150static LIB: Libgccjit = Libgccjit::new();