Skip to main content

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(any(feature="dlopen", feature="master"))]
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;
53#[cfg(feature="master")]
54pub use types::TypeAttribute;
55pub use field::Field;
56pub use structs::Struct;
57#[cfg(feature="master")]
58pub use lvalue::{VarAttribute, Visibility};
59pub use lvalue::{LValue, TlsModel, ToLValue};
60pub use rvalue::{RValue, ToRValue};
61pub use parameter::Parameter;
62#[cfg(feature="master")]
63pub use function::FnAttribute;
64pub use function::{Function, FunctionType};
65pub use block::{Block, BinaryOp, UnaryOp, ComparisonOp};
66#[cfg(feature="master")]
67pub use target_info::TargetInfo;
68
69use gccjit_sys::Libgccjit;
70
71#[cfg(feature="master")]
72pub fn set_global_personality_function_name(name: &'static [u8]) {
73    debug_assert!(name.ends_with(b"\0"), "Expecting a NUL-terminated C string");
74    with_lib(|lib| {
75        unsafe {
76            lib.gcc_jit_set_global_personality_function_name(name.as_ptr() as *const _);
77        }
78    })
79}
80
81#[derive(Debug)]
82pub struct Version {
83    pub major: i32,
84    pub minor: i32,
85    pub patch: i32,
86}
87
88impl Version {
89    pub fn get() -> Self {
90        with_lib(|lib| {
91            unsafe {
92                Self {
93                    major: lib.gcc_jit_version_major(),
94                    minor: lib.gcc_jit_version_minor(),
95                    patch: lib.gcc_jit_version_patchlevel(),
96                }
97            }
98        })
99    }
100}
101
102#[cfg(feature="master")]
103pub fn is_lto_supported() -> bool {
104    with_lib(|lib| {
105        unsafe {
106            lib.gcc_jit_is_lto_supported()
107        }
108    })
109}
110
111#[cfg(not(feature="dlopen"))]
112fn with_lib<T, F: Fn(&Libgccjit) -> T>(callback: F) -> T {
113    callback(&LIB)
114}
115
116#[cfg(feature="dlopen")]
117fn with_lib<T, F: Fn(&Libgccjit) -> T>(callback: F) -> T {
118    let lib = LIB.get().and_then(|lib| lib.as_ref());
119    match lib {
120        Some(lib) => callback(lib),
121        None => panic!("libgccjit needs to be loaded by calling load() before attempting to do any operation"),
122    }
123}
124
125/// Returns true if the library was loaded correctly, false otherwise.
126#[cfg(feature="dlopen")]
127pub fn load(path: &CStr) -> Result<(), String> {
128    let mut result = Ok(());
129    LIB.get_or_init(|| {
130        let lib = unsafe { Libgccjit::open(path) };
131        match lib {
132            Ok(lib) => Some(lib),
133            Err(error) => {
134                result = Err(error);
135                None
136            },
137        }
138    });
139    result
140}
141
142#[cfg(feature="dlopen")]
143pub fn is_loaded() -> bool {
144    LIB.get().is_some()
145}
146
147#[cfg(feature="dlopen")]
148pub static LIB: OnceLock<Option<Libgccjit>> = OnceLock::new();
149
150// Without the dlopen feature, we avoid using OnceLock as to not have any performance impact.
151#[cfg(not(feature="dlopen"))]
152static LIB: Libgccjit = Libgccjit::new();
153
154#[cfg(feature="master")]
155pub fn set_lang_name(lang_name: &'static CStr) {
156    unsafe {
157        with_lib(|lib| {
158            lib.gcc_jit_set_lang_name(lang_name.as_ptr());
159        });
160    }
161}