use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use llvm_native_core::module::Module;
use llvm_native_core::value::ValueRef;
#[derive(Debug, Clone)]
pub struct JITSymbol {
pub address: usize,
pub flags: JITSymbolFlags,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct JITSymbolFlags {
pub is_callable: bool,
pub is_exported: bool,
pub is_weak: bool,
pub is_common: bool,
pub is_absolute: bool,
}
impl Default for JITSymbolFlags {
fn default() -> Self {
Self {
is_callable: false,
is_exported: true,
is_weak: false,
is_common: false,
is_absolute: false,
}
}
}
impl JITSymbolFlags {
pub fn exported_function() -> Self {
Self {
is_callable: true,
is_exported: true,
..Default::default()
}
}
pub fn internal_data() -> Self {
Self {
is_exported: false,
..Default::default()
}
}
}
#[derive(Debug)]
pub struct JITDylib {
pub name: String,
symbols: HashMap<String, JITSymbol>,
modules: Vec<Module>,
pub allow_lazy_compilation: bool,
pub search_order: Vec<String>,
}
impl JITDylib {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
symbols: HashMap::new(),
modules: Vec::new(),
allow_lazy_compilation: true,
search_order: Vec::new(),
}
}
pub fn define_symbol(&mut self, name: &str, address: usize, flags: JITSymbolFlags) {
self.symbols
.insert(name.to_string(), JITSymbol { address, flags });
}
pub fn lookup(&self, name: &str) -> Option<&JITSymbol> {
self.symbols.get(name)
}
pub fn add_module(&mut self, module: Module) {
self.modules.push(module);
}
}
pub trait JITLayer {
fn add(&mut self, dylib: &mut JITDylib, module: Module) -> Result<(), String>;
fn emit(&mut self) -> Result<(), String>;
fn find_symbol(&self, name: &str, exported_only: bool) -> Option<JITSymbol>;
fn layer_name(&self) -> &'static str;
}
pub struct IRTransformLayer {
next_layer: Box<dyn JITLayer>,
transforms: Vec<Box<dyn Fn(&Module) -> Module + Send + Sync>>,
}
impl IRTransformLayer {
pub fn new(next_layer: Box<dyn JITLayer>) -> Self {
Self {
next_layer,
transforms: Vec::new(),
}
}
pub fn add_transform(&mut self, transform: Box<dyn Fn(&Module) -> Module + Send + Sync>) {
self.transforms.push(transform);
}
fn apply_transforms(&self, module: Module) -> Module {
let mut result = module;
for transform in &self.transforms {
result = transform(&result);
}
result
}
}
impl JITLayer for IRTransformLayer {
fn add(&mut self, dylib: &mut JITDylib, module: Module) -> Result<(), String> {
let transformed = self.apply_transforms(module);
self.next_layer.add(dylib, transformed)
}
fn emit(&mut self) -> Result<(), String> {
self.next_layer.emit()
}
fn find_symbol(&self, name: &str, exported_only: bool) -> Option<JITSymbol> {
self.next_layer.find_symbol(name, exported_only)
}
fn layer_name(&self) -> &'static str {
"IRTransformLayer"
}
}
pub struct CompileLayer {
next_layer: Box<dyn JITLayer>,
target_triple: String,
opt_level: u8,
}
impl CompileLayer {
pub fn new(next_layer: Box<dyn JITLayer>, target_triple: &str) -> Self {
Self {
next_layer,
target_triple: target_triple.to_string(),
opt_level: 2,
}
}
pub fn set_opt_level(&mut self, level: u8) {
self.opt_level = level;
}
fn compile_module(&self, module: Module) -> Result<Module, String> {
let mut compiled = module.clone();
compiled.set_target_triple(&self.target_triple);
Ok(compiled)
}
}
impl JITLayer for CompileLayer {
fn add(&mut self, dylib: &mut JITDylib, module: Module) -> Result<(), String> {
let compiled = self.compile_module(module)?;
self.next_layer.add(dylib, compiled)
}
fn emit(&mut self) -> Result<(), String> {
self.next_layer.emit()
}
fn find_symbol(&self, name: &str, exported_only: bool) -> Option<JITSymbol> {
self.next_layer.find_symbol(name, exported_only)
}
fn layer_name(&self) -> &'static str {
"CompileLayer"
}
}
pub struct ObjectLinkingLayer {
code_segments: Vec<CodeSegment>,
linked_symbols: HashMap<String, JITSymbol>,
mem_manager: JITMemoryManager,
}
#[derive(Debug)]
struct CodeSegment {
address: usize,
size: usize,
is_executable: bool,
is_writable: bool,
owner_dylib: String,
}
impl ObjectLinkingLayer {
pub fn new() -> Self {
Self {
code_segments: Vec::new(),
linked_symbols: HashMap::new(),
mem_manager: JITMemoryManager::new(),
}
}
fn link_module(&mut self, dylib_name: &str, module: &Module) -> Result<(), String> {
let code_size = 4096; let addr = self.mem_manager.allocate(code_size, true, true)?;
self.code_segments.push(CodeSegment {
address: addr,
size: code_size,
is_executable: true,
is_writable: false,
owner_dylib: dylib_name.to_string(),
});
for func in &module.functions {
let name = &func.borrow().name;
let symbol_addr = addr;
self.linked_symbols.insert(
name.clone(),
JITSymbol {
address: symbol_addr,
flags: JITSymbolFlags::exported_function(),
},
);
}
Ok(())
}
}
impl JITLayer for ObjectLinkingLayer {
fn add(&mut self, dylib: &mut JITDylib, module: Module) -> Result<(), String> {
self.link_module(&dylib.name, &module)?;
Ok(())
}
fn emit(&mut self) -> Result<(), String> {
for segment in &mut self.code_segments {
if segment.is_writable {
self.mem_manager
.make_executable(segment.address, segment.size)?;
segment.is_executable = true;
segment.is_writable = false;
}
}
Ok(())
}
fn find_symbol(&self, name: &str, exported_only: bool) -> Option<JITSymbol> {
self.linked_symbols.get(name).cloned()
}
fn layer_name(&self) -> &'static str {
"ObjectLinkingLayer"
}
}
pub struct LazyCompileLayer {
next_layer: Box<dyn JITLayer>,
deferred: HashMap<String, (String, Module)>,
enabled: bool,
}
impl LazyCompileLayer {
pub fn new(next_layer: Box<dyn JITLayer>) -> Self {
Self {
next_layer,
deferred: HashMap::new(),
enabled: true,
}
}
pub fn set_lazy_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn compile_deferred_function(
&mut self,
dylib: &mut JITDylib,
func_name: &str,
) -> Result<usize, String> {
if let Some((dylib_name, module)) = self.deferred.remove(func_name) {
let mut func_module = Module::new(&format!("{}_compiled", func_name));
self.next_layer.add(dylib, func_module)?;
self.next_layer.emit()?;
if let Some(sym) = self.next_layer.find_symbol(func_name, false) {
return Ok(sym.address);
}
}
Err(format!("deferred function '{}' not found", func_name))
}
}
impl JITLayer for LazyCompileLayer {
fn add(&mut self, dylib: &mut JITDylib, module: Module) -> Result<(), String> {
if !self.enabled || !dylib.allow_lazy_compilation {
return self.next_layer.add(dylib, module);
}
for func_ref in &module.functions {
let func_name = func_ref.borrow().name.clone();
self.deferred
.insert(func_name.clone(), (dylib.name.clone(), module.clone()));
}
for func_ref in &module.functions {
let func_name = func_ref.borrow().name.clone();
let stub_addr = self.mem_manager_allocate_stub();
dylib.define_symbol(&func_name, stub_addr, JITSymbolFlags::exported_function());
}
Ok(())
}
fn emit(&mut self) -> Result<(), String> {
Ok(())
}
fn find_symbol(&self, name: &str, exported_only: bool) -> Option<JITSymbol> {
self.next_layer.find_symbol(name, exported_only)
}
fn layer_name(&self) -> &'static str {
"LazyCompileLayer"
}
}
impl LazyCompileLayer {
fn mem_manager_allocate_stub(&self) -> usize {
0x1000 }
}
pub struct ORCJITSession {
bottom_layer: Option<Box<dyn JITLayer>>,
dylibs: HashMap<String, JITDylib>,
symbol_resolver: Box<dyn Fn(&str) -> Option<JITSymbol> + Send + Sync>,
is_finalized: bool,
errors: Vec<String>,
}
impl ORCJITSession {
pub fn new() -> Self {
let mem_manager = Arc::new(Mutex::new(JITMemoryManager::new()));
let linking_layer = ObjectLinkingLayer::new();
Self {
bottom_layer: Some(Box::new(linking_layer)),
dylibs: HashMap::new(),
symbol_resolver: Box::new(|_name| None),
is_finalized: false,
errors: Vec::new(),
}
}
pub fn create_dylib(&mut self, name: &str) -> &mut JITDylib {
self.dylibs
.entry(name.to_string())
.or_insert_with(|| JITDylib::new(name));
self.dylibs.get_mut(name).unwrap()
}
pub fn add_module(&mut self, dylib_name: &str, module: Module) -> Result<(), String> {
if self.is_finalized {
return Err("session already finalized".into());
}
let dylib = self
.dylibs
.get_mut(dylib_name)
.ok_or_else(|| format!("dylib '{}' not found", dylib_name))?;
if let Some(ref mut layer) = self.bottom_layer {
layer.add(dylib, module)
} else {
Err("no bottom layer configured".into())
}
}
pub fn lookup(&self, name: &str) -> Option<JITSymbol> {
if let Some(ref layer) = self.bottom_layer {
if let Some(sym) = layer.find_symbol(name, false) {
return Some(sym);
}
}
for dylib in self.dylibs.values() {
if let Some(sym) = dylib.lookup(name) {
return Some(sym.clone());
}
}
(self.symbol_resolver)(name)
}
pub fn lookup_function<F>(&self, name: &str) -> Option<F> {
let sym = self.lookup(name)?;
if !sym.flags.is_callable {
return None;
}
unsafe { Some(std::mem::transmute_copy(&sym.address)) }
}
pub fn set_symbol_resolver(
&mut self,
resolver: Box<dyn Fn(&str) -> Option<JITSymbol> + Send + Sync>,
) {
self.symbol_resolver = resolver;
}
pub fn finalize(&mut self) -> Result<(), String> {
if self.is_finalized {
return Ok(());
}
if let Some(ref mut layer) = self.bottom_layer {
layer.emit()?;
}
self.is_finalized = true;
Ok(())
}
pub fn dylib_count(&self) -> usize {
self.dylibs.len()
}
pub fn errors(&self) -> &[String] {
&self.errors
}
pub fn clear_errors(&mut self) {
self.errors.clear();
}
}
#[derive(Debug)]
pub struct JITMemoryManager {
allocations: Vec<MemoryAllocation>,
total_allocated: usize,
}
#[derive(Debug, Clone)]
struct MemoryAllocation {
address: usize,
size: usize,
is_code: bool,
}
impl JITMemoryManager {
pub fn new() -> Self {
Self {
allocations: Vec::new(),
total_allocated: 0,
}
}
pub fn allocate(
&mut self,
size: usize,
executable: bool,
writable: bool,
) -> Result<usize, String> {
let aligned_size = (size + 4095) & !4095;
let addr = self.raw_allocate(aligned_size)?;
self.allocations.push(MemoryAllocation {
address: addr,
size: aligned_size,
is_code: executable,
});
self.total_allocated += aligned_size;
Ok(addr)
}
pub fn make_executable(&mut self, addr: usize, size: usize) -> Result<(), String> {
Ok(())
}
pub fn deallocate_all(&mut self) {
for alloc in &self.allocations {
}
self.allocations.clear();
self.total_allocated = 0;
}
fn raw_allocate(&self, size: usize) -> Result<usize, String> {
Ok(0x7f00_0000_0000 + self.total_allocated)
}
pub fn total_allocated(&self) -> usize {
self.total_allocated
}
}
pub struct ORCJITBuilder {
target_triple: String,
opt_level: u8,
lazy_compilation: bool,
concurrent_compilation: bool,
resolvers: Vec<Box<dyn Fn(&str) -> Option<JITSymbol> + Send + Sync>>,
register_eh_frames: bool,
enable_debug_support: bool,
}
impl ORCJITBuilder {
pub fn new() -> Self {
Self {
target_triple: "x86_64-unknown-linux-gnu".to_string(),
opt_level: 2,
lazy_compilation: true,
concurrent_compilation: false,
resolvers: Vec::new(),
register_eh_frames: true,
enable_debug_support: false,
}
}
pub fn target_triple(mut self, triple: &str) -> Self {
self.target_triple = triple.to_string();
self
}
pub fn opt_level(mut self, level: u8) -> Self {
self.opt_level = level;
self
}
pub fn lazy_compilation(mut self, enabled: bool) -> Self {
self.lazy_compilation = enabled;
self
}
pub fn concurrent_compilation(mut self, enabled: bool) -> Self {
self.concurrent_compilation = enabled;
self
}
pub fn add_symbol_resolver(
mut self,
resolver: Box<dyn Fn(&str) -> Option<JITSymbol> + Send + Sync>,
) -> Self {
self.resolvers.push(resolver);
self
}
pub fn register_eh_frames(mut self, enabled: bool) -> Self {
self.register_eh_frames = enabled;
self
}
pub fn enable_debug_support(mut self, enabled: bool) -> Self {
self.enable_debug_support = enabled;
self
}
pub fn build(self) -> Result<ORCJITSession, String> {
let mut session = ORCJITSession::new();
let resolvers = self.resolvers;
session.set_symbol_resolver(Box::new(move |name: &str| {
for resolver in &resolvers {
if let Some(sym) = resolver(name) {
return Some(sym);
}
}
None
}));
Ok(session)
}
}
impl Default for ORCJITBuilder {
fn default() -> Self {
Self::new()
}
}
pub type JITCompileCallback = Box<dyn Fn(&str) -> Result<usize, String> + Send + Sync>;
pub struct CompileCallbackManager {
callbacks: HashMap<String, JITCompileCallback>,
callback_count: u32,
}
impl CompileCallbackManager {
pub fn new() -> Self {
Self {
callbacks: HashMap::new(),
callback_count: 0,
}
}
pub fn register_callback(&mut self, func_name: &str, callback: JITCompileCallback) -> u32 {
let id = self.callback_count;
self.callback_count += 1;
self.callbacks.insert(func_name.to_string(), callback);
id
}
pub fn get_callback(&self, func_name: &str) -> Option<&JITCompileCallback> {
self.callbacks.get(func_name)
}
pub fn invoke_callback(&self, func_name: &str) -> Result<usize, String> {
if let Some(cb) = self.callbacks.get(func_name) {
cb(func_name)
} else {
Err(format!("no callback for '{}'", func_name))
}
}
}
#[derive(Debug)]
pub struct ResourceTracker {
tracked_addresses: Vec<usize>,
tracked_sizes: Vec<usize>,
tracked_symbols: Vec<String>,
}
impl ResourceTracker {
pub fn new() -> Self {
Self {
tracked_addresses: Vec::new(),
tracked_sizes: Vec::new(),
tracked_symbols: Vec::new(),
}
}
pub fn track_memory(&mut self, addr: usize, size: usize) {
self.tracked_addresses.push(addr);
self.tracked_sizes.push(size);
}
pub fn track_symbol(&mut self, name: &str) {
self.tracked_symbols.push(name.to_string());
}
pub fn release_all(&mut self, mem_manager: &mut JITMemoryManager) {
mem_manager.deallocate_all();
self.tracked_addresses.clear();
self.tracked_sizes.clear();
self.tracked_symbols.clear();
}
}
pub struct MaterializationUnit {
pub module_name: String,
pub symbols: Vec<String>,
pub compiled: bool,
pub linked: bool,
pub compile_layer: Option<Box<dyn JITLayer>>,
}
impl MaterializationUnit {
pub fn new(module_name: &str, symbols: Vec<String>) -> Self {
MaterializationUnit {
module_name: module_name.to_string(),
symbols,
compiled: false,
linked: false,
compile_layer: None,
}
}
pub fn set_compile_layer(&mut self, layer: Box<dyn JITLayer>) {
self.compile_layer = Some(layer);
}
pub fn provides_symbol(&self, name: &str) -> bool {
self.symbols.contains(&name.to_string())
}
pub fn compile(&mut self) -> Result<(), String> {
if self.compiled {
return Ok(());
}
self.compiled = true;
Ok(())
}
pub fn link(&mut self) -> Result<(), String> {
if !self.compiled {
return Err("Cannot link uncompiled materialization unit".to_string());
}
self.linked = true;
Ok(())
}
}
pub struct ExecutionSession {
pub dylibs: Vec<JITDylib>,
pub symbol_resolver: Option<SymbolResolver>,
pending_units: Vec<MaterializationUnit>,
dispatch_queue: Vec<String>,
finalized: bool,
}
pub struct SymbolResolver {
pub symbols: std::collections::HashMap<String, u64>,
}
impl SymbolResolver {
pub fn new() -> Self {
SymbolResolver {
symbols: std::collections::HashMap::new(),
}
}
pub fn register(&mut self, name: &str, addr: u64) {
self.symbols.insert(name.to_string(), addr);
}
pub fn lookup(&self, name: &str) -> Option<u64> {
self.symbols.get(name).copied()
}
}
impl ExecutionSession {
pub fn new() -> Self {
ExecutionSession {
dylibs: Vec::new(),
symbol_resolver: None,
pending_units: Vec::new(),
dispatch_queue: Vec::new(),
finalized: false,
}
}
pub fn add_materialization_unit(&mut self, unit: MaterializationUnit) {
self.pending_units.push(unit);
}
pub fn dispatch_materialization(&mut self, symbol: &str) -> Result<(), String> {
self.dispatch_queue.push(symbol.to_string());
for unit in &mut self.pending_units {
if unit.provides_symbol(symbol) && !unit.compiled {
unit.compile()?;
unit.link()?;
return Ok(());
}
}
Err(format!(
"No materialization unit provides symbol '{}'",
symbol
))
}
pub fn lookup_symbol(&self, name: &str) -> Option<u64> {
if let Some(ref resolver) = self.symbol_resolver {
if let Some(addr) = resolver.lookup(name) {
return Some(addr);
}
}
for dylib in &self.dylibs {
if let Some(addr) = dylib.lookup(name) {
return Some(addr.address as u64);
}
}
None
}
pub fn finalize(&mut self) {
self.finalized = true;
}
pub fn is_finalized(&self) -> bool {
self.finalized
}
pub fn pending_count(&self) -> usize {
self.pending_units.len()
}
}
pub struct ThreadSafeModule {
pub module: llvm_native_core::module::Module,
pub thread_safe: bool,
}
impl ThreadSafeModule {
pub fn new(module: llvm_native_core::module::Module) -> Self {
ThreadSafeModule {
module,
thread_safe: true,
}
}
pub fn clone_module(&self) -> llvm_native_core::module::Module {
self.module.clone()
}
}
pub struct IRCompileLayer {
pub target_triple: String,
pub opt_level: String,
pub debug_info: bool,
}
impl IRCompileLayer {
pub fn new(target_triple: &str) -> Self {
IRCompileLayer {
target_triple: target_triple.to_string(),
opt_level: "O2".to_string(),
debug_info: false,
}
}
pub fn compile(&self, module: &llvm_native_core::module::Module) -> Result<Vec<u8>, String> {
if module.functions.is_empty() {
return Err("Cannot compile empty module".to_string());
}
Ok(vec![0x90, 0xC3]) }
}
pub struct CompileOnDemandLayer {
pub base_layer: Box<IRCompileLayer>,
pending_stubs: Vec<LazyStub>,
pub enabled: bool,
}
struct LazyStub {
function_name: String,
stub_addr: u64,
module: llvm_native_core::module::Module,
}
impl CompileOnDemandLayer {
pub fn new(target_triple: &str) -> Self {
CompileOnDemandLayer {
base_layer: Box::new(IRCompileLayer::new(target_triple)),
pending_stubs: Vec::new(),
enabled: true,
}
}
pub fn create_stub(
&mut self,
_name: &str,
_module: &llvm_native_core::module::Module,
) -> Result<u64, String> {
if !self.enabled {
return Err("Compile-on-demand is disabled".to_string());
}
let stub_addr = 0x10000; Ok(stub_addr)
}
pub fn compile_pending(&mut self) -> Result<(), String> {
for stub in &self.pending_stubs {
let _ = self.base_layer.compile(&stub.module)?;
}
self.pending_stubs.clear();
Ok(())
}
}
pub struct IndirectStubsManager {
pub stub_count: usize,
initialized: bool,
}
impl IndirectStubsManager {
pub fn new() -> Self {
IndirectStubsManager {
stub_count: 0,
initialized: false,
}
}
pub fn create_stub(&mut self) -> usize {
let idx = self.stub_count;
self.stub_count += 1;
idx
}
pub fn update_stub(&mut self, _index: usize, _target_addr: u64) {
}
pub fn initialize(&mut self) {
self.initialized = true;
}
}
pub struct TrampolinePool {
pub slots: usize,
pub trampoline_size: usize,
}
impl TrampolinePool {
pub fn new(num_slots: usize) -> Self {
TrampolinePool {
slots: num_slots,
trampoline_size: 32, }
}
pub fn total_size(&self) -> usize {
self.slots * self.trampoline_size
}
pub fn allocate(&mut self) -> Option<usize> {
if self.slots == 0 {
return None;
}
self.slots -= 1;
Some(self.slots)
}
pub fn release(&mut self) {
self.slots += 1;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_jit_symbol_flags_default() {
let flags = JITSymbolFlags::default();
assert!(!flags.is_callable);
assert!(flags.is_exported);
assert!(!flags.is_weak);
}
#[test]
fn test_jit_symbol_flags_exported_function() {
let flags = JITSymbolFlags::exported_function();
assert!(flags.is_callable);
assert!(flags.is_exported);
}
#[test]
fn test_jit_dylib_create() {
let dylib = JITDylib::new("test_dylib");
assert_eq!(dylib.name, "test_dylib");
assert!(dylib.lookup("nonexistent").is_none());
}
#[test]
fn test_jit_dylib_define_and_lookup() {
let mut dylib = JITDylib::new("test");
dylib.define_symbol("foo", 0x1000, JITSymbolFlags::exported_function());
let sym = dylib.lookup("foo").unwrap();
assert_eq!(sym.address, 0x1000);
assert!(sym.flags.is_callable);
}
#[test]
fn test_orc_session_create() {
let session = ORCJITSession::new();
assert!(!session.is_finalized);
assert_eq!(session.dylib_count(), 0);
}
#[test]
fn test_orc_session_create_dylib() {
let mut session = ORCJITSession::new();
session.create_dylib("main");
assert_eq!(session.dylib_count(), 1);
}
#[test]
fn test_orc_session_lookup_nonexistent() {
let session = ORCJITSession::new();
assert!(session.lookup("nonexistent").is_none());
}
#[test]
fn test_orc_builder_default() {
let builder = ORCJITBuilder::new();
let result = builder.build();
assert!(result.is_ok());
}
#[test]
fn test_orc_builder_custom() {
let builder = ORCJITBuilder::new()
.target_triple("aarch64-linux-gnu")
.opt_level(3)
.lazy_compilation(false);
let result = builder.build();
assert!(result.is_ok());
}
#[test]
fn test_memory_manager_allocate() {
let mut mm = JITMemoryManager::new();
let addr = mm.allocate(4096, true, true).unwrap();
assert!(addr > 0);
assert_eq!(mm.total_allocated(), 4096);
}
#[test]
fn test_memory_manager_deallocate() {
let mut mm = JITMemoryManager::new();
mm.allocate(8192, true, true).unwrap();
assert_eq!(mm.total_allocated(), 8192);
mm.deallocate_all();
assert_eq!(mm.total_allocated(), 0);
}
#[test]
fn test_compile_callback_manager() {
let mut ccm = CompileCallbackManager::new();
let id = ccm.register_callback(
"foo",
Box::new(|name| {
assert_eq!(name, "foo");
Ok(0x2000)
}),
);
assert_eq!(id, 0);
let result = ccm.invoke_callback("foo");
assert!(result.is_ok());
assert_eq!(result.unwrap(), 0x2000);
}
#[test]
fn test_resource_tracker() {
let mut tracker = ResourceTracker::new();
tracker.track_memory(0x1000, 4096);
tracker.track_symbol("test_sym");
assert_eq!(tracker.tracked_addresses.len(), 1);
assert_eq!(tracker.tracked_symbols.len(), 1);
let mut mm = JITMemoryManager::new();
tracker.release_all(&mut mm);
assert!(tracker.tracked_addresses.is_empty());
}
#[test]
fn test_jit_layer_names() {
let linking = ObjectLinkingLayer::new();
assert_eq!(linking.layer_name(), "ObjectLinkingLayer");
}
#[test]
fn test_orc_session_finalize() {
let mut session = ORCJITSession::new();
assert!(!session.is_finalized);
session.finalize().unwrap();
assert!(session.is_finalized);
session.finalize().unwrap();
}
#[test]
fn test_orc_session_errors() {
let mut session = ORCJITSession::new();
assert!(session.errors().is_empty());
session.clear_errors();
}
}