From 03c0c6b1842afc438a9ec299efc5386bf52e92e1 Mon Sep 17 00:00:00 2001 From: Qwox <103262539+Qwox0@users.noreply.github.com> Date: Sat, 21 Dec 2024 07:06:10 +0100 Subject: [PATCH 01/26] fix: reset `positioned` in `Builder::clear_insertion_position` (#561) --- src/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builder.rs b/src/builder.rs index ccdb811428d..8fa596a074c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -3247,6 +3247,7 @@ impl<'ctx> Builder<'ctx> { } pub fn clear_insertion_position(&self) { + self.positioned.set(PositionState::NotSet); unsafe { LLVMClearInsertionPosition(self.builder) } } From 97128a9036c24448a5bd2904238e0df064c6ea9d Mon Sep 17 00:00:00 2001 From: Kentaro Tanaka Date: Sun, 2 Feb 2025 13:55:59 +0900 Subject: [PATCH 02/26] Add create_mcjit_execution_engine_with_memory_manager for custom MCJIT memory management (#566) * Add a function to the Module that creates an MCJIT capable of using a custom MemoryManager * Fix test failures caused by differing allocate_data_section call counts across LLVM versions * refactor: Use explicit bool to i32 cast in MCJIT options * refactor: Use MaybeUninit::zeroed() for MCJIT options initialization * refactor: Mark c_str_to_str as unsafe due to arbitrary lifetime risk * fix: Prevent UB by reordering Box creation in memory manager destruction --- src/lib.rs | 1 + src/memory_manager.rs | 180 +++++++++++++++++++ src/module.rs | 145 +++++++++++++++- tests/all/test_execution_engine.rs | 270 ++++++++++++++++++++++++++++- 4 files changed, 589 insertions(+), 7 deletions(-) create mode 100644 src/memory_manager.rs diff --git a/src/lib.rs b/src/lib.rs index 9917f35920e..cf1691708be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ pub mod debug_info; pub mod execution_engine; pub mod intrinsics; pub mod memory_buffer; +pub mod memory_manager; #[deny(missing_docs)] pub mod module; pub mod object_file; diff --git a/src/memory_manager.rs b/src/memory_manager.rs new file mode 100644 index 00000000000..96af0bbd625 --- /dev/null +++ b/src/memory_manager.rs @@ -0,0 +1,180 @@ +use llvm_sys::prelude::LLVMBool; + +/// A trait for user-defined memory management in MCJIT. +/// +/// Implementors can override how LLVM's MCJIT engine allocates memory for code +/// and data sections. This is sometimes needed for: +/// - custom allocators, +/// - sandboxed or restricted environments, +/// - capturing stack map sections (e.g., for garbage collection), +/// - or other specialized JIT memory management requirements. +/// +/// # StackMap and GC Integration +/// +/// By examining the `section_name` argument in [`allocate_data_section`], you +/// can detect sections such as `.llvm_stackmaps` (on ELF) or `__llvm_stackmaps` +/// (on Mach-O). Recording the location of these sections may be useful for +/// custom garbage collectors. For more information, refer to the [LLVM +/// StackMaps documentation](https://llvm.org/docs/StackMaps.html#stack-map-section). +/// +/// Typically, on Darwin (Mach-O), the stack map section name is `__llvm_stackmaps`, +/// and on Linux (ELF), it is `.llvm_stackmaps`. +pub trait McjitMemoryManager: std::fmt::Debug { + /// Allocates a block of memory for a code section. + /// + /// # Parameters + /// + /// * `size` - The size in bytes for the code section. + /// * `alignment` - The required alignment in bytes. + /// * `section_id` - A numeric ID that LLVM uses to identify this section. + /// * `section_name` - A name for this section, if provided by LLVM. + /// + /// # Returns + /// + /// Returns a pointer to the allocated memory. Implementors must ensure it is + /// at least `size` bytes long and meets `alignment` requirements. + fn allocate_code_section( + &mut self, + size: libc::uintptr_t, + alignment: libc::c_uint, + section_id: libc::c_uint, + section_name: &str, + ) -> *mut u8; + + /// Allocates a block of memory for a data section. + /// + /// # Parameters + /// + /// * `size` - The size in bytes for the data section. + /// * `alignment` - The required alignment in bytes. + /// * `section_id` - A numeric ID that LLVM uses to identify this section. + /// * `section_name` - A name for this section, if provided by LLVM. + /// * `is_read_only` - Whether this data section should be read-only. + /// + /// # Returns + /// + /// Returns a pointer to the allocated memory. Implementors must ensure it is + /// at least `size` bytes long and meets `alignment` requirements. + fn allocate_data_section( + &mut self, + size: libc::uintptr_t, + alignment: libc::c_uint, + section_id: libc::c_uint, + section_name: &str, + is_read_only: bool, + ) -> *mut u8; + + /// Finalizes memory permissions for all allocated sections. + /// + /// This is called once all sections have been allocated. Implementors can set + /// permissions such as making code sections executable or data sections + /// read-only. + /// + /// # Errors + /// + /// If any error occurs (for example, failing to set page permissions), + /// return an `Err(String)`. This error is reported back to LLVM as a C string. + fn finalize_memory(&mut self) -> Result<(), String>; + + /// Cleans up or deallocates resources before the memory manager is destroyed. + /// + /// This is called when LLVM has finished using the memory manager. Any + /// additional allocations or references should be released here if needed. + fn destroy(&mut self); +} + +/// Holds a boxed `McjitMemoryManager` and passes it to LLVM as an opaque pointer. +/// +/// LLVM calls into the adapter using the extern "C" function pointers defined below. +#[derive(Debug)] +pub struct MemoryManagerAdapter { + pub memory_manager: Box, +} + +// ------ Extern "C" Adapters ------ + +/// Adapter for `allocate_code_section`. +/// +/// Called by LLVM with a raw pointer (`opaque`). Casts back to `MemoryManagerAdapter` +/// and delegates to `allocate_code_section`. +pub(crate) extern "C" fn allocate_code_section_adapter( + opaque: *mut libc::c_void, + size: libc::uintptr_t, + alignment: libc::c_uint, + section_id: libc::c_uint, + section_name: *const libc::c_char, +) -> *mut u8 { + let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) }; + let sname = unsafe { c_str_to_str(section_name) }; + adapter + .memory_manager + .allocate_code_section(size, alignment, section_id, sname) +} + +/// Adapter for `allocate_data_section`. +/// +/// Note that `LLVMBool` is `0` for false, and `1` for true. We check `!= 0` to +/// interpret it as a bool. +pub(crate) extern "C" fn allocate_data_section_adapter( + opaque: *mut libc::c_void, + size: libc::uintptr_t, + alignment: libc::c_uint, + section_id: libc::c_uint, + section_name: *const libc::c_char, + is_read_only: LLVMBool, +) -> *mut u8 { + let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) }; + let sname = unsafe { c_str_to_str(section_name) }; + adapter + .memory_manager + .allocate_data_section(size, alignment, section_id, sname, is_read_only != 0) +} + +/// Adapter for `finalize_memory`. +/// +/// If an error is returned, the message is converted into a C string and set in `err_msg_out`. +pub(crate) extern "C" fn finalize_memory_adapter( + opaque: *mut libc::c_void, + err_msg_out: *mut *mut libc::c_char, +) -> libc::c_int { + let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) }; + match adapter.memory_manager.finalize_memory() { + Ok(()) => 0, + Err(e) => { + let cstring = std::ffi::CString::new(e).unwrap_or_default(); + unsafe { + *err_msg_out = cstring.into_raw(); + } + 1 + }, + } +} + +/// Adapter for `destroy`. +/// +/// Called when LLVM is done with the memory manager. Calls `destroy` and drops +/// the adapter to free resources. +pub(crate) extern "C" fn destroy_adapter(opaque: *mut libc::c_void) { + // Re-box to drop the adapter and its contents. + // SAFETY: `opaque` must have been allocated by Box. + let mut adapter = unsafe { Box::from_raw(opaque as *mut MemoryManagerAdapter) }; + + // Clean up user-defined resources + adapter.memory_manager.destroy(); + + // Dropping `adapter` automatically frees the memory +} + +/// Converts a raw C string pointer to a Rust `&str`. +/// +/// # Safety +/// +/// The caller must ensure `ptr` points to a valid, null-terminated UTF-8 string. +/// If the string is invalid UTF-8 or `ptr` is null, an empty string is returned. +unsafe fn c_str_to_str<'a>(ptr: *const libc::c_char) -> &'a str { + if ptr.is_null() { + "" + } else { + unsafe { std::ffi::CStr::from_ptr(ptr) }.to_str().unwrap_or("") + } +} diff --git a/src/module.rs b/src/module.rs index 14c79a5cffe..821192d7631 100644 --- a/src/module.rs +++ b/src/module.rs @@ -9,10 +9,10 @@ use llvm_sys::core::LLVMGetTypeByName; use llvm_sys::core::{ LLVMAddFunction, LLVMAddGlobal, LLVMAddGlobalInAddressSpace, LLVMAddNamedMetadataOperand, LLVMCloneModule, - LLVMDisposeModule, LLVMDumpModule, LLVMGetFirstFunction, LLVMGetFirstGlobal, LLVMGetLastFunction, - LLVMGetLastGlobal, LLVMGetModuleContext, LLVMGetModuleIdentifier, LLVMGetNamedFunction, LLVMGetNamedGlobal, - LLVMGetNamedMetadataNumOperands, LLVMGetNamedMetadataOperands, LLVMGetTarget, LLVMPrintModuleToFile, - LLVMPrintModuleToString, LLVMSetDataLayout, LLVMSetModuleIdentifier, LLVMSetTarget, LLVMDisposeMessage + LLVMDisposeMessage, LLVMDisposeModule, LLVMDumpModule, LLVMGetFirstFunction, LLVMGetFirstGlobal, + LLVMGetLastFunction, LLVMGetLastGlobal, LLVMGetModuleContext, LLVMGetModuleIdentifier, LLVMGetNamedFunction, + LLVMGetNamedGlobal, LLVMGetNamedMetadataNumOperands, LLVMGetNamedMetadataOperands, LLVMGetTarget, + LLVMPrintModuleToFile, LLVMPrintModuleToString, LLVMSetDataLayout, LLVMSetModuleIdentifier, LLVMSetTarget, }; #[llvm_versions(7..)] use llvm_sys::core::{LLVMAddModuleFlag, LLVMGetModuleFlag}; @@ -20,6 +20,7 @@ use llvm_sys::core::{LLVMAddModuleFlag, LLVMGetModuleFlag}; use llvm_sys::error::LLVMGetErrorMessage; use llvm_sys::execution_engine::{ LLVMCreateExecutionEngineForModule, LLVMCreateInterpreterForModule, LLVMCreateJITCompilerForModule, + LLVMCreateSimpleMCJITMemoryManager, }; use llvm_sys::prelude::{LLVMModuleRef, LLVMValueRef}; #[llvm_versions(13..)] @@ -29,7 +30,7 @@ use llvm_sys::LLVMLinkage; use llvm_sys::LLVMModuleFlagBehavior; use std::cell::{Cell, Ref, RefCell}; -use std::ffi::CStr; +use std::ffi::{c_void, CStr}; use std::fs::File; use std::marker::PhantomData; use std::mem::{forget, MaybeUninit}; @@ -45,12 +46,16 @@ use crate::data_layout::DataLayout; use crate::debug_info::{DICompileUnit, DWARFEmissionKind, DWARFSourceLanguage, DebugInfoBuilder}; use crate::execution_engine::ExecutionEngine; use crate::memory_buffer::MemoryBuffer; +use crate::memory_manager::{ + allocate_code_section_adapter, allocate_data_section_adapter, destroy_adapter, finalize_memory_adapter, + McjitMemoryManager, MemoryManagerAdapter, +}; #[llvm_versions(13..)] use crate::passes::PassBuilderOptions; use crate::support::{to_c_str, LLVMString}; #[llvm_versions(13..)] use crate::targets::TargetMachine; -use crate::targets::{InitializationConfig, Target, TargetTriple}; +use crate::targets::{CodeModel, InitializationConfig, Target, TargetTriple}; use crate::types::{AsTypeRef, BasicType, FunctionType, StructType}; #[llvm_versions(7..)] use crate::values::BasicValue; @@ -609,6 +614,134 @@ impl<'ctx> Module<'ctx> { Ok(execution_engine) } + /// Creates an MCJIT `ExecutionEngine` for this `Module` using a custom memory manager. + /// + /// # Parameters + /// + /// * `memory_manager` - Specifies how LLVM allocates and finalizes code and data sections. + /// Implement the [`McjitMemoryManager`] trait to customize these operations. + /// * `opt_level` - Sets the desired optimization level (e.g. `None`, `Less`, `Default`, `Aggressive`). + /// Higher levels generally produce faster code at the expense of longer compilation times. + /// * `code_model` - Determines how code addresses are represented. Common values include + /// `CodeModel::Default` or `CodeModel::JITDefault`. This impacts the generated machine code layout. + /// * `no_frame_pointer_elim` - If true, frame pointer elimination is disabled. This may assist + /// with certain debugging or profiling tasks but can incur a performance cost. + /// * `enable_fast_isel` - If true, uses a faster instruction selector where possible. This can + /// improve compilation speed, though it may produce less optimized code in some cases. + /// + /// # Returns + /// + /// Returns a newly created [`ExecutionEngine`] for MCJIT on success. Returns an error if: + /// - The native target fails to initialize, + /// - The `Module` is already owned by another `ExecutionEngine`, + /// - Or MCJIT fails to create the engine (in which case an error string is returned from LLVM). + /// + /// # Notes + /// + /// Using a custom memory manager can help intercept or manage allocations for specific + /// sections (for example, capturing `.llvm_stackmaps` or applying custom permissions). + /// For details, refer to the [`McjitMemoryManager`] documentation. + /// + /// # Safety + /// + /// The returned [`ExecutionEngine`] takes ownership of the memory manager. Do not move + /// or free the `memory_manager` after calling this method. When the `ExecutionEngine` + /// is dropped, LLVM will destroy the memory manager by calling + /// [`McjitMemoryManager::destroy()`] and freeing its adapter. + pub fn create_mcjit_execution_engine_with_memory_manager( + &self, + memory_manager: impl McjitMemoryManager + 'static, + opt_level: OptimizationLevel, + code_model: CodeModel, + no_frame_pointer_elim: bool, + enable_fast_isel: bool, + ) -> Result, LLVMString> { + use std::mem::MaybeUninit; + // ... + + // 1) Initialize the native target + Target::initialize_native(&InitializationConfig::default()).map_err(|mut err_string| { + err_string.push('\0'); + LLVMString::create_from_str(&err_string) + })?; + + // Check if the module is already owned by an ExecutionEngine + if self.owned_by_ee.borrow().is_some() { + let string = "This module is already owned by an ExecutionEngine.\0"; + return Err(LLVMString::create_from_str(string)); + } + + // 2) Box the memory_manager into a MemoryManagerAdapter + let adapter = MemoryManagerAdapter { + memory_manager: Box::new(memory_manager), + }; + let adapter_box = Box::new(adapter); + // Convert the Box into a raw pointer for LLVM. + // In `destroy_adapter`, we use `Box::from_raw` to safely reclaim ownership. + let opaque = Box::into_raw(adapter_box) as *mut c_void; + + // 3) Create the LLVMMCJITMemoryManager using the custom callbacks + let mmgr = unsafe { + LLVMCreateSimpleMCJITMemoryManager( + opaque, + allocate_code_section_adapter, + allocate_data_section_adapter, + finalize_memory_adapter, + Some(destroy_adapter), + ) + }; + if mmgr.is_null() { + let msg = "Failed to create SimpleMCJITMemoryManager.\0"; + return Err(LLVMString::create_from_str(msg)); + } + + // 4) Build LLVMMCJITCompilerOptions + let mut options_uninit = MaybeUninit::::zeroed(); + unsafe { + // Ensure defaults are initialized + llvm_sys::execution_engine::LLVMInitializeMCJITCompilerOptions( + options_uninit.as_mut_ptr(), + std::mem::size_of::(), + ); + } + let mut options = unsafe { options_uninit.assume_init() }; + + // Override fields + options.OptLevel = opt_level as u32; + options.CodeModel = code_model.into(); + options.NoFramePointerElim = no_frame_pointer_elim as i32; + options.EnableFastISel = enable_fast_isel as i32; + options.MCJMM = mmgr; + + // 5) Create MCJIT + let mut execution_engine = MaybeUninit::uninit(); + let mut err_string = MaybeUninit::uninit(); + let code = unsafe { + llvm_sys::execution_engine::LLVMCreateMCJITCompilerForModule( + execution_engine.as_mut_ptr(), + self.module.get(), + &mut options, + std::mem::size_of::(), + err_string.as_mut_ptr(), + ) + }; + + // If creation fails, extract the error string + if code == 1 { + unsafe { + return Err(LLVMString::new(err_string.assume_init())); + } + } + + // Otherwise, it succeeded, so wrap the raw pointer + let execution_engine = unsafe { execution_engine.assume_init() }; + let execution_engine = unsafe { ExecutionEngine::new(Rc::new(execution_engine), true) }; + + *self.owned_by_ee.borrow_mut() = Some(execution_engine.clone()); + + Ok(execution_engine) + } + /// Creates a `GlobalValue` based on a type in an address space. /// /// # Example diff --git a/tests/all/test_execution_engine.rs b/tests/all/test_execution_engine.rs index bd056f00003..d19077afa29 100644 --- a/tests/all/test_execution_engine.rs +++ b/tests/all/test_execution_engine.rs @@ -1,6 +1,11 @@ +use std::cell::RefCell; +use std::rc::Rc; + use inkwell::context::Context; use inkwell::execution_engine::FunctionLookupError; -use inkwell::targets::{InitializationConfig, Target}; +use inkwell::memory_manager::McjitMemoryManager; +use inkwell::module::Linkage; +use inkwell::targets::{CodeModel, InitializationConfig, Target}; use inkwell::{AddressSpace, IntPredicate, OptimizationLevel}; type Thunk = unsafe extern "C" fn(); @@ -150,6 +155,122 @@ fn test_interpreter_execution_engine() { assert!(module.create_interpreter_execution_engine().is_ok()); } +#[test] + +fn test_mcjit_execution_engine_with_memory_manager() { + let mmgr = MockMemoryManager::new(); + let mmgr_for_test = mmgr.clone(); + + { + let context = Context::create(); + let module = context.create_module("main_module"); + let builder = context.create_builder(); + + // Define @llvm.experimental.stackmap + let fn_type = context + .void_type() + .fn_type(&[context.i64_type().into(), context.i32_type().into()], true); + let stackmap_func = module.add_function("llvm.experimental.stackmap", fn_type, Some(Linkage::External)); + + // Set up the function + // + // `@llvm.experimental.stackmap` a call is present, LLVM will emit a separate stackmap section, + // causing the `allocate_data_section` callback to be invoked an additional + // time to handle the stackmap data. Specifically: + // ``` + // f64 test_fn() { + // entry: + // call void @llvm.experimental.stackmap(i64 12345, i32 0) + // ret f64 64.0 + // } + // ``` + let double = context.f64_type(); + let sig = double.fn_type(&[], false); + let f = module.add_function("test_fn", sig, None); + let b = context.append_basic_block(f, "entry"); + builder.position_at_end(b); + + // Create a call to the stackmap intrinsic + // Stack maps are used by the garbage collector to find roots on the stack + // See: https://llvm.org/docs/StackMaps.html#intrinsics + builder + .build_call( + stackmap_func, + &[ + context.i64_type().const_int(12345, false).into(), + context.i32_type().const_int(0, false).into(), + ], + "call_stackmap", + ) + .unwrap(); + + // Insert a return statement + let ret = double.const_float(64.0); + builder.build_return(Some(&ret)).unwrap(); + + module.verify().unwrap(); + + let ee = module + .create_mcjit_execution_engine_with_memory_manager( + mmgr, + OptimizationLevel::None, + CodeModel::Default, + false, + false, + ) + .unwrap(); + + unsafe { + let test_fn = ee.get_function:: f64>("test_fn").unwrap(); + let return_value = test_fn.call(); + assert_eq!(return_value, 64.0); + } + } + // ee dropped here. Destroy should be called + + let data = mmgr_for_test.data.borrow(); + assert_eq!(1, data.code_alloc_calls); + assert!( + data.data_alloc_calls >= 2, + "Expected at least 2 calls to allocate_data_section, but got {}. \ + We've observed that LLVM 5 typically calls it 3 times, while LLVM 18 often calls it only 2.", + data.data_alloc_calls + ); + assert_eq!(1, data.finalize_calls); + assert_eq!(1, data.destroy_calls); +} + +#[test] +fn test_create_mcjit_engine_when_already_owned() { + let context = Context::create(); + let module = context.create_module("owned_module"); + + // First engine should succeed + let memory_manager = MockMemoryManager::new(); + let engine_result = module.create_mcjit_execution_engine_with_memory_manager( + memory_manager, + OptimizationLevel::None, + CodeModel::Default, + false, + false, + ); + assert!(engine_result.is_ok()); + + // Second engine should fail + let memory_manager2 = MockMemoryManager::new(); + let second_result = module.create_mcjit_execution_engine_with_memory_manager( + memory_manager2, + OptimizationLevel::None, + CodeModel::Default, + false, + false, + ); + assert!( + second_result.is_err(), + "Expected an error when creating a second ExecutionEngine on the same module" + ); +} + #[test] fn test_add_remove_module() { let context = Context::create(); @@ -235,3 +356,150 @@ fn test_add_remove_module() { // module.create_jit_execution_engine(OptimizationLevel::None).unwrap() // }; // } + +/// A mock memory manager that allocates memory in fixed-size pages for testing. +#[derive(Debug, Clone)] +struct MockMemoryManager { + data: Rc>, +} + +#[derive(Debug)] +struct MockMemoryManagerData { + fixed_capacity_bytes: usize, + fixed_page_size: usize, + + code_buff_ptr: std::ptr::NonNull, + code_offset: usize, + + data_buff_ptr: std::ptr::NonNull, + data_offset: usize, + + /// Count call to callbacks for testing + code_alloc_calls: usize, + data_alloc_calls: usize, + finalize_calls: usize, + destroy_calls: usize, +} + +impl MockMemoryManager { + pub fn new() -> Self { + let capacity_bytes = 128 * 1024; + let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }; + + let code_buff_ptr = unsafe { + std::ptr::NonNull::new_unchecked(libc::mmap( + std::ptr::null_mut(), + capacity_bytes, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ) as *mut u8) + }; + + let data_buff_ptr = unsafe { + std::ptr::NonNull::new_unchecked(libc::mmap( + std::ptr::null_mut(), + capacity_bytes, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ) as *mut u8) + }; + + Self { + data: Rc::new(RefCell::new(MockMemoryManagerData { + fixed_capacity_bytes: capacity_bytes, + fixed_page_size: page_size, + + code_buff_ptr, + code_offset: 0, + + data_buff_ptr, + data_offset: 0, + + code_alloc_calls: 0, + data_alloc_calls: 0, + finalize_calls: 0, + destroy_calls: 0, + })), + } + } +} + +impl McjitMemoryManager for MockMemoryManager { + fn allocate_code_section( + &mut self, + size: libc::size_t, + _alignment: libc::c_uint, + _section_id: libc::c_uint, + _section_name: &str, + ) -> *mut u8 { + let mut data = self.data.borrow_mut(); + data.code_alloc_calls += 1; + + let alloc_size = size.div_ceil(data.fixed_page_size) * data.fixed_page_size; + let ptr = unsafe { data.code_buff_ptr.as_ptr().add(data.code_offset) }; + data.code_offset += alloc_size; + + ptr + } + + fn allocate_data_section( + &mut self, + size: libc::size_t, + _alignment: libc::c_uint, + _section_id: libc::c_uint, + _section_name: &str, + _is_read_only: bool, + ) -> *mut u8 { + let mut data = self.data.borrow_mut(); + + data.data_alloc_calls += 1; + + let alloc_size = size.div_ceil(data.fixed_page_size) * data.fixed_page_size; + let ptr = unsafe { data.data_buff_ptr.as_ptr().add(data.data_offset) }; + data.data_offset += alloc_size; + + ptr + } + + fn finalize_memory(&mut self) -> Result<(), String> { + let mut data = self.data.borrow_mut(); + + data.finalize_calls += 1; + + unsafe { + libc::mprotect( + data.code_buff_ptr.as_ptr() as *mut libc::c_void, + data.fixed_capacity_bytes, + libc::PROT_READ | libc::PROT_EXEC, + ); + libc::mprotect( + data.data_buff_ptr.as_ptr() as *mut libc::c_void, + data.fixed_capacity_bytes, + libc::PROT_READ | libc::PROT_WRITE, + ); + } + + Ok(()) + } + + fn destroy(&mut self) { + let mut data = self.data.borrow_mut(); + + data.destroy_calls += 1; + + unsafe { + libc::munmap( + data.code_buff_ptr.as_ptr() as *mut libc::c_void, + data.fixed_capacity_bytes, + ); + libc::munmap( + data.data_buff_ptr.as_ptr() as *mut libc::c_void, + data.fixed_capacity_bytes, + ); + } + } +} From 16313d309144ab24a0d38d45f3eec998805f3afb Mon Sep 17 00:00:00 2001 From: Etienne Wodey <44871469+airwoodix@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:29:29 +0100 Subject: [PATCH 03/26] docs: fix warnings and typos (#574) * InstructionValue::get_instruction_with_name: remove superfluous return * docs: fix build warnings * Fix typos --- src/builder.rs | 13 +++++++------ src/debug_info.rs | 10 +++++++--- src/lib.rs | 11 ++++++----- src/memory_manager.rs | 4 ++-- src/module.rs | 17 +++++++++++------ src/passes.rs | 4 ++-- src/types/enums.rs | 4 ++-- src/values/instruction_value.rs | 6 +++--- tests/all/test_values.rs | 2 +- 9 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8fa596a074c..004ea5b9b1d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -806,7 +806,7 @@ impl<'ctx> Builder<'ctx> { } /// Landing pads are places where control flow jumps to if a [`Builder::build_invoke`] triggered an exception. - /// The landing pad will match the exception against its *clauses*. Depending on the clause + /// The landing pad will match the exception against its `clauses`. Depending on the clause /// that is matched, the exception can then be handled, or resumed after some optional cleanup, /// causing the exception to bubble up. /// @@ -848,7 +848,7 @@ impl<'ctx> Builder<'ctx> { /// ``` /// /// * **catch all**: An implementation of the C++ `catch(...)`, which catches all exceptions. - /// A catch clause with a NULL pointer value will match anything. + /// A catch clause with a NULL pointer value will match anything. /// /// ```no_run /// use inkwell::context::Context; @@ -920,7 +920,7 @@ impl<'ctx> Builder<'ctx> { /// ``` /// /// * **filter**: A filter clause encodes that only some types of exceptions are valid at this - /// point. A filter clause is made by constructing a clause from a constant array. + /// point. A filter clause is made by constructing a clause from a constant array. /// /// ```no_run /// use inkwell::context::Context; @@ -3455,12 +3455,14 @@ impl<'ctx> Builder<'ctx> { unsafe { Ok(IntValue::new(val)) } } - /// Builds a cmpxchg instruction. It allows you to atomically compare and replace memory. + /// Builds a [`cmpxchg`](https://llvm.org/docs/LangRef.html#cmpxchg-instruction) instruction. + /// + /// This instruction allows to atomically compare and replace memory. /// /// May return one of the following errors: /// - `Err(BuilderError::PointeeTypeMismatch)` if the pointer does not point to an element of the value type /// - `Err(BuilderError::ValueTypeMismatch)` if the value to compare and the new values are not of the same type, or if - /// the value does not have a pointer or integer type + /// the value does not have a pointer or integer type /// - `Err(BuilderError::OrderingError)` if the following conditions are not satisfied: /// - Both success and failure orderings are not Monotonic or stronger /// - The failure ordering is stronger than the success ordering @@ -3490,7 +3492,6 @@ impl<'ctx> Builder<'ctx> { /// builder.build_cmpxchg(i32_ptr_param, i32_seven, i32_eight, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic).unwrap(); /// builder.build_return(None).unwrap(); /// ``` - // https://llvm.org/docs/LangRef.html#cmpxchg-instruction pub fn build_cmpxchg>( &self, ptr: PointerValue<'ctx>, diff --git a/src/debug_info.rs b/src/debug_info.rs index 678db68060e..ff0eac6614d 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -400,8 +400,8 @@ impl<'ctx> DebugInfoBuilder<'ctx> { /// * `ty` - Function type. /// * `is_local_to_unit` - True if this function is not externally visible. /// * `is_definition` - True if this is a function definition ("When isDefinition: false, - /// subprograms describe a declaration in the type tree as opposed to a definition of a - /// function"). + /// subprograms describe a declaration in the type tree as opposed to a definition of a + /// function"). /// * `scope_line` - Set to the beginning of the scope this starts /// * `flags` - E.g.: LLVMDIFlagLValueReference. These flags are used to emit dwarf attributes. /// * `is_optimized` - True if optimization is ON. @@ -1363,7 +1363,11 @@ impl<'ctx> DIGlobalVariableExpression<'ctx> { } } -/// https://llvm.org/docs/LangRef.html#diexpression +/// Specialized metadata node that contains a DWARF-like expression. +/// +/// # Remarks +/// +/// See also the [LLVM language reference](https://llvm.org/docs/LangRef.html#diexpression). #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIExpression<'ctx> { pub(crate) metadata_ref: LLVMMetadataRef, diff --git a/src/lib.rs b/src/lib.rs index cf1691708be..102e33d4114 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,19 +136,19 @@ assert_unique_used_features! { /// Defines the address space in which a global will be inserted. /// -/// The default address space is zero. An address space can always be created from a `u16`: +/// The default address space is number zero. An address space can always be created from a [`u16`]: /// ```no_run /// inkwell::AddressSpace::from(1u16); /// ``` /// -/// An Address space is a 24-bit number. To convert from a u32, use the `TryFrom` instance +/// An address space is a 24-bit number. To convert from a [`u32`], use the [`TryFrom`] implementation: /// /// ```no_run /// inkwell::AddressSpace::try_from(42u32).expect("fits in 24-bit unsigned int"); /// ``` /// /// # Remarks -/// See also: https://llvm.org/doxygen/NVPTXBaseInfo_8h_source.html +/// See also: #[derive(Debug, PartialEq, Eq, Copy, Clone, Default)] pub struct AddressSpace(u32); @@ -379,10 +379,11 @@ pub enum AtomicRMWBinOp { FMin, } -/// Defines the optimization level used to compile a `Module`. +/// Defines the optimization level used to compile a [`Module`](crate::module::Module). /// /// # Remarks -/// See also: https://llvm.org/doxygen/CodeGen_8h_source.html +/// +/// See the C++ API documentation: [`llvm::CodeGenOpt`](https://llvm.org/doxygen/namespacellvm_1_1CodeGenOpt.html). #[repr(u32)] #[derive(Debug, PartialEq, Eq, Copy, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/src/memory_manager.rs b/src/memory_manager.rs index 96af0bbd625..8634f946c9a 100644 --- a/src/memory_manager.rs +++ b/src/memory_manager.rs @@ -11,8 +11,8 @@ use llvm_sys::prelude::LLVMBool; /// /// # StackMap and GC Integration /// -/// By examining the `section_name` argument in [`allocate_data_section`], you -/// can detect sections such as `.llvm_stackmaps` (on ELF) or `__llvm_stackmaps` +/// By examining the `section_name` argument in [`McjitMemoryManager::allocate_data_section`], +/// you can detect sections such as `.llvm_stackmaps` (on ELF) or `__llvm_stackmaps` /// (on Mach-O). Recording the location of these sections may be useful for /// custom garbage collectors. For more information, refer to the [LLVM /// StackMaps documentation](https://llvm.org/docs/StackMaps.html#stack-map-section). diff --git a/src/module.rs b/src/module.rs index 821192d7631..486b4965cff 100644 --- a/src/module.rs +++ b/src/module.rs @@ -859,11 +859,12 @@ impl<'ctx> Module<'ctx> { unsafe { MemoryBuffer::new(memory_buffer) } } - /// Ensures that the current `Module` is valid, and returns a `Result` - /// that describes whether or not it is, returning a LLVM allocated string on error. + /// Check whether the current [`Module`] is valid. + /// + /// The error variant is an LLVM-allocated string. /// /// # Remarks - /// See also: http://llvm.org/doxygen/Analysis_2Analysis_8cpp_source.html + /// See also: [`LLVMVerifyModule`](https://llvm.org/doxygen/group__LLVMCAnalysis.html#ga5645aec2d95116c0432a676db77b2cb0). pub fn verify(&self) -> Result<(), LLVMString> { let mut err_str = MaybeUninit::uninit(); @@ -1627,11 +1628,15 @@ impl<'ctx> Module<'ctx> { } /// Construct and run a set of passes over a module. + /// /// This function takes a string with the passes that should be used. - /// The format of this string is the same as opt's -passes argument for the new pass manager. + /// The format of this string is the same as + /// [`opt`](https://llvm.org/docs/CommandGuide/opt.html)'s + /// `-{passes}` argument for the new pass manager. /// Individual passes may be specified, separated by commas. - /// Full pipelines may also be invoked using default and friends. - /// See opt for full reference of the Passes format. + /// Full pipelines may also be invoked using `"default"` and friends. + /// See [`opt`](https://llvm.org/docs/CommandGuide/opt.html) + /// for full reference of the `passes` format. #[llvm_versions(13..)] pub fn run_passes( &self, diff --git a/src/passes.rs b/src/passes.rs index d0fd073dc7f..2ab9fd26746 100644 --- a/src/passes.rs +++ b/src/passes.rs @@ -636,7 +636,7 @@ impl PassManager { /// right-hand side. /// /// 2. Bitwise operators with constant operands are always grouped so that - /// shifts are performed first, then ors, then ands, then xors. + /// shifts are performed first, then ORs, then ANDs, then XORs. /// /// 3. Compare instructions are converted from <, >, ≤, or ≥ to = or ≠ if possible. /// @@ -906,7 +906,7 @@ impl PassManager { /// returns something else (like constant 0), and can still be TRE’d. It can be /// TRE'd if all other return instructions in the function return the exact same value. /// - /// 4. If it can prove that callees do not access theier caller stack frame, + /// 4. If it can prove that callees do not access their caller stack frame, /// they are marked as eligible for tail call elimination (by the code generator). #[llvm_versions(..=16)] pub fn add_tail_call_elimination_pass(&self) { diff --git a/src/types/enums.rs b/src/types/enums.rs index d17394698d4..4c731943d45 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -72,7 +72,7 @@ enum_type_set! { StructType, /// A contiguous homogeneous "SIMD" container type. VectorType, - /// A contiguous homogenous scalable "SIMD" container type. + /// A contiguous homogeneous scalable "SIMD" container type. ScalableVectorType, /// A valueless type. VoidType, @@ -93,7 +93,7 @@ enum_type_set! { StructType, /// A contiguous homogeneous "SIMD" container type. VectorType, - /// A contiguous homogenous scalable "SIMD" container type. + /// A contiguous homogeneous scalable "SIMD" container type. ScalableVectorType, } } diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 1de4cc206ea..a6499f65813 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -175,7 +175,7 @@ impl<'ctx> InstructionValue<'ctx> { return Some(*self); } } - return self.get_next_instruction()?.get_instruction_with_name(name); + self.get_next_instruction()?.get_instruction_with_name(name) } /// Set name of the `InstructionValue`. @@ -534,7 +534,7 @@ impl<'ctx> InstructionValue<'ctx> { /// 2) Bitcast has one: a variable float pointer %0 /// 3) Function call has two: i8 pointer %1 argument, and the free function itself /// 4) Void return has zero: void is not a value and does not count as an operand - /// even though the return instruction can take values. + /// even though the return instruction can take values. pub fn get_num_operands(self) -> u32 { unsafe { LLVMGetNumOperands(self.as_value_ref()) as u32 } } @@ -602,7 +602,7 @@ impl<'ctx> InstructionValue<'ctx> { /// 2) Bitcast has one: a variable float pointer %0 /// 3) Function call has two: i8 pointer %1 argument, and the free function itself /// 4) Void return has zero: void is not a value and does not count as an operand - /// even though the return instruction can take values. + /// even though the return instruction can take values. pub fn get_operand(self, index: u32) -> Option, BasicBlock<'ctx>>> { let num_operands = self.get_num_operands(); diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index 72fa704b5d6..69db8e065b7 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -1011,7 +1011,7 @@ fn test_floats() { assert_eq!(f128_pi.get_type(), f128_type); assert_eq!(f128_pi_cast.get_type(), f128_type); - // REIVEW: Why are these not FPTrunc, FPExt, FPToSI, FPToUI, BitCast instructions? + // REVIEW: Why are these not FPTrunc, FPExt, FPToSI, FPToUI, BitCast instructions? // Only thing I can think of is that they're constants and therefore precalculated assert!(f32_pi.as_instruction().is_none()); assert!(f128_pi.as_instruction().is_none()); From b63b10473eff36d688e372e8c9f0e27b2e3be8b7 Mon Sep 17 00:00:00 2001 From: Etienne Wodey <44871469+airwoodix@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:35:26 +0100 Subject: [PATCH 04/26] FunctionType::get_param_types: support metadata type (#573) Co-authored-by: Dan Kolsoi --- src/types/enums.rs | 22 ++++++++++++++++++++++ src/types/fn_type.rs | 11 +++++++---- tests/all/test_types.rs | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/types/enums.rs b/src/types/enums.rs index 4c731943d45..6d09c38bb30 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -111,6 +111,28 @@ enum_type_set! { } impl<'ctx> BasicMetadataTypeEnum<'ctx> { + /// Create [`BasicMetadataTypeEnum`] from [`LLVMTypeRef`]. + /// + /// # Safety + /// + /// Undefined behavior if the referenced type cannot be represented as [`BasicMetadataTypeEnum`], + /// or the underlying pointer is null. + /// + /// Before LLVM 6, [`BasicMetadataTypeEnum::MetadataType`] variants cannot be created + /// with this function. Attempting to do results in undefined behavior. + #[llvm_versions(6..)] + pub unsafe fn new(type_: LLVMTypeRef) -> Self { + match LLVMGetTypeKind(type_) { + LLVMTypeKind::LLVMMetadataTypeKind => Self::MetadataType(MetadataType::new(type_)), + _ => BasicTypeEnum::new(type_).into(), + } + } + + #[llvm_versions(..6)] + pub unsafe fn new(type_: LLVMTypeRef) -> Self { + BasicTypeEnum::new(type_).into() + } + pub fn into_array_type(self) -> ArrayType<'ctx> { if let BasicMetadataTypeEnum::ArrayType(t) = self { t diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index 25f3e8c92f3..bf41ede81f8 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -10,7 +10,7 @@ use std::mem::forget; use crate::context::ContextRef; use crate::support::LLVMString; use crate::types::traits::AsTypeRef; -use crate::types::{AnyType, BasicTypeEnum, PointerType, Type}; +use crate::types::{AnyType, BasicMetadataTypeEnum, BasicTypeEnum, PointerType, Type}; use crate::AddressSpace; /// A `FunctionType` is the type of a function variable. @@ -96,7 +96,7 @@ impl<'ctx> FunctionType<'ctx> { /// /// # Example /// - /// ```no_run + /// ``` /// use inkwell::context::Context; /// /// let context = Context::create(); @@ -107,7 +107,7 @@ impl<'ctx> FunctionType<'ctx> { /// assert_eq!(param_types.len(), 1); /// assert_eq!(param_types[0].into_float_type(), f32_type); /// ``` - pub fn get_param_types(self) -> Vec> { + pub fn get_param_types(self) -> Vec> { let count = self.count_param_types(); let mut raw_vec: Vec = Vec::with_capacity(count as usize); let ptr = raw_vec.as_mut_ptr(); @@ -120,7 +120,10 @@ impl<'ctx> FunctionType<'ctx> { Vec::from_raw_parts(ptr, count as usize, count as usize) }; - raw_vec.iter().map(|val| unsafe { BasicTypeEnum::new(*val) }).collect() + raw_vec + .iter() + .map(|val| unsafe { BasicMetadataTypeEnum::new(*val) }) + .collect() } /// Counts the number of param types this `FunctionType` has. diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index 1037984f9ff..f7832a488c8 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -1,4 +1,5 @@ use inkwell::context::Context; +use inkwell::memory_buffer::MemoryBuffer; use inkwell::types::BasicType; use inkwell::values::AnyValue; use inkwell::AddressSpace; @@ -141,6 +142,30 @@ fn test_function_type() { assert_eq!(fn_type.get_context(), context); } +/// Check that `FunctionType::get_param_types()` can handle metadata arguments. +/// Regression test for inkwell#546 +#[llvm_versions(6..)] +#[test] +fn test_function_type_metadata_params() { + let llvm_ir = r#" + declare void @my_fn(i32, metadata) + "#; + + let context = Context::create(); + let i32_type = context.i32_type(); + let md_type = context.metadata_type(); + + let memory_buffer = MemoryBuffer::create_from_memory_range_copy(llvm_ir.as_bytes(), "my_mod"); + let module = context.create_module_from_ir(memory_buffer).unwrap(); + + let fn_type = module.get_function("my_fn").unwrap().get_type(); + let param_types = fn_type.get_param_types(); + + assert_eq!(param_types.len(), 2); + assert_eq!(param_types[0].into_int_type(), i32_type); + assert_eq!(param_types[1].into_metadata_type(), md_type); +} + #[test] fn test_sized_types() { unsafe { Context::get_global(sized_types) } From b6bf69a6013d196f046b09c078349860e2eedb1f Mon Sep 17 00:00:00 2001 From: Etienne Wodey <44871469+airwoodix@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:46:19 +0100 Subject: [PATCH 05/26] CallSiteValue::get_called_fn_value: return None on indirect calls (#572) Co-authored-by: Dan Kolsoi --- src/values/call_site_value.rs | 74 ++++++++++++++++++++++++++++++++--- src/values/fn_value.rs | 4 +- tests/all/test_attributes.rs | 2 +- tests/all/test_values.rs | 50 ++++++++++++++++++++++- 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/src/values/call_site_value.rs b/src/values/call_site_value.rs index 7d307ef34ed..241789f7b3b 100644 --- a/src/values/call_site_value.rs +++ b/src/values/call_site_value.rs @@ -1,8 +1,10 @@ use std::fmt::{self, Display}; use either::Either; +#[llvm_versions(8..)] +use llvm_sys::core::LLVMGetCalledFunctionType; use llvm_sys::core::{ - LLVMGetInstructionCallConv, LLVMGetTypeKind, LLVMIsTailCall, LLVMSetInstrParamAlignment, + LLVMGetCalledValue, LLVMGetInstructionCallConv, LLVMGetTypeKind, LLVMIsTailCall, LLVMSetInstrParamAlignment, LLVMSetInstructionCallConv, LLVMSetTailCall, LLVMTypeOf, }; #[llvm_versions(18..)] @@ -11,6 +13,7 @@ use llvm_sys::prelude::LLVMValueRef; use llvm_sys::LLVMTypeKind; use crate::attributes::{Attribute, AttributeLoc}; +use crate::types::FunctionType; #[llvm_versions(18..)] use crate::values::operand_bundle::OperandBundleIter; use crate::values::{AsValueRef, BasicValueEnum, FunctionValue, InstructionValue, Value}; @@ -201,9 +204,12 @@ impl<'ctx> CallSiteValue<'ctx> { /// Gets the `FunctionValue` this `CallSiteValue` is based on. /// + /// Returns [`None`] if the call this value bases on is indirect or the retrieved function + /// value doesn't have the same type as the underlying call instruction. + /// /// # Example /// - /// ```no_run + /// ``` /// use inkwell::context::Context; /// /// let context = Context::create(); @@ -220,12 +226,68 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// - /// assert_eq!(call_site_value.get_called_fn_value(), fn_value); + /// assert_eq!(call_site_value.get_called_fn_value(), Some(fn_value)); /// ``` - pub fn get_called_fn_value(self) -> FunctionValue<'ctx> { - use llvm_sys::core::LLVMGetCalledValue; + pub fn get_called_fn_value(self) -> Option> { + // SAFETY: the passed LLVMValueRef is of type CallSite + let called_value = unsafe { LLVMGetCalledValue(self.as_value_ref()) }; + + let fn_value = unsafe { FunctionValue::new(called_value) }; + + // Check that the retrieved function value has the same type as the callee. + // This matches the behavior of the C++ API `CallBase::getCalledFunction`. + // This is only possible on LLVM >=8, where the `LLVMGetCalledFunctionType` API exists. + self.get_called_fn_value_check_type_consistency(fn_value) + } + + #[llvm_versions(..8)] + #[inline] + fn get_called_fn_value_check_type_consistency( + &self, + fn_value: Option>, + ) -> Option> { + fn_value + } + + #[llvm_versions(8..)] + #[inline] + fn get_called_fn_value_check_type_consistency( + &self, + fn_value: Option>, + ) -> Option> { + fn_value.filter(|fn_value| fn_value.get_type() == self.get_called_fn_type()) + } - unsafe { FunctionValue::new(LLVMGetCalledValue(self.as_value_ref())).expect("This should never be null?") } + /// Gets the type of the function called by the instruction this `CallSiteValue` is based on. + /// + /// # Example + /// + /// ``` + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let builder = context.create_builder(); + /// let module = context.create_module("my_mod"); + /// let i32_type = context.i32_type(); + /// let fn_type = i32_type.fn_type(&[], false); + /// let fn_value = module.add_function("my_fn", fn_type, None); + /// + /// let entry_bb = context.append_basic_block(fn_value, "entry"); + /// builder.position_at_end(entry_bb); + /// + /// // Recursive call. + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); + /// + /// assert_eq!(call_site_value.get_called_fn_type(), fn_type); + /// ``` + #[llvm_versions(8..)] + pub fn get_called_fn_type(self) -> FunctionType<'ctx> { + // SAFETY: the passed LLVMValueRef is of type CallSite + let fn_type_ref = unsafe { LLVMGetCalledFunctionType(self.as_value_ref()) }; + + // FIXME?: this assumes that fn_type_ref is not null. + // SAFETY: fn_type_ref is a function type reference. + unsafe { FunctionType::new(fn_type_ref) } } /// Counts the number of `Attribute`s on this `CallSiteValue` at an index. diff --git a/src/values/fn_value.rs b/src/values/fn_value.rs index 00a5126f135..ed8d98722fa 100644 --- a/src/values/fn_value.rs +++ b/src/values/fn_value.rs @@ -41,12 +41,10 @@ impl<'ctx> FunctionValue<'ctx> { /// /// The ref must be valid and of type function. pub unsafe fn new(value: LLVMValueRef) -> Option { - if value.is_null() { + if value.is_null() || LLVMIsAFunction(value).is_null() { return None; } - assert!(!LLVMIsAFunction(value).is_null()); - Some(FunctionValue { fn_value: Value::new(value), }) diff --git a/tests/all/test_attributes.rs b/tests/all/test_attributes.rs index 92aab1cf073..00df668b0ac 100644 --- a/tests/all/test_attributes.rs +++ b/tests/all/test_attributes.rs @@ -227,7 +227,7 @@ fn test_attributes_on_call_site_values() { assert!(call_site_value .get_string_attribute(AttributeLoc::Return, "my_key") .is_none()); - assert_eq!(call_site_value.get_called_fn_value(), fn_value); + assert_eq!(call_site_value.get_called_fn_value(), Some(fn_value)); call_site_value.set_alignment_attribute(AttributeLoc::Return, 16); diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index 69db8e065b7..a395f553cef 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -2,11 +2,12 @@ use inkwell::attributes::AttributeLoc; #[llvm_versions(7..)] use inkwell::comdat::ComdatSelectionKind; use inkwell::context::Context; +use inkwell::memory_buffer::MemoryBuffer; use inkwell::module::Linkage::*; use inkwell::types::{AnyTypeEnum, StringRadix, VectorType}; #[llvm_versions(18..)] use inkwell::values::OperandBundle; -use inkwell::values::{AnyValue, InstructionOpcode::*, FIRST_CUSTOM_METADATA_KIND_ID}; +use inkwell::values::{AnyValue, CallSiteValue, InstructionOpcode::*, FIRST_CUSTOM_METADATA_KIND_ID}; use inkwell::{AddressSpace, DLLStorageClass, GlobalVisibility, ThreadLocalMode}; #[llvm_versions(18..)] @@ -147,6 +148,53 @@ fn test_call_site_operand_bundles() { args_iter.for_each(|arg| assert!(arg.into_int_value().is_const())); } +/// Check that `CallSiteValue::get_called_fn_value` returns `None` if the underlying call is indirect. +/// Regression test for inkwell#571. +/// Retricted to LLVM >= 15, since the input IR uses opaque pointers. +#[llvm_versions(15..)] +#[test] +fn test_call_site_function_value_indirect_call() { + // ```c + // void dummy_fn(); + // + // void my_fn() { + // void (*fn_ptr)(void) = &dummy_fn; + // (*fn_ptr)(); + // } + // ``` + + let llvm_ir = r#" + source_filename = "my_mod"; + + define void @my_fn() { + entry: + %0 = alloca ptr, align 8 + store ptr @dummy_fn, ptr %0, align 8 + %1 = load ptr, ptr %0, align 8 + call void %1() + ret void + } + + declare void @dummy_fn(); + "#; + + let memory_buffer = MemoryBuffer::create_from_memory_range_copy(llvm_ir.as_bytes(), "my_mod"); + let context = Context::create(); + let module = context.create_module_from_ir(memory_buffer).unwrap(); + + let main_fn = module.get_function("my_fn").unwrap(); + let inst = main_fn + .get_last_basic_block() + .unwrap() + .get_instructions() + .nth(3) + .unwrap(); + let call_site_value = CallSiteValue::try_from(inst).unwrap(); + + let fn_value = call_site_value.get_called_fn_value(); + assert!(fn_value.is_none()); +} + #[test] fn test_set_get_name() { let context = Context::create(); From caabaa5a8e05c52c531f9a0df784ac5651434803 Mon Sep 17 00:00:00 2001 From: Etienne Wodey <44871469+airwoodix@users.noreply.github.com> Date: Tue, 25 Feb 2025 04:28:10 +0100 Subject: [PATCH 06/26] workflows: run rustfmt check, fix typos check (#575) * Apply rustfmt * Fix typos * workflows: run rustfmt check in test pipeline * Fix typo. --------- Co-authored-by: Dan Kolsoi --- .github/workflows/test.yml | 12 +++++++---- src/basic_block.rs | 8 +++++++- src/builder.rs | 42 +++++++++++++++++++++++++------------- src/context.rs | 8 +++++++- tests/all/test_values.rs | 2 +- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f5178379728..e08d02c9a8c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,16 +9,20 @@ env: DOC_PATH: target/doc jobs: - typos: - name: Typos + lint: + name: Linting runs-on: ubuntu-latest steps: + - name: Checkout Repo + uses: actions/checkout@v4 - name: Install Rust Stable uses: dtolnay/rust-toolchain@stable - name: Install typos uses: taiki-e/install-action@typos - - name: Run typos + - name: Check typos run: typos . + - name: Check code formatting + run: cargo fmt --check tests: name: "LLVM ${{ matrix.llvm-version[0] }}: ${{ matrix.os }}" runs-on: ${{ matrix.os }} @@ -74,7 +78,7 @@ jobs: doc: name: Documentation runs-on: ubuntu-20.04 - needs: [typos, tests] + needs: [lint, tests] if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: - uses: actions/checkout@v4 diff --git a/src/basic_block.rs b/src/basic_block.rs index 6d039a67bde..636cc5de07c 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -481,7 +481,13 @@ impl<'ctx> BasicBlock<'ctx> { { use llvm_sys::core::LLVMSetValueName2; - unsafe { LLVMSetValueName2(LLVMBasicBlockAsValue(self.basic_block), c_string.as_ptr(), c_string.to_bytes().len()) }; + unsafe { + LLVMSetValueName2( + LLVMBasicBlockAsValue(self.basic_block), + c_string.as_ptr(), + c_string.to_bytes().len(), + ) + }; } } diff --git a/src/builder.rs b/src/builder.rs index 004ea5b9b1d..6078075a4b7 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -5,18 +5,18 @@ use llvm_sys::core::LLVMBuildCallWithOperandBundles; use llvm_sys::core::{ LLVMAddCase, LLVMAddClause, LLVMAddDestination, LLVMBuildAShr, LLVMBuildAdd, LLVMBuildAddrSpaceCast, LLVMBuildAggregateRet, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc, - LLVMBuildAtomicCmpXchg, LLVMBuildAtomicRMW, LLVMBuildBinOp, LLVMBuildBitCast, LLVMBuildBr, LLVMBuildCast, LLVMBuildCondBr, - LLVMBuildExactSDiv, LLVMBuildExtractElement, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, - LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPCast, LLVMBuildFPExt, LLVMBuildFPToSI, LLVMBuildFPToUI, LLVMBuildFPTrunc, - LLVMBuildFRem, LLVMBuildFSub, LLVMBuildFence, LLVMBuildFree, LLVMBuildGlobalString, LLVMBuildGlobalStringPtr, - LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue, LLVMBuildIntCast, - LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad, LLVMBuildMalloc, - LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd, LLVMBuildNUWMul, - LLVMBuildNUWNeg, LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, - LLVMBuildPtrToInt, LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, LLVMBuildSExt, - LLVMBuildSExtOrBitCast, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl, LLVMBuildShuffleVector, - LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast, LLVMBuildUDiv, - LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, + LLVMBuildAtomicCmpXchg, LLVMBuildAtomicRMW, LLVMBuildBinOp, LLVMBuildBitCast, LLVMBuildBr, LLVMBuildCast, + LLVMBuildCondBr, LLVMBuildExactSDiv, LLVMBuildExtractElement, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, + LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPCast, LLVMBuildFPExt, LLVMBuildFPToSI, LLVMBuildFPToUI, + LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub, LLVMBuildFence, LLVMBuildFree, LLVMBuildGlobalString, + LLVMBuildGlobalStringPtr, LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue, + LLVMBuildIntCast, LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad, + LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd, + LLVMBuildNUWMul, LLVMBuildNUWNeg, LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, + LLVMBuildPointerCast, LLVMBuildPtrToInt, LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, + LLVMBuildSExt, LLVMBuildSExtOrBitCast, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl, + LLVMBuildShuffleVector, LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast, + LLVMBuildUDiv, LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, LLVMBuildZExtOrBitCast, LLVMClearInsertionPosition, LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMInsertIntoBuilder, LLVMInsertIntoBuilderWithName, LLVMPositionBuilder, LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore, LLVMSetCleanup, @@ -2622,12 +2622,26 @@ impl<'ctx> Builder<'ctx> { unsafe { Ok(T::new(value)) } } - pub fn build_binop>(&self, op: InstructionOpcode, lhs: T, rhs: T, name: &str) -> Result, BuilderError> { + pub fn build_binop>( + &self, + op: InstructionOpcode, + lhs: T, + rhs: T, + name: &str, + ) -> Result, BuilderError> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildBinOp(self.builder, op.into(), lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildBinOp( + self.builder, + op.into(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(BasicValueEnum::new(value)) } } diff --git a/src/context.rs b/src/context.rs index 82cb783bea1..e089e97dafc 100644 --- a/src/context.rs +++ b/src/context.rs @@ -345,7 +345,13 @@ impl ContextImpl { fn metadata_string<'ctx>(&self, string: &str) -> MetadataValue<'ctx> { let c_string = to_c_str(string); - unsafe { MetadataValue::new(LLVMMDStringInContext(self.0, c_string.as_ptr(), c_string.to_bytes().len() as u32)) } + unsafe { + MetadataValue::new(LLVMMDStringInContext( + self.0, + c_string.as_ptr(), + c_string.to_bytes().len() as u32, + )) + } } fn get_kind_id(&self, key: &str) -> u32 { diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index a395f553cef..4a971201342 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -150,7 +150,7 @@ fn test_call_site_operand_bundles() { /// Check that `CallSiteValue::get_called_fn_value` returns `None` if the underlying call is indirect. /// Regression test for inkwell#571. -/// Retricted to LLVM >= 15, since the input IR uses opaque pointers. +/// Restricted to LLVM >= 15, since the input IR uses opaque pointers. #[llvm_versions(15..)] #[test] fn test_call_site_function_value_indirect_call() { From b38c771e723eb0660824699f046676bfc0e97ad7 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 10 Mar 2025 11:08:22 +0800 Subject: [PATCH 07/26] Implement feature for disabling opaque pointers on LLVM 15 and 16 (#570) * Implement feature for disabling opaque pointers on LLVM 15 * Fix missing refactoring in docs * Update compile_error messages * Extend ability to disable opaque pointers to LLVM 16 --------- Co-authored-by: Dan Kolsoi --- Cargo.toml | 24 +- .../implementation_typed_pointers.rs | 6 +- src/basic_block.rs | 4 +- src/builder.rs | 209 ++++--- src/context.rs | 19 +- src/lib.rs | 21 + src/types/array_type.rs | 18 +- src/types/float_type.rs | 18 +- src/types/fn_type.rs | 18 +- src/types/int_type.rs | 18 +- src/types/ptr_type.rs | 83 ++- src/types/scalable_vec_type.rs | 18 +- src/types/struct_type.rs | 18 +- src/types/traits.rs | 4 +- src/types/vec_type.rs | 18 +- src/values/basic_value_use.rs | 12 +- src/values/instruction_value.rs | 20 +- src/values/ptr_value.rs | 39 +- tests/all/test_builder.rs | 539 ++---------------- tests/all/test_context.rs | 14 +- tests/all/test_execution_engine.rs | 14 +- tests/all/test_instruction_conversion.rs | 14 +- tests/all/test_instruction_values.rs | 179 +----- tests/all/test_types.rs | 156 +---- tests/all/test_values.rs | 161 +----- 25 files changed, 421 insertions(+), 1223 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3333ab9df93..66b883542df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,18 +14,20 @@ edition = "2021" [features] default = ["target-all"] +typed-pointers = [] + # Please update internal_macros::FEATURE_VERSIONS when adding a new LLVM version -llvm4-0 = ["llvm-sys-40"] -llvm5-0 = ["llvm-sys-50"] -llvm6-0 = ["llvm-sys-60"] -llvm7-0 = ["llvm-sys-70"] -llvm8-0 = ["llvm-sys-80"] -llvm9-0 = ["llvm-sys-90"] -llvm10-0 = ["llvm-sys-100"] -llvm11-0 = ["llvm-sys-110"] -llvm12-0 = ["llvm-sys-120"] -llvm13-0 = ["llvm-sys-130"] -llvm14-0 = ["llvm-sys-140"] +llvm4-0 = ["llvm-sys-40", "typed-pointers"] +llvm5-0 = ["llvm-sys-50", "typed-pointers"] +llvm6-0 = ["llvm-sys-60", "typed-pointers"] +llvm7-0 = ["llvm-sys-70", "typed-pointers"] +llvm8-0 = ["llvm-sys-80", "typed-pointers"] +llvm9-0 = ["llvm-sys-90", "typed-pointers"] +llvm10-0 = ["llvm-sys-100", "typed-pointers"] +llvm11-0 = ["llvm-sys-110", "typed-pointers"] +llvm12-0 = ["llvm-sys-120", "typed-pointers"] +llvm13-0 = ["llvm-sys-130", "typed-pointers"] +llvm14-0 = ["llvm-sys-140", "typed-pointers"] llvm15-0 = ["llvm-sys-150"] llvm16-0 = ["llvm-sys-160"] llvm17-0 = ["llvm-sys-170"] diff --git a/examples/kaleidoscope/implementation_typed_pointers.rs b/examples/kaleidoscope/implementation_typed_pointers.rs index acf7c0253fb..5e9ca8bfb0b 100644 --- a/examples/kaleidoscope/implementation_typed_pointers.rs +++ b/examples/kaleidoscope/implementation_typed_pointers.rs @@ -11,8 +11,6 @@ use inkwell::types::BasicMetadataTypeEnum; use inkwell::values::{BasicMetadataValueEnum, BasicValueEnum, FloatValue, FunctionValue, PointerValue}; use inkwell::FloatPredicate; -use inkwell_internals::llvm_versions; - use crate::Token::*; const ANONYMOUS_FUNCTION_NAME: &str = "anonymous"; @@ -856,12 +854,12 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { builder.build_alloca(self.context.f64_type(), name).unwrap() } - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> BasicValueEnum<'ctx> { self.builder.build_load(ptr, name).unwrap() } - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> BasicValueEnum<'ctx> { self.builder.build_load(self.context.f64_type(), ptr, name).unwrap() } diff --git a/src/basic_block.rs b/src/basic_block.rs index 636cc5de07c..1e725c0b9ba 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -288,9 +288,9 @@ impl<'ctx> BasicBlock<'ctx> { /// /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false); diff --git a/src/builder.rs b/src/builder.rs index 6078075a4b7..0f7c70578d0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -22,15 +22,14 @@ use llvm_sys::core::{ LLVMSetCleanup, }; #[llvm_versions(..=14)] -use llvm_sys::core::{ - LLVMBuildCall, LLVMBuildGEP, LLVMBuildInBoundsGEP, LLVMBuildInvoke, LLVMBuildLoad, LLVMBuildPtrDiff, - LLVMBuildStructGEP, -}; +use llvm_sys::core::{LLVMBuildCall, LLVMBuildInvoke}; #[llvm_versions(15..)] -use llvm_sys::core::{ - LLVMBuildCall2, LLVMBuildGEP2, LLVMBuildInBoundsGEP2, LLVMBuildInvoke2, LLVMBuildLoad2, LLVMBuildPtrDiff2, - LLVMBuildStructGEP2, -}; +use llvm_sys::core::{LLVMBuildCall2, LLVMBuildInvoke2}; +#[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))] +#[cfg_attr(feature = "llvm15-0", allow(deprecated))] +use llvm_sys::core::{LLVMBuildGEP, LLVMBuildInBoundsGEP, LLVMBuildLoad, LLVMBuildPtrDiff, LLVMBuildStructGEP}; +#[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))] +use llvm_sys::core::{LLVMBuildGEP2, LLVMBuildInBoundsGEP2, LLVMBuildLoad2, LLVMBuildPtrDiff2, LLVMBuildStructGEP2}; #[llvm_versions(8..)] use llvm_sys::core::{LLVMBuildIntCast2, LLVMBuildMemCpy, LLVMBuildMemMove, LLVMBuildMemSet}; @@ -576,9 +575,9 @@ impl<'ctx> Builder<'ctx> { /// }; /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_ty = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -697,6 +696,9 @@ impl<'ctx> Builder<'ctx> { /// }; /// /// // type of an exception in C++ + /// #[cfg(feature = "typed-pointers")] + /// let ptr_type = context.i8_type().ptr_type(AddressSpace::default()); + /// #[cfg(not(feature = "typed-pointers"))] /// let ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[ptr_type.into(), i32_type.into()], false); @@ -828,9 +830,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i8_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -860,9 +862,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i8_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -895,9 +897,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i8_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -933,9 +935,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i8_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -1055,9 +1057,9 @@ impl<'ctx> Builder<'ctx> { /// }; /// /// // type of an exception in C++ - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i8_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_type = context.i32_type(); /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -1081,7 +1083,7 @@ impl<'ctx> Builder<'ctx> { // REVIEW: Doesn't GEP work on array too? /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub unsafe fn build_gep( &self, ptr: PointerValue<'ctx>, @@ -1095,6 +1097,8 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = LLVMBuildGEP( self.builder, ptr.as_value_ref(), @@ -1102,13 +1106,22 @@ impl<'ctx> Builder<'ctx> { index_values.len() as u32, c_string.as_ptr(), ); + #[cfg(feature = "llvm16-0")] + let value = LLVMBuildGEP2( + self.builder, + ptr.get_type().get_element_type().as_type_ref(), + ptr.as_value_ref(), + index_values.as_mut_ptr(), + index_values.len() as u32, + c_string.as_ptr(), + ); Ok(PointerValue::new(value)) } // REVIEW: Doesn't GEP work on array too? /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub unsafe fn build_gep>( &self, pointee_ty: T, @@ -1138,7 +1151,7 @@ impl<'ctx> Builder<'ctx> { // REVIEW: Doesn't GEP work on array too? // REVIEW: This could be merge in with build_gep via a in_bounds: bool param /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub unsafe fn build_in_bounds_gep( &self, ptr: PointerValue<'ctx>, @@ -1152,6 +1165,8 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = LLVMBuildInBoundsGEP( self.builder, ptr.as_value_ref(), @@ -1159,6 +1174,15 @@ impl<'ctx> Builder<'ctx> { index_values.len() as u32, c_string.as_ptr(), ); + #[cfg(feature = "llvm16-0")] + let value = LLVMBuildInBoundsGEP2( + self.builder, + ptr.get_type().get_element_type().as_type_ref(), + ptr.as_value_ref(), + index_values.as_mut_ptr(), + index_values.len() as u32, + c_string.as_ptr(), + ); Ok(PointerValue::new(value)) } @@ -1166,7 +1190,7 @@ impl<'ctx> Builder<'ctx> { // REVIEW: Doesn't GEP work on array too? // REVIEW: This could be merge in with build_gep via a in_bounds: bool param /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub unsafe fn build_in_bounds_gep>( &self, pointee_ty: T, @@ -1207,9 +1231,9 @@ impl<'ctx> Builder<'ctx> { /// let module = context.create_module("struct_gep"); /// let void_type = context.void_type(); /// let i32_ty = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_ty = context.ptr_type(AddressSpace::default()); /// let field_types = &[i32_ty.into(), i32_ty.into()]; /// let struct_ty = context.struct_type(field_types, false); @@ -1229,7 +1253,7 @@ impl<'ctx> Builder<'ctx> { /// assert!(builder.build_struct_gep(struct_ptr, 1, "struct_gep").is_ok()); /// assert!(builder.build_struct_gep(struct_ptr, 2, "struct_gep").is_err()); /// ``` - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub fn build_struct_gep( &self, ptr: PointerValue<'ctx>, @@ -1254,7 +1278,19 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = unsafe { LLVMBuildStructGEP(self.builder, ptr.as_value_ref(), index, c_string.as_ptr()) }; + #[cfg(feature = "llvm16-0")] + let value = unsafe { + LLVMBuildStructGEP2( + self.builder, + ptr.get_type().get_element_type().as_type_ref(), + ptr.as_value_ref(), + index, + c_string.as_ptr(), + ) + }; unsafe { Ok(PointerValue::new(value)) } } @@ -1273,9 +1309,9 @@ impl<'ctx> Builder<'ctx> { /// let module = context.create_module("struct_gep"); /// let void_type = context.void_type(); /// let i32_ty = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_ty = context.ptr_type(AddressSpace::default()); /// let field_types = &[i32_ty.into(), i32_ty.into()]; /// let struct_ty = context.struct_type(field_types, false); @@ -1295,7 +1331,7 @@ impl<'ctx> Builder<'ctx> { /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 1, "struct_gep").is_ok()); /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 2, "struct_gep").is_err()); /// ``` - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub fn build_struct_gep>( &self, pointee_ty: T, @@ -1347,9 +1383,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false); /// let fn_value = module.add_function("ret", fn_type, None); @@ -1361,7 +1397,7 @@ impl<'ctx> Builder<'ctx> { /// builder.build_ptr_diff(i32_ptr_param1, i32_ptr_param2, "diff").unwrap(); /// builder.build_return(None).unwrap(); /// ``` - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub fn build_ptr_diff( &self, lhs_ptr: PointerValue<'ctx>, @@ -1372,6 +1408,8 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = unsafe { LLVMBuildPtrDiff( self.builder, @@ -1380,6 +1418,24 @@ impl<'ctx> Builder<'ctx> { c_string.as_ptr(), ) }; + #[cfg(feature = "llvm16-0")] + let value = { + if lhs_ptr.get_type().as_basic_type_enum() != rhs_ptr.get_type().as_basic_type_enum() { + return Err(BuilderError::ValueTypeMismatch( + "The values must have the same pointer type.", + )); + } + + unsafe { + LLVMBuildPtrDiff2( + self.builder, + lhs_ptr.get_type().get_element_type().as_type_ref(), + lhs_ptr.as_value_ref(), + rhs_ptr.as_value_ref(), + c_string.as_ptr(), + ) + } + }; unsafe { Ok(IntValue::new(value)) } } @@ -1398,9 +1454,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false); /// let fn_value = module.add_function("ret", fn_type, None); @@ -1412,7 +1468,7 @@ impl<'ctx> Builder<'ctx> { /// builder.build_ptr_diff(i32_ptr_type, i32_ptr_param1, i32_ptr_param2, "diff").unwrap(); /// builder.build_return(None).unwrap(); /// ``` - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub fn build_ptr_diff>( &self, pointee_ty: T, @@ -1467,9 +1523,9 @@ impl<'ctx> Builder<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let i32_seven = i32_type.const_int(7, false); /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false); @@ -1507,9 +1563,9 @@ impl<'ctx> Builder<'ctx> { /// let module = context.create_module("ret"); /// let builder = context.create_builder(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false); /// let fn_value = module.add_function("ret", fn_type, None); @@ -1522,14 +1578,25 @@ impl<'ctx> Builder<'ctx> { /// /// builder.build_return(Some(&pointee)).unwrap(); /// ``` - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> Result, BuilderError> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; + #[cfg(feature = "llvm16-0")] + let value = unsafe { + LLVMBuildLoad2( + self.builder, + ptr.get_type().get_element_type().as_type_ref(), + ptr.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(BasicValueEnum::new(value)) } } @@ -1547,9 +1614,9 @@ impl<'ctx> Builder<'ctx> { /// let module = context.create_module("ret"); /// let builder = context.create_builder(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false); /// let fn_value = module.add_function("ret", fn_type, None); @@ -1562,7 +1629,7 @@ impl<'ctx> Builder<'ctx> { /// /// builder.build_return(Some(&pointee)).unwrap(); /// ``` - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub fn build_load>( &self, pointee_ty: T, @@ -2907,21 +2974,9 @@ impl<'ctx> Builder<'ctx> { /// /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value(); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value(); /// /// let const_int1 = i32_type.const_int(2, false); @@ -2990,21 +3045,9 @@ impl<'ctx> Builder<'ctx> { /// /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value(); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value(); /// /// let const_int1 = i32_type.const_int(2, false); @@ -3410,9 +3453,9 @@ impl<'ctx> Builder<'ctx> { /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); /// let i32_seven = i32_type.const_int(7, false); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false); /// let fn_value = module.add_function("rmw", fn_type, None); @@ -3443,12 +3486,7 @@ impl<'ctx> Builder<'ctx> { )); } - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] if ptr.get_type().get_element_type() != value.get_type().into() { return Err(BuilderError::PointeeTypeMismatch( "Pointer's pointee type must match the value's type.", @@ -3491,9 +3529,9 @@ impl<'ctx> Builder<'ctx> { /// let module = context.create_module("cmpxchg"); /// let void_type = context.void_type(); /// let i32_type = context.i32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let i32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false); /// let fn_value = module.add_function("", fn_type, None); @@ -3530,12 +3568,7 @@ impl<'ctx> Builder<'ctx> { )); } - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] if ptr.get_type().get_element_type().as_basic_type_enum() != cmp.get_type() { return Err(BuilderError::PointeeTypeMismatch( "The pointer does not point to an element of the value type.", diff --git a/src/context.rs b/src/context.rs index e089e97dafc..0ca9e97955b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,6 +5,8 @@ use crate::InlineAsmDialect; use libc::c_void; #[llvm_versions(..=6)] use llvm_sys::core::LLVMConstInlineAsm; +#[cfg(all(any(feature = "llvm15-0", feature = "llvm16-0"), feature = "typed-pointers"))] +use llvm_sys::core::LLVMContextSetOpaquePointers; #[llvm_versions(12..)] use llvm_sys::core::LLVMCreateTypeAttribute; #[llvm_versions(7..)] @@ -13,7 +15,7 @@ use llvm_sys::core::LLVMGetInlineAsm; use llvm_sys::core::LLVMGetTypeByName2; #[llvm_versions(6..)] use llvm_sys::core::LLVMMetadataTypeInContext; -#[llvm_versions(15..)] +#[cfg(not(feature = "typed-pointers"))] use llvm_sys::core::LLVMPointerTypeInContext; use llvm_sys::core::{ LLVMAppendBasicBlockInContext, LLVMConstStringInContext, LLVMConstStructInContext, LLVMContextCreate, @@ -43,7 +45,9 @@ use crate::targets::TargetData; use crate::types::AnyTypeEnum; #[llvm_versions(6..)] use crate::types::MetadataType; -use crate::types::{AsTypeRef, BasicTypeEnum, FloatType, FunctionType, IntType, PointerType, StructType, VoidType}; +#[cfg(not(feature = "typed-pointers"))] +use crate::types::PointerType; +use crate::types::{AsTypeRef, BasicTypeEnum, FloatType, FunctionType, IntType, StructType, VoidType}; use crate::values::{ ArrayValue, AsValueRef, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, MetadataValue, PointerValue, StructValue, @@ -78,6 +82,11 @@ impl ContextImpl { pub(crate) unsafe fn new(context: LLVMContextRef) -> Self { assert!(!context.is_null()); + #[cfg(all(any(feature = "llvm15-0", feature = "llvm16-0"), feature = "typed-pointers"))] + unsafe { + LLVMContextSetOpaquePointers(context, 0) + }; + ContextImpl(context) } @@ -245,7 +254,7 @@ impl ContextImpl { unsafe { FloatType::new(LLVMPPCFP128TypeInContext(self.0)) } } - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] fn ptr_type<'ctx>(&self, address_space: AddressSpace) -> PointerType<'ctx> { unsafe { PointerType::new(LLVMPointerTypeInContext(self.0, address_space.0)) } } @@ -962,7 +971,7 @@ impl Context { /// assert_eq!(ptr_type.get_address_space(), AddressSpace::default()); /// assert_eq!(ptr_type.get_context(), context); /// ``` - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] #[inline] pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType { self.context.ptr_type(address_space) @@ -1844,7 +1853,7 @@ impl<'ctx> ContextRef<'ctx> { /// assert_eq!(ptr_type.get_address_space(), AddressSpace::default()); /// assert_eq!(ptr_type.get_context(), context); /// ``` - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] #[inline] pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType<'ctx> { self.context.ptr_type(address_space) diff --git a/src/lib.rs b/src/lib.rs index 102e33d4114..ef3fbb2845c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,27 @@ assert_unique_used_features! { "llvm18-0" } +#[cfg(all( + any( + feature = "llvm4-0", + feature = "llvm5-0", + feature = "llvm6-0", + feature = "llvm7-0", + feature = "llvm8-0", + feature = "llvm9-0", + feature = "llvm10-0", + feature = "llvm11-0", + feature = "llvm12-0", + feature = "llvm13-0", + feature = "llvm14-0" + ), + not(feature = "typed-pointers") +))] +compile_error!("Opaque pointers are not supported prior to LLVM version 15.0."); + +#[cfg(all(any(feature = "llvm17-0", feature = "llvm18-0"), feature = "typed-pointers"))] +compile_error!("Typed pointers are not supported starting from LLVM version 17.0."); + /// Defines the address space in which a global will be inserted. /// /// The default address space is number zero. An address space can always be created from a [`u16`]: diff --git a/src/types/array_type.rs b/src/types/array_type.rs index 85568f3009c..c46b6986176 100644 --- a/src/types/array_type.rs +++ b/src/types/array_type.rs @@ -77,25 +77,13 @@ impl<'ctx> ArrayType<'ctx> { /// let i8_array_type = i8_type.array_type(3); /// let i8_array_ptr_type = i8_array_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(i8_array_ptr_type.get_element_type().into_array_type(), i8_array_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/float_type.rs b/src/types/float_type.rs index 3de4f2d11ce..4eb0b0bce04 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -234,25 +234,13 @@ impl<'ctx> FloatType<'ctx> { /// let f32_type = context.f32_type(); /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index bf41ede81f8..73f53f7e538 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -45,25 +45,13 @@ impl<'ctx> FunctionType<'ctx> { /// let fn_type = f32_type.fn_type(&[], false); /// let fn_ptr_type = fn_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(fn_ptr_type.get_element_type().into_function_type(), fn_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/int_type.rs b/src/types/int_type.rs index 95f43a670b2..38487c1241a 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -321,25 +321,13 @@ impl<'ctx> IntType<'ctx> { /// let i8_type = context.i8_type(); /// let i8_ptr_type = i8_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(i8_ptr_type.get_element_type().into_int_type(), i8_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/ptr_type.rs b/src/types/ptr_type.rs index 575aeae5bd0..f1cf9db7c36 100644 --- a/src/types/ptr_type.rs +++ b/src/types/ptr_type.rs @@ -6,7 +6,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::context::ContextRef; use crate::support::LLVMString; use crate::types::traits::AsTypeRef; -#[llvm_versions(..=14)] +#[cfg(feature = "typed-pointers")] use crate::types::AnyTypeEnum; use crate::types::{ArrayType, FunctionType, ScalableVectorType, Type, VectorType}; use crate::values::{ArrayValue, IntValue, PointerValue}; @@ -44,9 +44,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_type_size = f32_ptr_type.size_of(); /// ``` @@ -64,9 +64,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_type_alignment = f32_ptr_type.get_alignment(); /// ``` @@ -84,31 +84,19 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_ptr_type = f32_ptr_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(f32_ptr_ptr_type.get_element_type().into_pointer_type(), f32_ptr_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), @@ -130,9 +118,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// /// assert_eq!(f32_ptr_type.get_context(), context); @@ -152,9 +140,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = f32_ptr_type.fn_type(&[], false); /// ``` @@ -172,9 +160,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_array_type = f32_ptr_type.array_type(3); /// @@ -195,9 +183,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// /// assert_eq!(f32_ptr_type.get_address_space(), AddressSpace::default()); @@ -224,9 +212,9 @@ impl<'ctx> PointerType<'ctx> { /// // Local Context /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_null = f32_ptr_type.const_null(); /// @@ -249,9 +237,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_zero = f32_ptr_type.const_zero(); /// ``` @@ -268,9 +256,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_undef = f32_ptr_type.get_undef(); /// @@ -290,9 +278,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_undef = f32_ptr_type.get_poison(); /// @@ -313,9 +301,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_vec_type = f32_ptr_type.vec_type(3); /// @@ -336,9 +324,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_scalable_vec_type = f32_ptr_type.scalable_vec_type(3); /// @@ -361,14 +349,15 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// /// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type); /// ``` - #[llvm_versions(..=14)] + #[llvm_versions(..=16)] + #[cfg(feature = "typed-pointers")] pub fn get_element_type(self) -> AnyTypeEnum<'ctx> { self.ptr_type.get_element_type() } @@ -382,9 +371,9 @@ impl<'ctx> PointerType<'ctx> { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let f32_ptr_val = f32_ptr_type.const_null(); /// let f32_ptr_array = f32_ptr_type.const_array(&[f32_ptr_val, f32_ptr_val]); diff --git a/src/types/scalable_vec_type.rs b/src/types/scalable_vec_type.rs index b4890768158..82277bd65be 100644 --- a/src/types/scalable_vec_type.rs +++ b/src/types/scalable_vec_type.rs @@ -172,25 +172,13 @@ impl<'ctx> ScalableVectorType<'ctx> { /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3); /// let f32_scalable_vec_ptr_type = f32_scalable_vec_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(f32_scalable_vec_ptr_type.get_element_type().into_scalable_vector_type(), f32_scalable_vec_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index 56e24251569..b907de2cf1b 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -201,25 +201,13 @@ impl<'ctx> StructType<'ctx> { /// let struct_type = context.struct_type(&[f32_type.into(), f32_type.into()], false); /// let struct_ptr_type = struct_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(struct_ptr_type.get_element_type().into_struct_type(), struct_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/traits.rs b/src/types/traits.rs index 368b4d68e0d..1caf9318913 100644 --- a/src/types/traits.rs +++ b/src/types/traits.rs @@ -134,8 +134,8 @@ pub unsafe trait BasicType<'ctx>: AnyType<'ctx> { /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/types/vec_type.rs b/src/types/vec_type.rs index 28ccd1f4b70..3a6a47765e3 100644 --- a/src/types/vec_type.rs +++ b/src/types/vec_type.rs @@ -200,25 +200,13 @@ impl<'ctx> VectorType<'ctx> { /// let f32_vec_type = f32_type.vec_type(3); /// let f32_vec_ptr_type = f32_vec_type.ptr_type(AddressSpace::default()); /// - /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", - /// feature = "llvm8-0", - /// feature = "llvm9-0", - /// feature = "llvm10-0", - /// feature = "llvm11-0", - /// feature = "llvm12-0", - /// feature = "llvm13-0", - /// feature = "llvm14-0" - /// ))] + /// #[cfg(feature = "typed-pointers")] /// assert_eq!(f32_vec_ptr_type.get_element_type().into_vector_type(), f32_vec_type); /// ``` #[cfg_attr( any( - feature = "llvm15-0", - feature = "llvm16-0", + all(feature = "llvm15-0", not(feature = "typed-pointers")), + all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", feature = "llvm18-0" ), diff --git a/src/values/basic_value_use.rs b/src/values/basic_value_use.rs index 32591293770..e847c9f004b 100644 --- a/src/values/basic_value_use.rs +++ b/src/values/basic_value_use.rs @@ -40,9 +40,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -104,9 +104,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -143,9 +143,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index a6499f65813..5007da5abec 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -490,9 +490,9 @@ impl<'ctx> InstructionValue<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -553,9 +553,9 @@ impl<'ctx> InstructionValue<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -657,9 +657,9 @@ impl<'ctx> InstructionValue<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -703,9 +703,9 @@ impl<'ctx> InstructionValue<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// @@ -770,9 +770,9 @@ impl<'ctx> InstructionValue<'ctx> { /// let builder = context.create_builder(); /// let void_type = context.void_type(); /// let f32_type = context.f32_type(); - /// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + /// #[cfg(feature = "typed-pointers")] /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(not(feature = "typed-pointers"))] /// let f32_ptr_type = context.ptr_type(AddressSpace::default()); /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); /// diff --git a/src/values/ptr_value.rs b/src/values/ptr_value.rs index 97726f88629..d94098fc090 100644 --- a/src/values/ptr_value.rs +++ b/src/values/ptr_value.rs @@ -1,6 +1,7 @@ -#[llvm_versions(..=14)] +#[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))] +#[cfg_attr(feature = "llvm15-0", allow(deprecated))] use llvm_sys::core::{LLVMConstGEP, LLVMConstInBoundsGEP}; -#[llvm_versions(15..)] +#[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))] use llvm_sys::core::{LLVMConstGEP2, LLVMConstInBoundsGEP2}; use llvm_sys::core::{LLVMConstAddrSpaceCast, LLVMConstPointerCast, LLVMConstPtrToInt}; @@ -10,7 +11,9 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::fmt::{self, Display}; -use crate::types::{AsTypeRef, BasicType, IntType, PointerType}; +#[cfg(not(feature = "typed-pointers"))] +use crate::types::BasicType; +use crate::types::{AsTypeRef, IntType, PointerType}; use crate::values::{AsValueRef, InstructionValue, IntValue, Value}; use super::AnyValue; @@ -82,10 +85,12 @@ impl<'ctx> PointerValue<'ctx> { // REVIEW: Should this be on array value too? /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub unsafe fn const_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = { LLVMConstGEP( self.as_value_ref(), @@ -93,13 +98,22 @@ impl<'ctx> PointerValue<'ctx> { index_values.len() as u32, ) }; + #[cfg(feature = "llvm16-0")] + let value = { + LLVMConstGEP2( + self.get_type().get_element_type().as_type_ref(), + self.as_value_ref(), + index_values.as_mut_ptr(), + index_values.len() as u32, + ) + }; PointerValue::new(value) } // REVIEW: Should this be on array value too? /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub unsafe fn const_gep>(self, ty: T, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); @@ -116,10 +130,12 @@ impl<'ctx> PointerValue<'ctx> { } /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(..=14)] + #[cfg(feature = "typed-pointers")] pub unsafe fn const_in_bounds_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); + #[cfg(not(feature = "llvm16-0"))] + #[cfg_attr(feature = "llvm15-0", allow(deprecated))] let value = { LLVMConstInBoundsGEP( self.as_value_ref(), @@ -127,12 +143,21 @@ impl<'ctx> PointerValue<'ctx> { index_values.len() as u32, ) }; + #[cfg(feature = "llvm16-0")] + let value = { + LLVMConstInBoundsGEP2( + self.get_type().get_element_type().as_type_ref(), + self.as_value_ref(), + index_values.as_mut_ptr(), + index_values.len() as u32, + ) + }; PointerValue::new(value) } /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. - #[llvm_versions(15..)] + #[cfg(not(feature = "typed-pointers"))] pub unsafe fn const_in_bounds_gep>( self, ty: T, diff --git a/tests/all/test_builder.rs b/tests/all/test_builder.rs index d25f2a27581..2e1869d26c6 100644 --- a/tests/all/test_builder.rs +++ b/tests/all/test_builder.rs @@ -47,19 +47,9 @@ fn test_build_call() { let function3 = module.add_function("call_fn", fn_type2, None); let basic_block3 = context.append_basic_block(function3, "entry"); let fn_ptr = function3.as_global_value().as_pointer_value(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let fn_ptr_type = fn_ptr.get_type(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let fn_ptr_type = context.ptr_type(AddressSpace::default()); builder.position_at_end(basic_block3); @@ -68,26 +58,9 @@ fn test_build_call() { builder.build_store(alloca, fn_ptr).unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let load = builder.build_load(alloca, "load").unwrap().into_pointer_value(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let load = builder .build_load(fn_ptr_type, alloca, "load") .unwrap() @@ -179,19 +152,9 @@ fn test_build_invoke_cleanup_resume() { }; // type of an exception in C++ - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_type = context.ptr_type(AddressSpace::default()); let i32_type = context.i32_type(); let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -263,19 +226,9 @@ fn test_build_invoke_catch_all() { }; // type of an exception in C++ - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_type = context.ptr_type(AddressSpace::default()); let i32_type = context.i32_type(); let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -351,19 +304,9 @@ fn landing_pad_filter() { }; // type of an exception in C++ - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_type = context.ptr_type(AddressSpace::default()); let i32_type = context.i32_type(); let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); @@ -409,19 +352,9 @@ fn test_null_checked_ptr_ops() { // } let i8_type = context.i8_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_type = context.ptr_type(AddressSpace::default()); let i64_type = context.i64_type(); let fn_type = i8_type.fn_type(&[i8_ptr_type.into()], false); @@ -454,26 +387,9 @@ fn test_null_checked_ptr_ops() { let new_ptr = builder .build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr") .unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let index1 = builder.build_load(new_ptr, "deref").unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref").unwrap(); builder.build_return(Some(&index1)).unwrap(); @@ -513,26 +429,9 @@ fn test_null_checked_ptr_ops() { let new_ptr = builder .build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr") .unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let index1 = builder.build_load(new_ptr, "deref").unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref").unwrap(); builder.build_return(Some(&index1)).unwrap(); @@ -1170,19 +1069,9 @@ fn test_vector_pointer_ops() { let context = Context::create(); let module = context.create_module("test"); let int32_vec_type = context.i32_type().vec_type(4); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_vec_type = context.i8_type().ptr_type(AddressSpace::default()).vec_type(4); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_vec_type = context.ptr_type(AddressSpace::default()).vec_type(4); let bool_vec_type = context.bool_type().vec_type(4); @@ -1207,19 +1096,9 @@ fn test_scalable_vector_pointer_ops() { let context = Context::create(); let module = context.create_module("test"); let int32_vec_type = context.i32_type().scalable_vec_type(4); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_vec_type = context.i8_type().ptr_type(AddressSpace::default()).scalable_vec_type(4); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_vec_type = context.ptr_type(AddressSpace::default()).scalable_vec_type(4); let bool_vec_type = context.bool_type().scalable_vec_type(4); @@ -1255,29 +1134,12 @@ fn test_insert_value() { builder.position_at_end(entry); let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let array = builder .build_load(array_alloca, "array_load") .unwrap() .into_array_value(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let array = builder .build_load(array_type, array_alloca, "array_load") .unwrap() @@ -1314,29 +1176,12 @@ fn test_insert_value() { .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); let struct_alloca = builder.build_alloca(struct_type, "struct_alloca").unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let struct_value = builder .build_load(struct_alloca, "struct_load") .unwrap() .into_struct_value(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let struct_value = builder .build_load(struct_type, struct_alloca, "struct_load") .unwrap() @@ -1519,19 +1364,9 @@ fn run_memcpy_on<'ctx>( let i32_type = context.i32_type(); let i64_type = context.i64_type(); let array_len = 4; - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let fn_type = i32_type.ptr_type(AddressSpace::default()).fn_type(&[], false); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let fn_type = context.ptr_type(AddressSpace::default()).fn_type(&[], false); let fn_value = module.add_function("test_fn", fn_type, None); let builder = context.create_builder(); @@ -1546,26 +1381,9 @@ fn run_memcpy_on<'ctx>( // Initialize the array with the values [1, 2, 3, 4] for index in 0..4 { let index_val = i32_type.const_int(index, false); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let elem_ptr = unsafe { builder .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") @@ -1581,26 +1399,9 @@ fn run_memcpy_on<'ctx>( let bytes_to_copy = elems_to_copy * std::mem::size_of::(); let size_val = i64_type.const_int(bytes_to_copy as u64, false); let index_val = i32_type.const_int(2, false); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let dest_ptr = unsafe { builder .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") @@ -1651,19 +1452,9 @@ fn run_memmove_on<'ctx>( let i32_type = context.i32_type(); let i64_type = context.i64_type(); let array_len = 4; - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let fn_type = i32_type.ptr_type(AddressSpace::default()).fn_type(&[], false); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let fn_type = context.ptr_type(AddressSpace::default()).fn_type(&[], false); let fn_value = module.add_function("test_fn", fn_type, None); let builder = context.create_builder(); @@ -1678,26 +1469,9 @@ fn run_memmove_on<'ctx>( // Initialize the array with the values [1, 2, 3, 4] for index in 0..4 { let index_val = i32_type.const_int(index, false); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let elem_ptr = unsafe { builder .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") @@ -1713,26 +1487,9 @@ fn run_memmove_on<'ctx>( let bytes_to_copy = elems_to_copy * std::mem::size_of::(); let size_val = i64_type.const_int(bytes_to_copy as u64, false); let index_val = i32_type.const_int(2, false); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let dest_ptr = unsafe { builder .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") @@ -1784,19 +1541,9 @@ fn run_memset_on<'ctx>( let i32_type = context.i32_type(); let i64_type = context.i64_type(); let array_len = 4; - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let fn_type = i32_type.ptr_type(AddressSpace::default()).fn_type(&[], false); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let fn_type = context.ptr_type(AddressSpace::default()).fn_type(&[], false); let fn_value = module.add_function("test_fn", fn_type, None); let builder = context.create_builder(); @@ -1817,26 +1564,9 @@ fn run_memset_on<'ctx>( // Memset the second half of the array as -1 let val = i8_type.const_all_ones(); let index = i32_type.const_int(2, false); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let part_2 = unsafe { builder.build_in_bounds_gep(array_ptr, &[index], "index") }.unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let part_2 = unsafe { builder .build_in_bounds_gep(element_type, array_ptr, &[index], "index") @@ -1887,33 +1617,13 @@ fn test_bit_cast() { let i32_type = context.i32_type(); let f64_type = context.f64_type(); let i64_type = context.i64_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_type = context.ptr_type(AddressSpace::default()); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i64_ptr_type = i64_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i64_ptr_type = context.ptr_type(AddressSpace::default()); let i32_vec_type = i32_type.vec_type(2); #[cfg(any( @@ -2026,37 +1736,15 @@ fn test_atomicrmw() { let i31_type = context.custom_width_int_type(31); let i4_type = context.custom_width_int_type(4); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_value = i32_type.ptr_type(AddressSpace::default()).get_undef(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_value = context.ptr_type(AddressSpace::default()).get_undef(); let zero_value = i32_type.const_zero(); let result = builder.build_atomicrmw(AtomicRMWBinOp::Add, ptr_value, zero_value, AtomicOrdering::Unordered); assert!(result.is_ok()); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] { let i64_type = context.i64_type(); let ptr_value = i64_type.ptr_type(AddressSpace::default()).get_undef(); @@ -2065,37 +1753,17 @@ fn test_atomicrmw() { assert!(result.is_err()); } - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_value = i31_type.ptr_type(AddressSpace::default()).get_undef(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_value = context.ptr_type(AddressSpace::default()).get_undef(); let zero_value = i31_type.const_zero(); let result = builder.build_atomicrmw(AtomicRMWBinOp::Add, ptr_value, zero_value, AtomicOrdering::Unordered); assert!(result.is_err()); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_value = i4_type.ptr_type(AddressSpace::default()).get_undef(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_value = context.ptr_type(AddressSpace::default()).get_undef(); let zero_value = i4_type.const_zero(); let result = builder.build_atomicrmw(AtomicRMWBinOp::Add, ptr_value, zero_value, AtomicOrdering::Unordered); @@ -2116,33 +1784,13 @@ fn test_cmpxchg() { let i32_type = context.i32_type(); let i64_type = context.i64_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_type = context.ptr_type(AddressSpace::default()); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_ptr_type = i32_ptr_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_ptr_type = context.ptr_type(AddressSpace::default()); let ptr_value = i32_ptr_type.get_undef(); @@ -2217,19 +1865,7 @@ fn test_cmpxchg() { ); assert!(result.is_err()); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] { let ptr_value = i32_ptr_ptr_type.get_undef(); let zero_value = i32_type.const_zero(); @@ -2280,19 +1916,7 @@ fn test_cmpxchg() { ); assert!(result.is_ok()); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] { let ptr_value = i32_ptr_type.get_undef(); let zero_value = i32_ptr_type.const_zero(); @@ -2315,35 +1939,15 @@ fn test_safe_struct_gep() { let module = context.create_module("struct_gep"); let void_type = context.void_type(); let i32_ty = context.i32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_ty = context.ptr_type(AddressSpace::default()); let field_types = &[i32_ty.into(), i32_ty.into()]; let struct_ty = context.struct_type(field_types, false); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let struct_ptr_ty = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false); let fn_value = module.add_function("", fn_type, None); @@ -2354,19 +1958,7 @@ fn test_safe_struct_gep() { let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value(); let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] { assert!(builder.build_struct_gep(i32_ptr, 0, "struct_gep").is_err()); assert!(builder.build_struct_gep(i32_ptr, 10, "struct_gep").is_err()); @@ -2374,12 +1966,7 @@ fn test_safe_struct_gep() { assert!(builder.build_struct_gep(struct_ptr, 1, "struct_gep").is_ok()); assert!(builder.build_struct_gep(struct_ptr, 2, "struct_gep").is_err()); } - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] { assert!(builder.build_struct_gep(i32_ty, i32_ptr, 0, "struct_gep").is_err()); assert!(builder.build_struct_gep(i32_ty, i32_ptr, 10, "struct_gep").is_err()); diff --git a/tests/all/test_context.rs b/tests/all/test_context.rs index 003eedf1439..98038642646 100644 --- a/tests/all/test_context.rs +++ b/tests/all/test_context.rs @@ -53,19 +53,9 @@ fn test_values_get_context() { let i8_type = context.i8_type(); let f32_type = context.f32_type(); let f32_vec_type = f32_type.vec_type(3); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let f32_array_type = f32_type.array_type(2); let fn_type = f32_type.fn_type(&[], false); diff --git a/tests/all/test_execution_engine.rs b/tests/all/test_execution_engine.rs index d19077afa29..7f4c880f271 100644 --- a/tests/all/test_execution_engine.rs +++ b/tests/all/test_execution_engine.rs @@ -59,22 +59,12 @@ fn test_jit_execution_engine() { let module = context.create_module("main_module"); let builder = context.create_builder(); let i32_type = context.i32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_ptr_type = context .i8_type() .ptr_type(AddressSpace::default()) .ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_ptr_type = context.ptr_type(AddressSpace::default()); let one_i32 = i32_type.const_int(1, false); let three_i32 = i32_type.const_int(3, false); diff --git a/tests/all/test_instruction_conversion.rs b/tests/all/test_instruction_conversion.rs index e129e711af9..371319698ad 100644 --- a/tests/all/test_instruction_conversion.rs +++ b/tests/all/test_instruction_conversion.rs @@ -110,19 +110,9 @@ fn test_conversion_to_pointer_value() { builder.position_at_end(basic_block); // Create a PointerType instruction - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i64_ptr_type = context.i64_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i64_ptr_type = context.ptr_type(AddressSpace::default()); let alloca_instr = builder .build_alloca(i64_ptr_type, "alloca") diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 04d9a1c6440..f280a0cf325 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -1,5 +1,7 @@ use inkwell::context::Context; -use inkwell::types::{AnyType, AnyTypeEnum, BasicType}; +#[cfg(not(feature = "typed-pointers"))] +use inkwell::types::AnyType; +use inkwell::types::{AnyTypeEnum, BasicType}; use inkwell::values::{BasicValue, CallSiteValue, InstructionOpcode::*}; use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; @@ -11,19 +13,9 @@ fn test_operands() { let builder = context.create_builder(); let void_type = context.void_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false); @@ -87,19 +79,7 @@ fn test_operands() { assert!(free_instruction.set_operand(0, arg1)); // Module is no longer valid because free takes an i8* not f32* - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] assert!(module.verify().is_err()); assert!(free_instruction.set_operand(0, free_operand0)); @@ -267,19 +247,9 @@ fn test_instructions() { let void_type = context.void_type(); let i64_type = context.i64_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false); @@ -311,12 +281,7 @@ fn test_instructions() { .build_conditional_branch(i64_type.const_zero(), basic_block, basic_block) .unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] { let gep_instr = unsafe { builder.build_gep(i64_type, alloca_val, &vec![], "gep").unwrap() }; assert_eq!( @@ -391,19 +356,9 @@ fn test_volatile_atomicrmw_cmpxchg() { let void_type = context.void_type(); let i32_type = context.i32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_type.into()], false); @@ -458,19 +413,9 @@ fn test_mem_instructions() { let void_type = context.void_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false); @@ -536,19 +481,9 @@ fn test_mem_instructions() { let void_type = context.void_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false); @@ -566,26 +501,9 @@ fn test_mem_instructions() { let f32_val = f32_type.const_float(std::f64::consts::PI); let store_instruction = builder.build_store(arg1, f32_val).unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let load = builder.build_load(arg1, "").unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let load = builder.build_load(f32_type, arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); @@ -633,19 +551,9 @@ fn test_atomic_ordering_mem_instructions() { let void_type = context.void_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let f32_ptr_type = f32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let f32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false); @@ -663,26 +571,9 @@ fn test_atomic_ordering_mem_instructions() { let f32_val = f32_type.const_float(std::f64::consts::PI); let store_instruction = builder.build_store(arg1, f32_val).unwrap(); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] let load = builder.build_load(arg1, "").unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let load = builder.build_load(f32_type, arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); @@ -726,19 +617,9 @@ fn test_metadata_kinds() { let i8_type = context.i8_type(); let f32_type = context.f32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_type = i8_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let struct_type = context.struct_type(&[i8_type.into(), f32_type.into()], false); let vector_type = i8_type.vec_type(2); @@ -773,19 +654,9 @@ fn test_find_instruction_with_name() { let void_type = context.void_type(); let i32_type = context.i32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false); diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index f7832a488c8..8872e7c91d5 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -185,12 +185,7 @@ fn sized_types(global_ctx: &Context) { let f80_type = global_ctx.x86_f80_type(); let f128_type = global_ctx.f128_type(); let ppc_f128_type = global_ctx.ppc_f128_type(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = global_ctx.ptr_type(AddressSpace::default()); let struct_type = global_ctx.struct_type(&[i8_type.into(), f128_type.into()], false); let struct_type2 = global_ctx.struct_type(&[], false); @@ -216,12 +211,7 @@ fn sized_types(global_ctx: &Context) { assert!(f80_type.is_sized()); assert!(f128_type.is_sized()); assert!(ppc_f128_type.is_sized()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] assert!(ptr_type.is_sized()); assert!(struct_type.is_sized()); assert!(struct_type2.is_sized()); @@ -232,12 +222,7 @@ fn sized_types(global_ctx: &Context) { assert!(!fn_type3.is_sized()); assert!(!fn_type4.is_sized()); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] { assert!(bool_type.ptr_type(AddressSpace::default()).is_sized()); assert!(i8_type.ptr_type(AddressSpace::default()).is_sized()); @@ -269,12 +254,7 @@ fn sized_types(global_ctx: &Context) { assert!(f80_type.array_type(42).is_sized()); assert!(f128_type.array_type(42).is_sized()); assert!(ppc_f128_type.array_type(42).is_sized()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] assert!(ptr_type.array_type(42).is_sized()); assert!(struct_type.array_type(0).is_sized()); assert!(struct_type2.array_type(0).is_sized()); @@ -293,12 +273,7 @@ fn sized_types(global_ctx: &Context) { assert!(f80_type.vec_type(42).is_sized()); assert!(f128_type.vec_type(42).is_sized()); assert!(ppc_f128_type.vec_type(42).is_sized()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] assert!(ptr_type.vec_type(42).is_sized()); #[cfg(any( @@ -323,12 +298,7 @@ fn sized_types(global_ctx: &Context) { assert!(f80_type.scalable_vec_type(42).is_sized()); assert!(f128_type.scalable_vec_type(42).is_sized()); assert!(ppc_f128_type.scalable_vec_type(42).is_sized()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] assert!(ptr_type.scalable_vec_type(42).is_sized()); } @@ -337,12 +307,7 @@ fn sized_types(global_ctx: &Context) { assert!(!opaque_struct_type.is_sized()); assert!(!opaque_struct_type.array_type(0).is_sized()); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] { let opaque_struct_ptr_type = opaque_struct_type.ptr_type(AddressSpace::default()); assert!(opaque_struct_ptr_type.is_sized()); @@ -365,19 +330,9 @@ fn test_const_zero() { let f128_type = context.f128_type(); let ppc_f128_type = context.ppc_f128_type(); let struct_type = context.struct_type(&[i8_type.into(), f128_type.into()], false); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_type = f64_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let vec_type = f64_type.vec_type(42); #[cfg(any( @@ -507,12 +462,7 @@ fn test_const_zero() { ); // handle opaque pointers - let ptr_type = if cfg!(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )) { + let ptr_type = if cfg!(not(feature = "typed-pointers")) { "ptr null" } else { "double* null" @@ -571,36 +521,14 @@ fn test_type_copies() { #[test] fn test_ptr_type() { let context = Context::create(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_type = context.i8_type().ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); assert_eq!(ptr_type.get_address_space(), AddressSpace::default()); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] assert_eq!(ptr_type.get_element_type().into_int_type(), context.i8_type()); // Fn ptr: @@ -609,19 +537,7 @@ fn test_ptr_type() { #[allow(deprecated)] let fn_ptr_type = fn_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] assert_eq!(fn_ptr_type.get_element_type().into_function_type(), fn_type); assert_eq!(fn_ptr_type.get_context(), context); @@ -640,19 +556,9 @@ fn test_basic_type_enum() { &context.f64_type(), // derived types &int.array_type(0), - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] &int.ptr_type(addr), - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] &context.ptr_type(addr), &context.struct_type(&[int.as_basic_type_enum()], false), &int.vec_type(1), @@ -668,12 +574,7 @@ fn test_basic_type_enum() { &int.scalable_vec_type(1), ]; for basic_type in types { - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] assert_eq!( basic_type.as_basic_type_enum().ptr_type(addr), basic_type.ptr_type(addr) @@ -709,19 +610,9 @@ fn test_ptr_address_space() { for index in spaces { let address_space = AddressSpace::try_from(index).unwrap(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr = context.i32_type().ptr_type(address_space); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr = context.ptr_type(address_space); assert_eq!(ptr.get_address_space(), address_space); } @@ -736,8 +627,11 @@ fn test_ptr_is_opaque() { let context = Context::create(); let i32_ptr_type = context.i32_type().ptr_type(AddressSpace::default()); - assert!(i32_ptr_type.is_opaque()); + assert_eq!(!i32_ptr_type.is_opaque(), cfg!(feature = "typed-pointers")); - let ptr_type = context.ptr_type(AddressSpace::default()); - assert!(ptr_type.is_opaque()); + #[cfg(not(feature = "typed-pointers"))] + { + let ptr_type = context.ptr_type(AddressSpace::default()); + assert!(ptr_type.is_opaque()); + } } diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index 4a971201342..cb2ac076f49 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -208,12 +208,7 @@ fn test_set_get_name() { let f32_type = context.f32_type(); let f64_type = context.f64_type(); let f128_type = context.f128_type(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let array_type = f64_type.array_type(42); let ppc_f128_type = context.ppc_f128_type(); @@ -228,19 +223,9 @@ fn test_set_get_name() { let f32_val = f32_type.const_float(0.0); let f64_val = f64_type.const_float(0.0); let f128_val = f128_type.const_float(0.0); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_val = ptr_type.const_null(); let array_val = f64_type.const_array(&[f64_val]); let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); @@ -337,19 +322,9 @@ fn test_set_get_name() { assert_eq!(ppc_f128_val.get_name().to_str(), Ok("")); let void_type = context.void_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_type = bool_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let struct_type = context.struct_type(&[bool_type.into()], false); let vec_type = bool_type.vec_type(1); @@ -481,12 +456,7 @@ fn test_undef() { let f32_type = context.f32_type(); let f64_type = context.f64_type(); let f128_type = context.f128_type(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let array_type = f64_type.array_type(42); let ppc_f128_type = context.ppc_f128_type(); @@ -503,19 +473,9 @@ fn test_undef() { let f32_val = f32_type.const_float(0.0); let f64_val = f64_type.const_float(0.0); let f128_val = f128_type.const_float(0.0); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_val = ptr_type.const_null(); let array_val = f64_type.const_array(&[f64_val]); let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); @@ -568,19 +528,9 @@ fn test_undef() { let f32_undef = f32_type.get_undef(); let f64_undef = f64_type.get_undef(); let f128_undef = f128_type.get_undef(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_undef = bool_type.ptr_type(AddressSpace::default()).get_undef(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_undef = ptr_type.get_undef(); let array_undef = array_type.get_undef(); let struct_undef = context.struct_type(&[bool_type.into()], false).get_undef(); @@ -638,12 +588,7 @@ fn test_poison() { let f32_type = context.f32_type(); let f64_type = context.f64_type(); let f128_type = context.f128_type(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_type = context.ptr_type(AddressSpace::default()); let array_type = f64_type.array_type(42); #[cfg(any( @@ -670,19 +615,9 @@ fn test_poison() { let f32_val = f32_type.const_float(0.0); let f64_val = f64_type.const_float(0.0); let f128_val = f128_type.const_float(0.0); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_val = ptr_type.const_null(); let array_val = f64_type.const_array(&[f64_val]); let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); @@ -735,19 +670,9 @@ fn test_poison() { let f32_poison = f32_type.get_poison(); let f64_poison = f64_type.get_poison(); let f128_poison = f128_type.get_poison(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let ptr_poison = bool_type.ptr_type(AddressSpace::default()).get_poison(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let ptr_poison = ptr_type.get_poison(); let array_poison = array_type.get_poison(); let struct_poison = context.struct_type(&[bool_type.into()], false).get_poison(); @@ -1448,12 +1373,7 @@ fn test_allocations() { builder.position_at_end(entry_block); // handle opaque pointers - let ptr_type = if cfg!(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )) { + let ptr_type = if cfg!(not(feature = "typed-pointers")) { "ptr" } else { "i32*" @@ -1739,19 +1659,9 @@ fn test_non_fn_ptr_called() { let builder = context.create_builder(); let module = context.create_module("my_mod"); let i8_type = context.i8_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i8_ptr_type = i8_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i8_ptr_type = context.ptr_type(AddressSpace::default()); let fn_type = i8_type.fn_type(&[i8_ptr_type.into()], false); let fn_value = module.add_function("my_func", fn_type, None); @@ -1854,19 +1764,9 @@ fn test_aggregate_returns() { let builder = context.create_builder(); let module = context.create_module("my_mod"); let i32_type = context.i32_type(); - #[cfg(not(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - )))] + #[cfg(feature = "typed-pointers")] let i32_ptr_type = i32_type.ptr_type(AddressSpace::default()); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] let i32_ptr_type = context.ptr_type(AddressSpace::default()); let i32_three = i32_type.const_int(3, false); let i32_seven = i32_type.const_int(7, false); @@ -1878,26 +1778,9 @@ fn test_aggregate_returns() { let ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value(); builder.position_at_end(bb); - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0", - feature = "llvm11-0", - feature = "llvm12-0", - feature = "llvm13-0", - feature = "llvm14-0" - ))] + #[cfg(feature = "typed-pointers")] builder.build_ptr_diff(ptr_param1, ptr_param2, "diff").unwrap(); - #[cfg(any( - feature = "llvm15-0", - feature = "llvm16-0", - feature = "llvm17-0", - feature = "llvm18-0" - ))] + #[cfg(not(feature = "typed-pointers"))] builder .build_ptr_diff(i32_ptr_type, ptr_param1, ptr_param2, "diff") .unwrap(); From 9f64611f4bf0151370093ac40361fadc08fb2c21 Mon Sep 17 00:00:00 2001 From: Lach Date: Mon, 10 Mar 2025 04:13:21 +0100 Subject: [PATCH 08/26] fix: proper string constant handling (#577) * fix: proper string constant handling Fixes: https://github.com/TheDan64/inkwell/issues/510 * fix: test for as_const_string includes unexpected nul termination --------- Co-authored-by: Dan Kolsoi --- src/values/array_value.rs | 28 ++++++++++++++++++++++++++++ tests/all/test_values.rs | 18 ++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/values/array_value.rs b/src/values/array_value.rs index c6d7c44d6d4..47836f6221c 100644 --- a/src/values/array_value.rs +++ b/src/values/array_value.rs @@ -129,6 +129,33 @@ impl<'ctx> ArrayValue<'ctx> { unsafe { LLVMIsConstantString(self.as_value_ref()) == 1 } } + /// Obtain the string from the ArrayValue + /// if the value points to a constant string. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// use std::ffi::CStr; + /// + /// let context = Context::create(); + /// let string = context.const_string(b"hello!", false); + /// + /// let result = b"hello!".as_slice(); + /// assert_eq!(string.as_const_string(), Some(result)); + /// ``` + // SubTypes: Impl only for ArrayValue> + pub fn as_const_string(&self) -> Option<&[u8]> { + let mut len = 0; + let ptr = unsafe { LLVMGetAsString(self.as_value_ref(), &mut len) }; + + if ptr.is_null() { + None + } else { + unsafe { Some(std::slice::from_raw_parts(ptr.cast(), len)) } + } + } + /// Obtain the string from the ArrayValue /// if the value points to a constant string. /// @@ -145,6 +172,7 @@ impl<'ctx> ArrayValue<'ctx> { /// assert_eq!(string.get_string_constant(), Some(result)); /// ``` // SubTypes: Impl only for ArrayValue> + #[deprecated = "llvm strings can contain internal NULs, and this function truncates such values, use as_const_string instead"] pub fn get_string_constant(&self) -> Option<&CStr> { let mut len = 0; let ptr = unsafe { LLVMGetAsString(self.as_value_ref(), &mut len) }; diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index cb2ac076f49..fbc6fe24d27 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -1430,6 +1430,7 @@ fn test_string_values() { let i8_type = context.i8_type(); let string = context.const_string(b"my_string", false); let string_null = context.const_string(b"my_string", true); + let string_internal_nul = context.const_string(b"my\0string", false); assert!(string.is_const()); assert!(string_null.is_const()); @@ -1444,27 +1445,32 @@ fn test_string_values() { assert_eq!(string.get_type().get_element_type().into_int_type(), i8_type); assert_eq!(string_null.get_type().get_element_type().into_int_type(), i8_type); - let string_const = string.get_string_constant(); - let string_null_const = string_null.get_string_constant(); + let string_const = string.as_const_string(); + let string_null_const = string_null.as_const_string(); + let string_internal_nul_const = string_internal_nul.as_const_string(); assert!(string_const.is_some()); assert!(string_null_const.is_some()); - assert_eq!(string_const.unwrap().to_str(), Ok("my_string")); - assert_eq!(string_null_const.unwrap().to_str(), Ok("my_string")); + assert_eq!(string_const.unwrap(), b"my_string"); + assert_eq!(string_null_const.unwrap(), b"my_string\0"); + assert_eq!(string_internal_nul_const.unwrap(), b"my\0string"); let i8_val = i8_type.const_int(33, false); let i8_val2 = i8_type.const_int(43, false); let non_string_vec_i8 = i8_type.const_array(&[i8_val, i8_val2]); - let non_string_vec_i8_const = non_string_vec_i8.get_string_constant(); + let non_string_vec_i8_const = non_string_vec_i8.as_const_string(); // TODOC: Will still interpret vec as string even if not generated with const_string: assert!(non_string_vec_i8_const.is_some()); - assert_eq!(non_string_vec_i8_const.unwrap().to_str(), Ok("!+")); + assert_eq!(non_string_vec_i8_const.unwrap(), b"!+"); let i32_type = context.i32_type(); let i32_val = i32_type.const_int(33, false); let i32_val2 = i32_type.const_int(43, false); let non_string_vec_i32 = i8_type.const_array(&[i32_val, i32_val2, i32_val2]); + + // This test expects silent truncation + #[allow(deprecated)] let non_string_vec_i32_const = non_string_vec_i32.get_string_constant(); // TODOC: Will still interpret vec with non i8 but in unexpected ways: From e1a5c2f8ed0ddab3a84cb9f92f69bbd57f70db49 Mon Sep 17 00:00:00 2001 From: lazymio Date: Thu, 27 Mar 2025 01:52:10 +0800 Subject: [PATCH 09/26] Fix is_conditional (#583) LLVMIsConditional assume input is Branch and unwraps --- src/values/instruction_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 5007da5abec..f823fc87c92 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -246,7 +246,7 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to terminators /// Returns if a terminator is conditional or not pub fn is_conditional(self) -> bool { - if self.is_terminator() { + if self.get_opcode() == InstructionOpcode::Br { unsafe { LLVMIsConditional(self.as_value_ref()) == 1 } } else { false From 129aa8dbd1c64a814ff4874dbad02f4ec638e104 Mon Sep 17 00:00:00 2001 From: Daniel Kolsoi Date: Sun, 20 Apr 2025 22:39:23 -0400 Subject: [PATCH 10/26] Re-export Either crate. Closes #580 --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index ef3fbb2845c..dcd7e9c14e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ use llvm_sys::LLVMInlineAsmDialect; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::convert::TryFrom; +pub use either::Either; // Thanks to kennytm for coming up with assert_unique_features! // which ensures that the LLVM feature flags are mutually exclusive From 68c1d6b5132ed67730fcaef1ba6a204572d66a9c Mon Sep 17 00:00:00 2001 From: Dan Kolsoi Date: Fri, 25 Apr 2025 02:39:20 -0400 Subject: [PATCH 11/26] Remove support for LLVM4-7 (#587) * Remove support for LLVM4-7 * Updated workflow * Fixed tests * Fixed more tests * Fixed more tests * Cleanup workflow * Attempt to build all on ubuntu 22.04 * Install missing dep * Clippy and warning cleanup * Fixed tests * Add clippy to CI and appease clippy * rm locked flag * Fix more clippy errors * Fix more clippy errors * Fix more clippy errors * Fix more clippy errors * Fix more clippy errors * Fix more clippy errors * Fix more clippy errors * Rename references to llvm 18-0 to 18-1 * Fixed tests --- .github/workflows/test.yml | 24 +- Cargo.toml | 27 +- README.md | 4 +- internal_macros/src/cfg.rs | 19 +- src/attributes.rs | 2 + src/basic_block.rs | 27 +- src/builder.rs | 34 ++- src/context.rs | 83 +----- src/debug_info.rs | 83 +++--- src/execution_engine.rs | 6 +- src/intrinsics.rs | 2 - src/lib.rs | 31 +-- src/module.rs | 52 +--- src/passes.rs | 47 +--- src/support/mod.rs | 2 +- src/targets.rs | 4 - src/types/array_type.rs | 2 +- src/types/enums.rs | 22 +- src/types/float_type.rs | 8 +- src/types/fn_type.rs | 2 +- src/types/int_type.rs | 6 +- src/types/metadata_type.rs | 9 - src/types/ptr_type.rs | 6 +- src/types/scalable_vec_type.rs | 2 +- src/types/struct_type.rs | 2 +- src/types/traits.rs | 2 +- src/types/vec_type.rs | 2 +- src/values/call_site_value.rs | 13 +- src/values/callable_value.rs | 6 +- src/values/enums.rs | 6 +- src/values/fn_value.rs | 14 - src/values/global_value.rs | 40 +-- src/values/instruction_value.rs | 5 +- src/values/metadata_value.rs | 13 +- src/values/mod.rs | 36 +-- src/values/ptr_value.rs | 6 +- tests/all/main.rs | 4 +- tests/all/test_builder.rs | 25 +- tests/all/test_debug_info.rs | 122 ++------- tests/all/test_instruction_values.rs | 18 +- tests/all/test_intrinsics.rs | 4 - tests/all/test_module.rs | 49 ++-- tests/all/test_object_file.rs | 12 - tests/all/test_passes.rs | 43 +-- tests/all/test_targets.rs | 23 +- tests/all/test_types.rs | 17 +- tests/all/test_values.rs | 383 +++++++++++++-------------- 47 files changed, 453 insertions(+), 896 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e08d02c9a8c..607fd542aef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,11 +29,6 @@ jobs: strategy: matrix: llvm-version: - - ["4.0", "4-0"] - - ["5.0", "5-0"] - - ["6.0", "6-0"] - - ["7.0", "7-0"] - - ["7.1", "7-0"] - ["8.0", "8-0"] - ["9.0", "9-0"] - ["10.0", "10-0"] @@ -44,31 +39,24 @@ jobs: - ["15.0", "15-0"] - ["16.0", "16-0"] - ["17.0", "17-0"] - - ["18.1", "18-0"] + - ["18.1", "18-1"] include: - - os: ubuntu-20.04 - # only use ubuntu-22.04 for llvm 16 and llvm 17 - os: ubuntu-22.04 - llvm-version: ["16.0", "16-0"] - - os: ubuntu-22.04 - llvm-version: ["17.0", "17-0"] steps: - name: Checkout Repo uses: actions/checkout@v4 + - name: Install Dependencies + run: sudo apt update && sudo apt install -y libtinfo5 - name: Install LLVM and Clang (LLVM >= 7.1) uses: KyleMayes/install-llvm-action@v2 - if: ${{ matrix.llvm-version[0] > 7 }} - with: - version: ${{ matrix.llvm-version[0] }} - - name: Install LLVM and Clang (LLVM <= 7) - uses: KyleMayes/install-llvm-action@v1 - if: ${{ matrix.llvm-version[0] <= 7 }} with: version: ${{ matrix.llvm-version[0] }} - name: llvm-config run: llvm-config --version --bindir --libdir - name: Install Rust Stable uses: dtolnay/rust-toolchain@stable + - name: cargo clippy + run: cargo clippy --tests --features llvm${{ matrix.llvm-version[1] }} -- -D warnings - name: Build run: cargo build --release --features llvm${{ matrix.llvm-version[1] }} --verbose - name: Run tests @@ -77,7 +65,7 @@ jobs: run: cargo build --example kaleidoscope --features llvm${{ matrix.llvm-version[1] }} --verbose doc: name: Documentation - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: [lint, tests] if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: diff --git a/Cargo.toml b/Cargo.toml index 66b883542df..077c2bd6300 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,14 +13,9 @@ edition = "2021" [features] default = ["target-all"] - typed-pointers = [] # Please update internal_macros::FEATURE_VERSIONS when adding a new LLVM version -llvm4-0 = ["llvm-sys-40", "typed-pointers"] -llvm5-0 = ["llvm-sys-50", "typed-pointers"] -llvm6-0 = ["llvm-sys-60", "typed-pointers"] -llvm7-0 = ["llvm-sys-70", "typed-pointers"] llvm8-0 = ["llvm-sys-80", "typed-pointers"] llvm9-0 = ["llvm-sys-90", "typed-pointers"] llvm10-0 = ["llvm-sys-100", "typed-pointers"] @@ -31,17 +26,13 @@ llvm14-0 = ["llvm-sys-140", "typed-pointers"] llvm15-0 = ["llvm-sys-150"] llvm16-0 = ["llvm-sys-160"] llvm17-0 = ["llvm-sys-170"] -llvm18-0 = ["llvm-sys-180"] +llvm18-1 = ["llvm-sys-181"] # Don't link against LLVM libraries. This is useful if another dependency is # installing LLVM. See llvm-sys for more details. We can't enable a single # `no-llvm-linking` feature across the board of llvm versions, as it'll cause # cargo to try and download and compile them all. See # https://github.com/rust-lang/cargo/issues/3494 -llvm4-0-no-llvm-linking = ["llvm4-0", "llvm-sys-40/no-llvm-linking"] -llvm5-0-no-llvm-linking = ["llvm5-0", "llvm-sys-50/no-llvm-linking"] -llvm6-0-no-llvm-linking = ["llvm6-0", "llvm-sys-60/no-llvm-linking"] -llvm7-0-no-llvm-linking = ["llvm7-0", "llvm-sys-70/no-llvm-linking"] llvm8-0-no-llvm-linking = ["llvm8-0", "llvm-sys-80/no-llvm-linking"] llvm9-0-no-llvm-linking = ["llvm9-0", "llvm-sys-90/no-llvm-linking"] llvm10-0-no-llvm-linking = ["llvm10-0", "llvm-sys-100/no-llvm-linking"] @@ -52,7 +43,7 @@ llvm14-0-no-llvm-linking = ["llvm14-0", "llvm-sys-140/no-llvm-linking"] llvm15-0-no-llvm-linking = ["llvm15-0", "llvm-sys-150/no-llvm-linking"] llvm16-0-no-llvm-linking = ["llvm16-0", "llvm-sys-160/no-llvm-linking"] llvm17-0-no-llvm-linking = ["llvm17-0", "llvm-sys-170/no-llvm-linking"] -llvm18-0-no-llvm-linking = ["llvm18-0", "llvm-sys-180/no-llvm-linking"] +llvm18-1-no-llvm-linking = ["llvm18-1", "llvm-sys-181/no-llvm-linking"] # Linking preference. # If none of these are enabled, it defaults to force static linking. @@ -64,7 +55,7 @@ llvm14-0-force-dynamic = ["llvm14-0", "llvm-sys-140/force-dynamic"] llvm15-0-force-dynamic = ["llvm15-0", "llvm-sys-150/force-dynamic"] llvm16-0-force-dynamic = ["llvm16-0", "llvm-sys-160/force-dynamic"] llvm17-0-force-dynamic = ["llvm17-0", "llvm-sys-170/force-dynamic"] -llvm18-0-force-dynamic = ["llvm18-0", "llvm-sys-180/force-dynamic"] +llvm18-1-force-dynamic = ["llvm18-1", "llvm-sys-181/force-dynamic"] # Prefer dynamic linking against LLVM libraries. See llvm-sys for more details llvm12-0-prefer-dynamic = ["llvm12-0", "llvm-sys-120/prefer-dynamic"] @@ -73,7 +64,7 @@ llvm14-0-prefer-dynamic = ["llvm14-0", "llvm-sys-140/prefer-dynamic"] llvm15-0-prefer-dynamic = ["llvm15-0", "llvm-sys-150/prefer-dynamic"] llvm16-0-prefer-dynamic = ["llvm16-0", "llvm-sys-160/prefer-dynamic"] llvm17-0-prefer-dynamic = ["llvm17-0", "llvm-sys-170/prefer-dynamic"] -llvm18-0-prefer-dynamic = ["llvm18-0", "llvm-sys-180/prefer-dynamic"] +llvm18-1-prefer-dynamic = ["llvm18-1", "llvm-sys-181/prefer-dynamic"] # Force static linking against LLVM libraries. See llvm-sys for more details llvm12-0-force-static = ["llvm12-0", "llvm-sys-120/force-static"] @@ -82,7 +73,7 @@ llvm14-0-force-static = ["llvm14-0", "llvm-sys-140/force-static"] llvm15-0-force-static = ["llvm15-0", "llvm-sys-150/force-static"] llvm16-0-force-static = ["llvm16-0", "llvm-sys-160/force-static"] llvm17-0-force-static = ["llvm17-0", "llvm-sys-170/force-static"] -llvm18-0-force-static = ["llvm18-0", "llvm-sys-180/force-static"] +llvm18-1-force-static = ["llvm18-1", "llvm-sys-181/force-static"] # Prefer static linking against LLVM libraries. See llvm-sys for more details llvm12-0-prefer-static = ["llvm12-0", "llvm-sys-120/prefer-static"] @@ -91,7 +82,7 @@ llvm14-0-prefer-static = ["llvm14-0", "llvm-sys-140/prefer-static"] llvm15-0-prefer-static = ["llvm15-0", "llvm-sys-150/prefer-static"] llvm16-0-prefer-static = ["llvm16-0", "llvm-sys-160/prefer-static"] llvm17-0-prefer-static = ["llvm17-0", "llvm-sys-170/prefer-static"] -llvm18-0-prefer-static = ["llvm18-0", "llvm-sys-180/prefer-static"] +llvm18-1-prefer-static = ["llvm18-1", "llvm-sys-181/prefer-static"] # Don't force linking to libffi on non-windows platforms. Without this feature # inkwell always links to libffi on non-windows platforms. @@ -153,7 +144,7 @@ llvm-sys-140 = { package = "llvm-sys", version = "140.0.2", optional = true } llvm-sys-150 = { package = "llvm-sys", version = "150.0.3", optional = true } llvm-sys-160 = { package = "llvm-sys", version = "160.1.0", optional = true } llvm-sys-170 = { package = "llvm-sys", version = "170.2.0", optional = true } -llvm-sys-180 = { package = "llvm-sys", version = "181.2.0", optional = true } +llvm-sys-181 = { package = "llvm-sys", version = "181.2.0", optional = true } either = "1.5" libc = "0.2" @@ -161,7 +152,9 @@ once_cell = "1.16" thiserror = "1.0.48" static-alloc = { version = "0.2", optional = true } -serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } +serde = { version = "1.0", default-features = false, features = [ + "derive", +], optional = true } [dev-dependencies] regex = "1" diff --git a/README.md b/README.md index 90ba58adb2c..44afd839fd5 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Inkwell aims to help you pen your own programming languages by safely wrapping l ## Requirements * Rust 1.56+ (Stable, Beta, or Nightly) -* One of LLVM 4-18 +* One of LLVM 8-18 ## Usage @@ -22,7 +22,7 @@ You'll need to point your Cargo.toml to use a single LLVM version feature flag c ```toml [dependencies] -inkwell = { version = "0.5.0", features = ["llvm18-0"] } +inkwell = { version = "0.6.0", features = ["llvm18-1"] } ``` Supported versions: diff --git a/internal_macros/src/cfg.rs b/internal_macros/src/cfg.rs index 73e1f1e425a..9d5b09dd632 100644 --- a/internal_macros/src/cfg.rs +++ b/internal_macros/src/cfg.rs @@ -9,8 +9,8 @@ use syn::{Lit, RangeLimits}; // This array should match the LLVM features in the top level Cargo manifest const FEATURE_VERSIONS: &[&str] = &[ - "llvm4-0", "llvm5-0", "llvm6-0", "llvm7-0", "llvm8-0", "llvm9-0", "llvm10-0", "llvm11-0", "llvm12-0", "llvm13-0", - "llvm14-0", "llvm15-0", "llvm16-0", "llvm17-0", "llvm18-0", + "llvm8-0", "llvm9-0", "llvm10-0", "llvm11-0", "llvm12-0", "llvm13-0", "llvm14-0", "llvm15-0", "llvm16-0", + "llvm17-0", "llvm18-1", ]; pub struct VersionRange { @@ -111,11 +111,22 @@ struct Version { span: Span, } +fn default_minor(major: u32) -> u32 { + if major >= 18 { + 1 + } else { + 0 + } +} + impl Parse for Version { fn parse(input: ParseStream) -> Result { let lit = input.parse::()?; let (major, minor) = match &lit { - Lit::Int(int) => (int.base10_parse()?, 0), + Lit::Int(int) => { + let major = int.base10_parse()?; + (major, default_minor(major)) + }, Lit::Float(float) => { let s = float.base10_digits(); let mut parts = s.split('.'); @@ -127,7 +138,7 @@ impl Parse for Version { let minor = if let Some(minor) = parts.next() { minor.parse().map_err(|e| syn::Error::new(float.span(), e))? } else { - 0 + default_minor(major) }; (major, minor) }, diff --git a/src/attributes.rs b/src/attributes.rs index ed85374c489..888dcf93544 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -73,6 +73,8 @@ impl PartialEq for Attribute { } if self.is_type() && other.is_type() { + // Seems to be some clippy bug here, but it's not clear why. + #[allow(clippy::unit_cmp)] return self.get_enum_kind_id() == other.get_enum_kind_id() && self.get_type_value() == other.get_type_value(); } diff --git a/src/basic_block.rs b/src/basic_block.rs index 1e725c0b9ba..f7996d6e341 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -5,7 +5,7 @@ use llvm_sys::core::{ LLVMGetBasicBlockTerminator, LLVMGetFirstInstruction, LLVMGetFirstUse, LLVMGetLastInstruction, LLVMGetNextBasicBlock, LLVMGetPreviousBasicBlock, LLVMGetTypeContext, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, - LLVMRemoveBasicBlockFromParent, LLVMReplaceAllUsesWith, LLVMTypeOf, + LLVMRemoveBasicBlockFromParent, LLVMReplaceAllUsesWith, LLVMSetValueName2, LLVMTypeOf, }; use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef}; @@ -471,24 +471,13 @@ impl<'ctx> BasicBlock<'ctx> { pub fn set_name(&self, name: &str) { let c_string = to_c_str(name); - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))] - { - use llvm_sys::core::LLVMSetValueName; - - unsafe { LLVMSetValueName(LLVMBasicBlockAsValue(self.basic_block), c_string.as_ptr()) }; - } - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - use llvm_sys::core::LLVMSetValueName2; - - unsafe { - LLVMSetValueName2( - LLVMBasicBlockAsValue(self.basic_block), - c_string.as_ptr(), - c_string.to_bytes().len(), - ) - }; - } + unsafe { + LLVMSetValueName2( + LLVMBasicBlockAsValue(self.basic_block), + c_string.as_ptr(), + c_string.to_bytes().len(), + ) + }; } /// Replaces all uses of this basic block with another. diff --git a/src/builder.rs b/src/builder.rs index 0f7c70578d0..dfcd6c50112 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -22,27 +22,27 @@ use llvm_sys::core::{ LLVMSetCleanup, }; #[llvm_versions(..=14)] +#[allow(deprecated)] use llvm_sys::core::{LLVMBuildCall, LLVMBuildInvoke}; #[llvm_versions(15..)] use llvm_sys::core::{LLVMBuildCall2, LLVMBuildInvoke2}; #[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))] -#[cfg_attr(feature = "llvm15-0", allow(deprecated))] +#[allow(deprecated)] use llvm_sys::core::{LLVMBuildGEP, LLVMBuildInBoundsGEP, LLVMBuildLoad, LLVMBuildPtrDiff, LLVMBuildStructGEP}; #[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))] use llvm_sys::core::{LLVMBuildGEP2, LLVMBuildInBoundsGEP2, LLVMBuildLoad2, LLVMBuildPtrDiff2, LLVMBuildStructGEP2}; -#[llvm_versions(8..)] use llvm_sys::core::{LLVMBuildIntCast2, LLVMBuildMemCpy, LLVMBuildMemMove, LLVMBuildMemSet}; - use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef}; use thiserror::Error; use crate::basic_block::BasicBlock; -#[llvm_versions(7..=8)] +#[cfg(feature = "llvm8-0")] use crate::context::AsContextRef; -#[llvm_versions(7..)] use crate::debug_info::DILocation; use crate::support::to_c_str; -use crate::types::{AsTypeRef, BasicType, FloatMathType, FunctionType, IntMathType, PointerMathType, PointerType}; +#[llvm_versions(15..)] +use crate::types::FunctionType; +use crate::types::{AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType, PointerType}; #[llvm_versions(18..)] use crate::values::operand_bundle::OperandBundle; #[llvm_versions(..=14)] @@ -243,6 +243,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let mut args: Vec = args.iter().map(|val| val.as_value_ref()).collect(); + #[allow(deprecated)] let value = unsafe { LLVMBuildCall( self.builder, @@ -613,6 +614,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let mut args: Vec = args.iter().map(|val| val.as_value_ref()).collect(); + #[allow(deprecated)] let value = unsafe { LLVMBuildInvoke( self.builder, @@ -1098,7 +1100,7 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = LLVMBuildGEP( self.builder, ptr.as_value_ref(), @@ -1166,7 +1168,7 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = LLVMBuildInBoundsGEP( self.builder, ptr.as_value_ref(), @@ -1279,7 +1281,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = unsafe { LLVMBuildStructGEP(self.builder, ptr.as_value_ref(), index, c_string.as_ptr()) }; #[cfg(feature = "llvm16-0")] let value = unsafe { @@ -1409,7 +1411,7 @@ impl<'ctx> Builder<'ctx> { } let c_string = to_c_str(name); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = unsafe { LLVMBuildPtrDiff( self.builder, @@ -1586,7 +1588,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; #[cfg(feature = "llvm16-0")] let value = unsafe { @@ -1691,7 +1693,6 @@ impl<'ctx> Builder<'ctx> { /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2. /// /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. - #[llvm_versions(8..)] pub fn build_memcpy( &self, dest: PointerValue<'ctx>, @@ -1739,7 +1740,6 @@ impl<'ctx> Builder<'ctx> { /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2 under 2^64. /// /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. - #[llvm_versions(8..)] pub fn build_memmove( &self, dest: PointerValue<'ctx>, @@ -1787,7 +1787,6 @@ impl<'ctx> Builder<'ctx> { /// Returns an `Err(BuilderError::AlignmentError)` if the source alignment is not a power of 2 under 2^64. /// /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. - #[llvm_versions(8..)] pub fn build_memset( &self, dest: PointerValue<'ctx>, @@ -2348,7 +2347,6 @@ impl<'ctx> Builder<'ctx> { } /// Like `build_int_cast`, but respects the signedness of the type being cast to. - #[llvm_versions(8..)] pub fn build_int_cast_sign_flag>( &self, int: T, @@ -3608,7 +3606,7 @@ impl<'ctx> Builder<'ctx> { } /// Set the debug info source location of the instruction currently pointed at by the builder - #[llvm_versions(7..=8)] + #[cfg(feature = "llvm8-0")] pub fn set_current_debug_location(&self, context: impl AsContextRef<'ctx>, location: DILocation<'ctx>) { use llvm_sys::core::LLVMMetadataAsValue; use llvm_sys::core::LLVMSetCurrentDebugLocation; @@ -3631,7 +3629,6 @@ impl<'ctx> Builder<'ctx> { /// Get the debug info source location of the instruction currently pointed at by the builder, /// if available. - #[llvm_versions(7..)] pub fn get_current_debug_location(&self) -> Option> { use llvm_sys::core::LLVMGetCurrentDebugLocation; use llvm_sys::core::LLVMValueAsMetadata; @@ -3647,7 +3644,7 @@ impl<'ctx> Builder<'ctx> { /// Unset the debug info source location of the instruction currently pointed at by the /// builder. If there isn't any debug info, this is a no-op. - #[llvm_versions(7..=8)] + #[cfg(feature = "llvm8-0")] pub fn unset_current_debug_location(&self) { use llvm_sys::core::LLVMSetCurrentDebugLocation; unsafe { @@ -3667,7 +3664,6 @@ impl<'ctx> Builder<'ctx> { } /// Used by build_memcpy and build_memmove -#[llvm_versions(8..)] fn is_alignment_ok(align: u32) -> bool { // This replicates the assertions LLVM runs. // diff --git a/src/context.rs b/src/context.rs index 0ca9e97955b..e11fc4474fc 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,19 +1,15 @@ //! A `Context` is an opaque owner and manager of core global data. -#[llvm_versions(7..)] use crate::InlineAsmDialect; use libc::c_void; -#[llvm_versions(..=6)] -use llvm_sys::core::LLVMConstInlineAsm; #[cfg(all(any(feature = "llvm15-0", feature = "llvm16-0"), feature = "typed-pointers"))] use llvm_sys::core::LLVMContextSetOpaquePointers; #[llvm_versions(12..)] use llvm_sys::core::LLVMCreateTypeAttribute; -#[llvm_versions(7..)] + use llvm_sys::core::LLVMGetInlineAsm; #[llvm_versions(12..)] use llvm_sys::core::LLVMGetTypeByName2; -#[llvm_versions(6..)] use llvm_sys::core::LLVMMetadataTypeInContext; #[cfg(not(feature = "typed-pointers"))] use llvm_sys::core::LLVMPointerTypeInContext; @@ -43,7 +39,6 @@ use crate::support::{to_c_str, LLVMString}; use crate::targets::TargetData; #[llvm_versions(12..)] use crate::types::AnyTypeEnum; -#[llvm_versions(6..)] use crate::types::MetadataType; #[cfg(not(feature = "typed-pointers"))] use crate::types::PointerType; @@ -124,14 +119,8 @@ impl ContextImpl { mut constraints: String, sideeffects: bool, alignstack: bool, - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] dialect: Option< - InlineAsmDialect, - >, + dialect: Option, #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -140,17 +129,6 @@ impl ContextImpl { )))] can_throw: bool, ) -> PointerValue<'ctx> { - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))] - let value = unsafe { - LLVMConstInlineAsm( - ty.as_type_ref(), - assembly.as_ptr() as *const ::libc::c_char, - constraints.as_ptr() as *const ::libc::c_char, - sideeffects as i32, - alignstack as i32, - ) - }; - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] let value = unsafe { LLVMGetInlineAsm( ty.as_type_ref(), @@ -162,10 +140,6 @@ impl ContextImpl { alignstack as i32, dialect.unwrap_or(InlineAsmDialect::ATT).into(), #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -214,7 +188,6 @@ impl ContextImpl { unsafe { IntType::new(LLVMIntTypeInContext(self.0, bits)) } } - #[llvm_versions(6..)] fn metadata_type<'ctx>(&self) -> MetadataType<'ctx> { unsafe { MetadataType::new(LLVMMetadataTypeInContext(self.0)) } } @@ -574,12 +547,8 @@ impl Context { /// "=r,{rax},{rdi}".to_string(), /// true, /// false, - /// #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] None, + /// None, /// #[cfg(not(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", /// feature = "llvm8-0", /// feature = "llvm9-0", /// feature = "llvm10-0", @@ -591,10 +560,6 @@ impl Context { /// let params = &[context.i64_type().const_int(60, false).into(), context.i64_type().const_int(1, false).into()]; /// /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", /// feature = "llvm8-0", /// feature = "llvm9-0", /// feature = "llvm10-0", @@ -609,7 +574,7 @@ impl Context { /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// /// builder.build_return(None).unwrap(); @@ -622,14 +587,8 @@ impl Context { constraints: String, sideeffects: bool, alignstack: bool, - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] dialect: Option< - InlineAsmDialect, - >, + dialect: Option, #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -644,13 +603,8 @@ impl Context { constraints, sideeffects, alignstack, - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] dialect, #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -818,7 +772,6 @@ impl Context { /// assert_eq!(md_type.get_context(), context); /// ``` #[inline] - #[llvm_versions(6..)] pub fn metadata_type(&self) -> MetadataType { self.context.metadata_type() } @@ -1456,12 +1409,8 @@ impl<'ctx> ContextRef<'ctx> { /// "=r,{rax},{rdi}".to_string(), /// true, /// false, - /// #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] None, + /// None, /// #[cfg(not(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", /// feature = "llvm8-0", /// feature = "llvm9-0", /// feature = "llvm10-0", @@ -1473,10 +1422,6 @@ impl<'ctx> ContextRef<'ctx> { /// let params = &[context.i64_type().const_int(60, false).into(), context.i64_type().const_int(1, false).into()]; /// /// #[cfg(any( - /// feature = "llvm4-0", - /// feature = "llvm5-0", - /// feature = "llvm6-0", - /// feature = "llvm7-0", /// feature = "llvm8-0", /// feature = "llvm9-0", /// feature = "llvm10-0", @@ -1491,7 +1436,7 @@ impl<'ctx> ContextRef<'ctx> { /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// /// builder.build_return(None).unwrap(); @@ -1504,14 +1449,8 @@ impl<'ctx> ContextRef<'ctx> { constraints: String, sideeffects: bool, alignstack: bool, - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] dialect: Option< - InlineAsmDialect, - >, + dialect: Option, #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -1526,13 +1465,8 @@ impl<'ctx> ContextRef<'ctx> { constraints, sideeffects, alignstack, - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] dialect, #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -1700,7 +1634,6 @@ impl<'ctx> ContextRef<'ctx> { /// assert_eq!(md_type.get_context(), context); /// ``` #[inline] - #[llvm_versions(6..)] pub fn metadata_type(&self) -> MetadataType<'ctx> { self.context.metadata_type() } diff --git a/src/debug_info.rs b/src/debug_info.rs index ff0eac6614d..1721e7e56a8 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -108,7 +108,7 @@ use crate::values::{AsValueRef, BasicValueEnum, InstructionValue, MetadataValue, use crate::AddressSpace; use llvm_sys::core::LLVMMetadataAsValue; -#[llvm_versions(8..)] + use llvm_sys::debuginfo::LLVMDIBuilderCreateTypedef; pub use llvm_sys::debuginfo::LLVMDWARFTypeEncoding; use llvm_sys::debuginfo::LLVMDebugMetadataVersion; @@ -127,7 +127,7 @@ use llvm_sys::debuginfo::{ LLVMDIBuilderInsertDeclareBefore, LLVMDILocationGetColumn, LLVMDILocationGetLine, LLVMDILocationGetScope, LLVMDITypeGetAlignInBits, LLVMDITypeGetOffsetInBits, LLVMDITypeGetSizeInBits, }; -#[llvm_versions(8..)] + use llvm_sys::debuginfo::{LLVMDIBuilderCreateConstantValueExpression, LLVMDIBuilderCreateGlobalVariableExpression}; use llvm_sys::prelude::{LLVMDIBuilderRef, LLVMMetadataRef}; use std::convert::TryInto; @@ -157,7 +157,7 @@ pub struct DIScope<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl<'ctx> DIScope<'ctx> { +impl DIScope<'_> { /// Acquires the underlying raw pointer belonging to this `DIScope` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -195,7 +195,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sysroot: &str, #[cfg(any( @@ -206,7 +206,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sdk: &str, ) -> (Self, DICompileUnit<'ctx>) { @@ -245,7 +245,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sysroot, #[cfg(any( @@ -256,7 +256,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sdk, ); @@ -303,7 +303,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sysroot: &str, #[cfg(any( @@ -314,20 +314,12 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sdk: &str, ) -> DICompileUnit<'ctx> { let metadata_ref = unsafe { - #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0", - feature = "llvm10-0" - ))] + #[cfg(any(feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0"))] { LLVMDIBuilderCreateCompileUnit( self.builder, @@ -356,7 +348,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] { LLVMDIBuilderCreateCompileUnit( @@ -511,13 +503,12 @@ impl<'ctx> DebugInfoBuilder<'ctx> { /// Create a primitive basic type. `encoding` is an unsigned int flag (`DW_ATE_*` /// enum) defined by the chosen DWARF standard. - #[llvm_versions(7..)] pub fn create_basic_type( &self, name: &str, size_in_bits: u64, encoding: LLVMDWARFTypeEncoding, - #[cfg(not(feature = "llvm7-0"))] flags: DIFlags, + flags: DIFlags, ) -> Result, &'static str> { if name.is_empty() { // Also, LLVM returns the same type if you ask for the same @@ -531,7 +522,6 @@ impl<'ctx> DebugInfoBuilder<'ctx> { name.len(), size_in_bits, encoding, - #[cfg(not(feature = "llvm7-0"))] flags, ) }; @@ -542,7 +532,6 @@ impl<'ctx> DebugInfoBuilder<'ctx> { } /// Create a typedef (alias) of `ditype` - #[llvm_versions(8..)] pub fn create_typedef( &self, ditype: DIType<'ctx>, @@ -791,7 +780,6 @@ impl<'ctx> DebugInfoBuilder<'ctx> { } } - #[llvm_versions(8..)] pub fn create_global_variable_expression( &self, scope: DIScope<'ctx>, @@ -830,7 +818,6 @@ impl<'ctx> DebugInfoBuilder<'ctx> { } } - #[llvm_versions(8..)] pub fn create_constant_expression(&self, value: i64) -> DIExpression<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateConstantValueExpression(self.builder, value as _) }; @@ -1037,7 +1024,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { } } -impl<'ctx> Drop for DebugInfoBuilder<'ctx> { +impl Drop for DebugInfoBuilder<'_> { fn drop(&mut self) { self.finalize(); unsafe { LLVMDisposeDIBuilder(self.builder) } @@ -1060,7 +1047,7 @@ impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> { } } -impl<'ctx> DIFile<'ctx> { +impl DIFile<'_> { /// Acquires the underlying raw pointer belonging to this `DIFile` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1102,7 +1089,7 @@ pub struct DINamespace<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl<'ctx> DINamespace<'ctx> { +impl DINamespace<'_> { /// Acquires the underlying raw pointer belonging to this `DINamespace` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1134,7 +1121,7 @@ impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> { } } -impl<'ctx> DISubprogram<'ctx> { +impl DISubprogram<'_> { /// Acquires the underlying raw pointer belonging to this `DISubprogram` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1148,7 +1135,7 @@ pub struct DIType<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl<'ctx> DIType<'ctx> { +impl DIType<'_> { pub fn get_size_in_bits(&self) -> u64 { unsafe { LLVMDITypeGetSizeInBits(self.metadata_ref) } } @@ -1192,7 +1179,7 @@ impl<'ctx> DIDerivedType<'ctx> { } } -impl<'ctx> DIDerivedType<'ctx> { +impl DIDerivedType<'_> { pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref } @@ -1289,7 +1276,7 @@ impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> { } } -impl<'ctx> DILexicalBlock<'ctx> { +impl DILexicalBlock<'_> { /// Acquires the underlying raw pointer belonging to this `DILexicalBlock` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1339,7 +1326,7 @@ pub struct DILocalVariable<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl<'ctx> DILocalVariable<'ctx> { +impl DILocalVariable<'_> { /// Acquires the underlying raw pointer belonging to this `DILocalVariable` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1374,7 +1361,7 @@ pub struct DIExpression<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl<'ctx> DIExpression<'ctx> { +impl DIExpression<'_> { /// Acquires the underlying raw pointer belonging to this `DIExpression` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1393,7 +1380,7 @@ mod flags { const PUBLIC: Self; const FWD_DECL: Self; const APPLE_BLOCK: Self; - //#[llvm_versions(7..=9)] + //#[llvm_versions(8..=9)] //const BLOCK_BYREF_STRUCT: Self; const VIRTUAL: Self; const ARTIFICIAL: Self; @@ -1412,24 +1399,22 @@ mod flags { const INTRODUCED_VIRTUAL: Self; const BIT_FIELD: Self; const NO_RETURN: Self; - //#[llvm_versions(7..=8)] + //#[llvm_versions(8..=8)] //const MAIN_SUBPROGRAM: Self; const TYPE_PASS_BY_VALUE: Self; const TYPE_PASS_BY_REFERENCE: Self; - //#[llvm_versions(7)] - //const FIXED_ENUM: Self; - //#[llvm_versions(8..)] + // //const ENUM_CLASS: Self; const THUNK: Self; - //#[llvm_versions(7..=8)] + //#[llvm_versions(8..=8)] //const TRIVIAL: Self; //#[llvm_versions(9..)] //const NON_TRIVIAL: Self; //#[llvm_versions(10)] //const RESERVED_BIT4: Self; - //#[llvm_versions(8..)] + // //const BIGE_NDIAN: Self; - //#[llvm_versions(8..)] + // //const LITTLE_ENDIAN: Self; const INDIRECT_VIRTUAL_BASE: Self; } @@ -1440,7 +1425,7 @@ mod flags { const PUBLIC: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPublic; const FWD_DECL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagFwdDecl; const APPLE_BLOCK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagAppleBlock; - //#[llvm_versions(7..=9)] + //#[llvm_versions(8..=9)] //const BLOCK_BYREF_STRUCT: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBlockByrefStruct; const VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVirtual; const ARTIFICIAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagArtificial; @@ -1459,24 +1444,22 @@ mod flags { const INTRODUCED_VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIntroducedVirtual; const BIT_FIELD: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBitField; const NO_RETURN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagNoReturn; - //#[llvm_versions(7..=8)] + //#[llvm_versions(8..=8)] //const MAIN_SUBPROGRAM: DIFlags = llvm_sys::debuginfo::LLVMDIFlagMainSubprogram; const TYPE_PASS_BY_VALUE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByValue; const TYPE_PASS_BY_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByReference; - //#[llvm_versions(7)] - //const FIXED_ENUM: DIFlags = llvm_sys::debuginfo::LLVMDIFlagFixedEnum; - //#[llvm_versions(8..)] + // //const ENUM_CLASS: DIFlags = llvm_sys::debuginfo::LLVMDIFlagEnumClass; const THUNK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagThunk; - //#[llvm_versions(7..=8)] + //#[llvm_versions(8..=8)] //const TRIVIAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTrivial; //#[llvm_versions(9..)] //const NON_TRIVIAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagNonTrivial; //#[llvm_versions(10)] //const RESERVED_BIT4: DIFlags = llvm_sys::debuginfo::LLVMDIFlagReservedBit4; - //#[llvm_versions(8..)] + // //const BIG_ENDIAN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBigEndian; - //#[llvm_versions(8..)] + // //const LITTLE_ENDIAN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagLittleEndian; const INDIRECT_VIRTUAL_BASE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIndirectVirtualBase; } diff --git a/src/execution_engine.rs b/src/execution_engine.rs index 1f032782795..0de13a79ef3 100644 --- a/src/execution_engine.rs +++ b/src/execution_engine.rs @@ -332,9 +332,9 @@ impl<'ctx> ExecutionEngine<'ctx> { /// It is recommended to use `get_function` instead of this method when intending to call the function /// pointer so that you don't have to do error-prone transmutes yourself. pub fn get_function_address(&self, fn_name: &str) -> Result { - // LLVMGetFunctionAddress segfaults in llvm 5.0 -> 8.0 when fn_name doesn't exist. This is a workaround + // LLVMGetFunctionAddress segfaults in llvm 8.0 when fn_name doesn't exist. This is a workaround // to see if it exists and avoid the segfault when it doesn't - #[cfg(any(feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0"))] + #[cfg(feature = "llvm8-0")] self.get_function_value(fn_name)?; let c_string = to_c_str(fn_name); @@ -487,7 +487,7 @@ pub struct JitFunction<'ctx, F> { inner: F, } -impl<'ctx, F: Copy> JitFunction<'ctx, F> { +impl JitFunction<'_, F> { /// Returns the raw function pointer, consuming self in the process. /// This function is unsafe because the function pointer may dangle /// if the ExecutionEngine it came from is dropped. The caller is diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 93dfdd1abca..0fa4c06398d 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -1,4 +1,3 @@ -#[llvm_versions(9..)] use llvm_sys::core::{LLVMGetIntrinsicDeclaration, LLVMIntrinsicIsOverloaded, LLVMLookupIntrinsicID}; use llvm_sys::prelude::LLVMTypeRef; @@ -14,7 +13,6 @@ pub struct Intrinsic { /// A wrapper around LLVM intrinsic id /// /// To call it you would need to create a declaration inside a module using [`Self::get_declaration()`]. -#[llvm_versions(9..)] impl Intrinsic { /// Create an Intrinsic object from raw LLVM intrinsic id /// diff --git a/src/lib.rs b/src/lib.rs index dcd7e9c14e0..eba3350a0a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,14 +23,13 @@ pub mod attributes; pub mod basic_block; pub mod builder; #[deny(missing_docs)] -#[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] pub mod comdat; #[deny(missing_docs)] pub mod context; pub mod data_layout; -#[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] pub mod debug_info; pub mod execution_engine; +#[cfg(not(feature = "llvm8-0"))] pub mod intrinsics; pub mod memory_buffer; pub mod memory_manager; @@ -59,16 +58,8 @@ pub extern crate llvm_sys_150 as llvm_sys; pub extern crate llvm_sys_160 as llvm_sys; #[cfg(feature = "llvm17-0")] pub extern crate llvm_sys_170 as llvm_sys; -#[cfg(feature = "llvm18-0")] -pub extern crate llvm_sys_180 as llvm_sys; -#[cfg(feature = "llvm4-0")] -pub extern crate llvm_sys_40 as llvm_sys; -#[cfg(feature = "llvm5-0")] -pub extern crate llvm_sys_50 as llvm_sys; -#[cfg(feature = "llvm6-0")] -pub extern crate llvm_sys_60 as llvm_sys; -#[cfg(feature = "llvm7-0")] -pub extern crate llvm_sys_70 as llvm_sys; +#[cfg(feature = "llvm18-1")] +pub extern crate llvm_sys_181 as llvm_sys; #[cfg(feature = "llvm8-0")] pub extern crate llvm_sys_80 as llvm_sys; #[cfg(feature = "llvm9-0")] @@ -80,13 +71,12 @@ use llvm_sys::{ LLVMThreadLocalMode, LLVMVisibility, }; -#[llvm_versions(7..)] use llvm_sys::LLVMInlineAsmDialect; +pub use either::Either; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::convert::TryFrom; -pub use either::Either; // Thanks to kennytm for coming up with assert_unique_features! // which ensures that the LLVM feature flags are mutually exclusive @@ -118,10 +108,6 @@ macro_rules! assert_unique_used_features { } assert_unique_used_features! { - "llvm4-0", - "llvm5-0", - "llvm6-0", - "llvm7-0", "llvm8-0", "llvm9-0", "llvm10-0", @@ -132,15 +118,11 @@ assert_unique_used_features! { "llvm15-0", "llvm16-0", "llvm17-0", - "llvm18-0" + "llvm18-1" } #[cfg(all( any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -153,7 +135,7 @@ assert_unique_used_features! { ))] compile_error!("Opaque pointers are not supported prior to LLVM version 15.0."); -#[cfg(all(any(feature = "llvm17-0", feature = "llvm18-0"), feature = "typed-pointers"))] +#[cfg(all(any(feature = "llvm17-0", feature = "llvm18-1"), feature = "typed-pointers"))] compile_error!("Typed pointers are not supported starting from LLVM version 17.0."); /// Defines the address space in which a global will be inserted. @@ -503,7 +485,6 @@ impl Default for DLLStorageClass { } } -#[llvm_versions(7..)] #[llvm_enum(LLVMInlineAsmDialect)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/src/module.rs b/src/module.rs index 486b4965cff..62c5fbd3713 100644 --- a/src/module.rs +++ b/src/module.rs @@ -4,18 +4,18 @@ use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyModule}; #[allow(deprecated)] use llvm_sys::bit_reader::LLVMParseBitcodeInContext; use llvm_sys::bit_writer::{LLVMWriteBitcodeToFile, LLVMWriteBitcodeToMemoryBuffer}; -#[llvm_versions(..=14)] +#[llvm_versions(..=11)] use llvm_sys::core::LLVMGetTypeByName; - use llvm_sys::core::{ LLVMAddFunction, LLVMAddGlobal, LLVMAddGlobalInAddressSpace, LLVMAddNamedMetadataOperand, LLVMCloneModule, LLVMDisposeMessage, LLVMDisposeModule, LLVMDumpModule, LLVMGetFirstFunction, LLVMGetFirstGlobal, LLVMGetLastFunction, LLVMGetLastGlobal, LLVMGetModuleContext, LLVMGetModuleIdentifier, LLVMGetNamedFunction, LLVMGetNamedGlobal, LLVMGetNamedMetadataNumOperands, LLVMGetNamedMetadataOperands, LLVMGetTarget, - LLVMPrintModuleToFile, LLVMPrintModuleToString, LLVMSetDataLayout, LLVMSetModuleIdentifier, LLVMSetTarget, + LLVMPrintModuleToFile, LLVMPrintModuleToString, LLVMSetDataLayout, LLVMSetModuleIdentifier, + LLVMSetModuleInlineAsm2, LLVMSetTarget, }; -#[llvm_versions(7..)] use llvm_sys::core::{LLVMAddModuleFlag, LLVMGetModuleFlag}; +use llvm_sys::debuginfo::{LLVMGetModuleDebugMetadataVersion, LLVMStripModuleDebugInfo}; #[llvm_versions(13..)] use llvm_sys::error::LLVMGetErrorMessage; use llvm_sys::execution_engine::{ @@ -26,7 +26,7 @@ use llvm_sys::prelude::{LLVMModuleRef, LLVMValueRef}; #[llvm_versions(13..)] use llvm_sys::transforms::pass_builder::LLVMRunPasses; use llvm_sys::LLVMLinkage; -#[llvm_versions(7..)] + use llvm_sys::LLVMModuleFlagBehavior; use std::cell::{Cell, Ref, RefCell}; @@ -38,11 +38,10 @@ use std::path::Path; use std::ptr; use std::rc::Rc; -#[llvm_versions(7..)] use crate::comdat::Comdat; use crate::context::{AsContextRef, Context, ContextRef}; use crate::data_layout::DataLayout; -#[llvm_versions(7..)] + use crate::debug_info::{DICompileUnit, DWARFEmissionKind, DWARFSourceLanguage, DebugInfoBuilder}; use crate::execution_engine::ExecutionEngine; use crate::memory_buffer::MemoryBuffer; @@ -57,7 +56,7 @@ use crate::support::{to_c_str, LLVMString}; use crate::targets::TargetMachine; use crate::targets::{CodeModel, InitializationConfig, Target, TargetTriple}; use crate::types::{AsTypeRef, BasicType, FunctionType, StructType}; -#[llvm_versions(7..)] + use crate::values::BasicValue; use crate::values::{AsValueRef, FunctionValue, GlobalValue, MetadataValue}; use crate::{AddressSpace, OptimizationLevel}; @@ -995,20 +994,7 @@ impl<'ctx> Module<'ctx> { /// Sets the inline assembly for the `Module`. pub fn set_inline_assembly(&self, asm: &str) { - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))] - { - use llvm_sys::core::LLVMSetModuleInlineAsm; - - let c_string = to_c_str(asm); - - unsafe { LLVMSetModuleInlineAsm(self.module.get(), c_string.as_ptr()) } - } - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - use llvm_sys::core::LLVMSetModuleInlineAsm2; - - unsafe { LLVMSetModuleInlineAsm2(self.module.get(), asm.as_ptr() as *const ::libc::c_char, asm.len()) } - } + unsafe { LLVMSetModuleInlineAsm2(self.module.get(), asm.as_ptr() as *const ::libc::c_char, asm.len()) } } // REVIEW: Should module take ownership of metadata? @@ -1378,7 +1364,6 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_name().to_str(), Ok("my_mod")); /// assert_eq!(module.get_source_file_name().to_str(), Ok("my_mod.rs")); /// ``` - #[llvm_versions(7..)] pub fn get_source_file_name(&self) -> &CStr { use llvm_sys::core::LLVMGetSourceFileName; @@ -1405,7 +1390,6 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_name().to_str(), Ok("my_mod")); /// assert_eq!(module.get_source_file_name().to_str(), Ok("my_mod.rs")); /// ``` - #[llvm_versions(7..)] pub fn set_source_file_name(&self, file_name: &str) { use llvm_sys::core::LLVMSetSourceFileName; @@ -1465,7 +1449,6 @@ impl<'ctx> Module<'ctx> { /// Gets the `Comdat` associated with a particular name. If it does not exist, it will be created. /// A new `Comdat` defaults to a kind of `ComdatSelectionKind::Any`. - #[llvm_versions(7..)] pub fn get_or_insert_comdat(&self, name: &str) -> Comdat { use llvm_sys::comdat::LLVMGetOrInsertComdat; @@ -1479,7 +1462,6 @@ impl<'ctx> Module<'ctx> { /// If a `BasicValue` was used to create this flag, it will be wrapped in a `MetadataValue` /// when returned from this function. // SubTypes: Might need to return Option, or MV> - #[llvm_versions(7..)] pub fn get_flag(&self, key: &str) -> Option> { use llvm_sys::core::LLVMMetadataAsValue; @@ -1496,7 +1478,6 @@ impl<'ctx> Module<'ctx> { /// Append a `MetadataValue` as a module wide flag. Note that using the same key twice /// will likely invalidate the module. - #[llvm_versions(7..)] pub fn add_metadata_flag(&self, key: &str, behavior: FlagBehavior, flag: MetadataValue<'ctx>) { let md = flag.as_metadata_ref(); @@ -1514,7 +1495,6 @@ impl<'ctx> Module<'ctx> { /// Append a `BasicValue` as a module wide flag. Note that using the same key twice /// will likely invalidate the module. // REVIEW: What happens if value is not const? - #[llvm_versions(7..)] pub fn add_basic_value_flag>(&self, key: &str, behavior: FlagBehavior, flag: BV) { use llvm_sys::core::LLVMValueAsMetadata; @@ -1532,23 +1512,16 @@ impl<'ctx> Module<'ctx> { } /// Strips and debug info from the module, if it exists. - #[llvm_versions(6..)] pub fn strip_debug_info(&self) -> bool { - use llvm_sys::debuginfo::LLVMStripModuleDebugInfo; - unsafe { LLVMStripModuleDebugInfo(self.module.get()) == 1 } } /// Gets the version of debug metadata contained in this `Module`. - #[llvm_versions(6..)] pub fn get_debug_metadata_version(&self) -> libc::c_uint { - use llvm_sys::debuginfo::LLVMGetModuleDebugMetadataVersion; - unsafe { LLVMGetModuleDebugMetadataVersion(self.module.get()) } } /// Creates a `DebugInfoBuilder` for this `Module`. - #[llvm_versions(7..)] pub fn create_debug_info_builder( &self, allow_unresolved: bool, @@ -1572,7 +1545,7 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sysroot: &str, #[cfg(any( @@ -1583,7 +1556,7 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sdk: &str, ) -> (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>) { @@ -1610,7 +1583,7 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sysroot, #[cfg(any( @@ -1621,7 +1594,7 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] sdk, ) @@ -1690,7 +1663,6 @@ impl Drop for Module<'_> { } } -#[llvm_versions(7..)] #[llvm_enum(LLVMModuleFlagBehavior)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] /// Defines the operational behavior for a module wide flag. This documentation comes directly diff --git a/src/passes.rs b/src/passes.rs index 2ab9fd26746..313624b57ba 100644 --- a/src/passes.rs +++ b/src/passes.rs @@ -15,6 +15,8 @@ use llvm_sys::initialization::{LLVMInitializeInstrumentation, LLVMInitializeObjC use llvm_sys::prelude::LLVMPassManagerRef; #[llvm_versions(..=16)] use llvm_sys::prelude::LLVMPassRegistryRef; +#[llvm_versions(..=15)] +use llvm_sys::transforms::aggressive_instcombine::LLVMAddAggressiveInstCombinerPass; #[llvm_versions(10..=16)] use llvm_sys::transforms::ipo::LLVMAddMergeFunctionsPass; #[llvm_versions(..=15)] @@ -466,26 +468,6 @@ impl PassManager { unsafe { LLVMAddStripSymbolsPass(self.pass_manager) } } - /// This pass combines instructions inside basic blocks to form - /// vector instructions. It iterates over each basic block, - /// attempting to pair compatible instructions, repeating this - /// process until no additional pairs are selected for vectorization. - /// When the outputs of some pair of compatible instructions are - /// used as inputs by some other pair of compatible instructions, - /// those pairs are part of a potential vectorization chain. - /// Instruction pairs are only fused into vector instructions when - /// they are part of a chain longer than some threshold length. - /// Moreover, the pass attempts to find the best possible chain - /// for each pair of compatible instructions. These heuristics - /// are intended to prevent vectorization in cases where it would - /// not yield a performance increase of the resulting code. - #[cfg(feature = "llvm4-0")] - pub fn add_bb_vectorize_pass(&self) { - use llvm_sys::transforms::vectorize::LLVMAddBBVectorizePass; - - unsafe { LLVMAddBBVectorizePass(self.pass_manager) } - } - /// No LLVM documentation is available at this time. #[llvm_versions(..=16)] pub fn add_loop_vectorize_pass(&self) { @@ -806,9 +788,6 @@ impl PassManager { /// switch instruction until it is convenient. #[llvm_versions(..=16)] pub fn add_lower_switch_pass(&self) { - #[llvm_versions(..=6)] - use llvm_sys::transforms::scalar::LLVMAddLowerSwitchPass; - #[llvm_versions(7..=16)] use llvm_sys::transforms::util::LLVMAddLowerSwitchPass; unsafe { LLVMAddLowerSwitchPass(self.pass_manager) } @@ -822,9 +801,6 @@ impl PassManager { /// the standard SSA construction algorithm to construct "pruned" SSA form. #[llvm_versions(..=16)] pub fn add_promote_memory_to_register_pass(&self) { - #[llvm_versions(..=6)] - use llvm_sys::transforms::scalar::LLVMAddPromoteMemoryToRegisterPass; - #[llvm_versions(7..=16)] use llvm_sys::transforms::util::LLVMAddPromoteMemoryToRegisterPass; unsafe { LLVMAddPromoteMemoryToRegisterPass(self.pass_manager) } @@ -1071,45 +1047,40 @@ impl PassManager { unsafe { LLVMAddBasicAliasAnalysisPass(self.pass_manager) } } - #[llvm_versions(7..=15)] + #[llvm_versions(..=15)] pub fn add_aggressive_inst_combiner_pass(&self) { - #[cfg(not(feature = "llvm7-0"))] - use llvm_sys::transforms::aggressive_instcombine::LLVMAddAggressiveInstCombinerPass; - #[cfg(feature = "llvm7-0")] - use llvm_sys::transforms::scalar::LLVMAddAggressiveInstCombinerPass; - unsafe { LLVMAddAggressiveInstCombinerPass(self.pass_manager) } } - #[llvm_versions(7..=16)] + #[llvm_versions(..=16)] pub fn add_loop_unroll_and_jam_pass(&self) { use llvm_sys::transforms::scalar::LLVMAddLoopUnrollAndJamPass; unsafe { LLVMAddLoopUnrollAndJamPass(self.pass_manager) } } - #[llvm_versions(8..15)] + #[llvm_versions(..15)] pub fn add_coroutine_early_pass(&self) { use llvm_sys::transforms::coroutines::LLVMAddCoroEarlyPass; unsafe { LLVMAddCoroEarlyPass(self.pass_manager) } } - #[llvm_versions(8..15)] + #[llvm_versions(..15)] pub fn add_coroutine_split_pass(&self) { use llvm_sys::transforms::coroutines::LLVMAddCoroSplitPass; unsafe { LLVMAddCoroSplitPass(self.pass_manager) } } - #[llvm_versions(8..15)] + #[llvm_versions(..15)] pub fn add_coroutine_elide_pass(&self) { use llvm_sys::transforms::coroutines::LLVMAddCoroElidePass; unsafe { LLVMAddCoroElidePass(self.pass_manager) } } - #[llvm_versions(8..15)] + #[llvm_versions(..15)] pub fn add_coroutine_cleanup_pass(&self) { use llvm_sys::transforms::coroutines::LLVMAddCoroCleanupPass; @@ -1199,7 +1170,7 @@ impl PassRegistry { unsafe { LLVMInitializeTarget(self.pass_registry) } } - #[llvm_versions(7..=15)] + #[llvm_versions(..=15)] pub fn initialize_aggressive_inst_combiner(&self) { use llvm_sys::initialization::LLVMInitializeAggressiveInstCombiner; diff --git a/src/support/mod.rs b/src/support/mod.rs index 0c3941e6a9c..d6ea212f781 100644 --- a/src/support/mod.rs +++ b/src/support/mod.rs @@ -43,7 +43,7 @@ impl LLVMString { /// This method will allocate a c string through LLVM pub(crate) fn create_from_str(string: &str) -> LLVMString { - debug_assert_eq!(string.as_bytes()[string.as_bytes().len() - 1], 0); + debug_assert_eq!(string.as_bytes()[string.len() - 1], 0); unsafe { LLVMString::new(LLVMCreateMessage(string.as_ptr() as *const _)) } } diff --git a/src/targets.rs b/src/targets.rs index 5edc005632a..6b8932456ca 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -784,7 +784,6 @@ impl Target { } #[cfg(feature = "target-webassembly")] - #[llvm_versions(8..)] pub fn initialize_webassembly(config: &InitializationConfig) { use llvm_sys::target::{ LLVMInitializeWebAssemblyAsmParser, LLVMInitializeWebAssemblyAsmPrinter, @@ -1094,7 +1093,6 @@ impl TargetMachine { unsafe { TargetTriple::new(llvm_string) } } - #[llvm_versions(7..)] pub fn normalize_triple(triple: &TargetTriple) -> TargetTriple { use llvm_sys::target_machine::LLVMNormalizeTargetTriple; @@ -1108,7 +1106,6 @@ impl TargetMachine { /// # Example Output /// /// `x86_64-pc-linux-gnu` - #[llvm_versions(7..)] pub fn get_host_cpu_name() -> LLVMString { use llvm_sys::target_machine::LLVMGetHostCPUName; @@ -1120,7 +1117,6 @@ impl TargetMachine { /// # Example Output /// /// `+sse2,+cx16,+sahf,-tbm` - #[llvm_versions(7..)] pub fn get_host_cpu_features() -> LLVMString { use llvm_sys::target_machine::LLVMGetHostCPUFeatures; diff --git a/src/types/array_type.rs b/src/types/array_type.rs index c46b6986176..b6675b10c20 100644 --- a/src/types/array_type.rs +++ b/src/types/array_type.rs @@ -85,7 +85,7 @@ impl<'ctx> ArrayType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/enums.rs b/src/types/enums.rs index 6d09c38bb30..958fc30804c 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -120,7 +120,6 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { /// /// Before LLVM 6, [`BasicMetadataTypeEnum::MetadataType`] variants cannot be created /// with this function. Attempting to do results in undefined behavior. - #[llvm_versions(6..)] pub unsafe fn new(type_: LLVMTypeRef) -> Self { match LLVMGetTypeKind(type_) { LLVMTypeKind::LLVMMetadataTypeKind => Self::MetadataType(MetadataType::new(type_)), @@ -128,11 +127,6 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { } } - #[llvm_versions(..6)] - pub unsafe fn new(type_: LLVMTypeRef) -> Self { - BasicTypeEnum::new(type_).into() - } - pub fn into_array_type(self) -> ArrayType<'ctx> { if let BasicMetadataTypeEnum::ArrayType(t) = self { t @@ -266,7 +260,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)), LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"), @@ -284,7 +278,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => AnyTypeEnum::ScalableVectorType(ScalableVectorType::new(type_)), // FIXME: should inkwell support metadata as AnyType? @@ -297,11 +291,11 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMX86_AMXTypeKind => panic!("FIXME: Unsupported type: AMX"), LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"), - #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] LLVMTypeKind::LLVMTargetExtTypeKind => panic!("FIXME: Unsupported type: TargetExt"), } } @@ -466,7 +460,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)), LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)), @@ -482,7 +476,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicTypeEnum::ScalableVectorType(ScalableVectorType::new(type_)) @@ -498,14 +492,14 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMX86_AMXTypeKind => unreachable!("Unsupported basic type: AMX"), LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"), LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"), LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"), LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"), - #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] + #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] LLVMTypeKind::LLVMTargetExtTypeKind => unreachable!("Unsupported basic type: TargetExt"), } } diff --git a/src/types/float_type.rs b/src/types/float_type.rs index 4eb0b0bce04..2fe29876fde 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -6,7 +6,9 @@ use crate::context::ContextRef; use crate::support::LLVMString; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::traits::AsTypeRef; -use crate::types::{ArrayType, FunctionType, PointerType, ScalableVectorType, Type, VectorType}; +#[llvm_versions(12..)] +use crate::types::ScalableVectorType; +use crate::types::{ArrayType, FunctionType, PointerType, Type, VectorType}; use crate::values::{ArrayValue, FloatValue, GenericValue, IntValue}; use crate::AddressSpace; @@ -64,7 +66,7 @@ impl<'ctx> FloatType<'ctx> { self.float_type.array_type(size) } - /// Creates a `ScalableVectorType` with this `FloatType` for its element type. + /// Creates a `VectorType` with this `FloatType` for its element type. /// /// # Example /// @@ -242,7 +244,7 @@ impl<'ctx> FloatType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index 73f53f7e538..21f35015ecc 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -53,7 +53,7 @@ impl<'ctx> FunctionType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/int_type.rs b/src/types/int_type.rs index 38487c1241a..cd1d33e4428 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -7,7 +7,9 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::context::ContextRef; use crate::support::LLVMString; use crate::types::traits::AsTypeRef; -use crate::types::{ArrayType, FunctionType, PointerType, ScalableVectorType, Type, VectorType}; +#[llvm_versions(12..)] +use crate::types::ScalableVectorType; +use crate::types::{ArrayType, FunctionType, PointerType, Type, VectorType}; use crate::values::{ArrayValue, GenericValue, IntValue}; use crate::AddressSpace; @@ -329,7 +331,7 @@ impl<'ctx> IntType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/metadata_type.rs b/src/types/metadata_type.rs index db53342187c..c679541dc7a 100644 --- a/src/types/metadata_type.rs +++ b/src/types/metadata_type.rs @@ -19,7 +19,6 @@ impl<'ctx> MetadataType<'ctx> { /// /// # Safety /// Undefined behavior, if referenced type isn't metadata type - #[llvm_versions(6..)] pub unsafe fn new(metadata_type: LLVMTypeRef) -> Self { assert!(!metadata_type.is_null()); @@ -39,7 +38,6 @@ impl<'ctx> MetadataType<'ctx> { /// let md_type = context.metadata_type(); /// let fn_type = md_type.fn_type(&[], false); /// ``` - #[llvm_versions(6..)] pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> { self.metadata_type.fn_type(param_types, is_var_args) } @@ -56,7 +54,6 @@ impl<'ctx> MetadataType<'ctx> { /// /// assert_eq!(md_type.get_context(), context); /// ``` - #[llvm_versions(6..)] pub fn get_context(self) -> ContextRef<'ctx> { self.metadata_type.get_context() } @@ -68,15 +65,9 @@ impl<'ctx> MetadataType<'ctx> { } unsafe impl AsTypeRef for MetadataType<'_> { - #[llvm_versions(6..)] fn as_type_ref(&self) -> LLVMTypeRef { self.metadata_type.ty } - - #[llvm_versions(..=5)] - fn as_type_ref(&self) -> LLVMTypeRef { - unimplemented!("MetadataType is only available in LLVM > 6.0") - } } impl Display for MetadataType<'_> { diff --git a/src/types/ptr_type.rs b/src/types/ptr_type.rs index f1cf9db7c36..e649687a3e2 100644 --- a/src/types/ptr_type.rs +++ b/src/types/ptr_type.rs @@ -8,7 +8,9 @@ use crate::support::LLVMString; use crate::types::traits::AsTypeRef; #[cfg(feature = "typed-pointers")] use crate::types::AnyTypeEnum; -use crate::types::{ArrayType, FunctionType, ScalableVectorType, Type, VectorType}; +#[llvm_versions(12..)] +use crate::types::ScalableVectorType; +use crate::types::{ArrayType, FunctionType, Type, VectorType}; use crate::values::{ArrayValue, IntValue, PointerValue}; use crate::AddressSpace; @@ -98,7 +100,7 @@ impl<'ctx> PointerType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/scalable_vec_type.rs b/src/types/scalable_vec_type.rs index 82277bd65be..d1207c3af2b 100644 --- a/src/types/scalable_vec_type.rs +++ b/src/types/scalable_vec_type.rs @@ -180,7 +180,7 @@ impl<'ctx> ScalableVectorType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index b907de2cf1b..96b62bede41 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -209,7 +209,7 @@ impl<'ctx> StructType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/traits.rs b/src/types/traits.rs index 1caf9318913..a67c685cf32 100644 --- a/src/types/traits.rs +++ b/src/types/traits.rs @@ -137,7 +137,7 @@ pub unsafe trait BasicType<'ctx>: AnyType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/vec_type.rs b/src/types/vec_type.rs index 3a6a47765e3..7ae1fb01a62 100644 --- a/src/types/vec_type.rs +++ b/src/types/vec_type.rs @@ -208,7 +208,7 @@ impl<'ctx> VectorType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/values/call_site_value.rs b/src/values/call_site_value.rs index 241789f7b3b..212e29f2741 100644 --- a/src/values/call_site_value.rs +++ b/src/values/call_site_value.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Display}; use either::Either; -#[llvm_versions(8..)] + use llvm_sys::core::LLVMGetCalledFunctionType; use llvm_sys::core::{ LLVMGetCalledValue, LLVMGetInstructionCallConv, LLVMGetTypeKind, LLVMIsTailCall, LLVMSetInstrParamAlignment, @@ -240,16 +240,6 @@ impl<'ctx> CallSiteValue<'ctx> { self.get_called_fn_value_check_type_consistency(fn_value) } - #[llvm_versions(..8)] - #[inline] - fn get_called_fn_value_check_type_consistency( - &self, - fn_value: Option>, - ) -> Option> { - fn_value - } - - #[llvm_versions(8..)] #[inline] fn get_called_fn_value_check_type_consistency( &self, @@ -280,7 +270,6 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// assert_eq!(call_site_value.get_called_fn_type(), fn_type); /// ``` - #[llvm_versions(8..)] pub fn get_called_fn_type(self) -> FunctionType<'ctx> { // SAFETY: the passed LLVMValueRef is of type CallSite let fn_type_ref = unsafe { LLVMGetCalledFunctionType(self.as_value_ref()) }; diff --git a/src/values/callable_value.rs b/src/values/callable_value.rs index b7ae7c3a0d8..2595b76ba59 100644 --- a/src/values/callable_value.rs +++ b/src/values/callable_value.rs @@ -79,7 +79,7 @@ use llvm_sys::LLVMTypeKind; #[derive(Debug)] pub struct CallableValue<'ctx>(Either, PointerValue<'ctx>>); -unsafe impl<'ctx> AsValueRef for CallableValue<'ctx> { +unsafe impl AsValueRef for CallableValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { use either::Either::*; @@ -92,7 +92,7 @@ unsafe impl<'ctx> AsValueRef for CallableValue<'ctx> { unsafe impl<'ctx> AnyValue<'ctx> for CallableValue<'ctx> {} -unsafe impl<'ctx> AsTypeRef for CallableValue<'ctx> { +unsafe impl AsTypeRef for CallableValue<'_> { fn as_type_ref(&self) -> LLVMTypeRef { use either::Either::*; @@ -103,7 +103,7 @@ unsafe impl<'ctx> AsTypeRef for CallableValue<'ctx> { } } -impl<'ctx> CallableValue<'ctx> { +impl CallableValue<'_> { #[llvm_versions(..=14)] pub(crate) fn returns_void(&self) -> bool { use llvm_sys::core::LLVMGetReturnType; diff --git a/src/values/enums.rs b/src/values/enums.rs index b0a29933c3a..576dd388ae3 100644 --- a/src/values/enums.rs +++ b/src/values/enums.rs @@ -102,7 +102,7 @@ impl<'ctx> AnyValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { AnyValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) @@ -271,7 +271,7 @@ impl<'ctx> BasicValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) @@ -456,7 +456,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicMetadataValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) diff --git a/src/values/fn_value.rs b/src/values/fn_value.rs index ed8d98722fa..e93784ce9e1 100644 --- a/src/values/fn_value.rs +++ b/src/values/fn_value.rs @@ -10,7 +10,6 @@ use llvm_sys::core::{ LLVMIsAFunction, LLVMIsConstant, LLVMSetFunctionCallConv, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment, }; use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn}; -#[llvm_versions(7..)] use llvm_sys::debuginfo::{LLVMGetSubprogram, LLVMSetSubprogram}; use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef}; @@ -21,7 +20,6 @@ use std::mem::forget; use crate::attributes::{Attribute, AttributeLoc}; use crate::basic_block::BasicBlock; -#[llvm_versions(7..)] use crate::debug_info::DISubprogram; use crate::module::Linkage; use crate::support::to_c_str; @@ -205,16 +203,6 @@ impl<'ctx> FunctionValue<'ctx> { LLVMDeleteFunction(self.as_value_ref()) } - #[llvm_versions(..=7)] - pub fn get_type(self) -> FunctionType<'ctx> { - use crate::types::PointerType; - - let ptr_type = unsafe { PointerType::new(self.fn_value.get_type()) }; - - ptr_type.get_element_type().into_function_type() - } - - #[llvm_versions(8..)] pub fn get_type(self) -> FunctionType<'ctx> { unsafe { FunctionType::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) } } @@ -497,13 +485,11 @@ impl<'ctx> FunctionValue<'ctx> { } /// Set the debug info descriptor - #[llvm_versions(7..)] pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) { unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.metadata_ref) } } /// Get the debug info descriptor - #[llvm_versions(7..)] pub fn get_subprogram(self) -> Option> { let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) }; diff --git a/src/values/global_value.rs b/src/values/global_value.rs index 1ca9f5c1537..89d5482b680 100644 --- a/src/values/global_value.rs +++ b/src/values/global_value.rs @@ -1,14 +1,5 @@ -#[llvm_versions(8..)] use llvm_sys::core::LLVMGlobalSetMetadata; -#[llvm_versions(..=7)] -use llvm_sys::core::{ - LLVMDeleteGlobal, LLVMGetAlignment, LLVMGetDLLStorageClass, LLVMGetInitializer, LLVMGetLinkage, LLVMGetNextGlobal, - LLVMGetPreviousGlobal, LLVMGetSection, LLVMGetThreadLocalMode, LLVMGetVisibility, LLVMIsDeclaration, - LLVMIsExternallyInitialized, LLVMIsGlobalConstant, LLVMIsThreadLocal, LLVMSetAlignment, LLVMSetDLLStorageClass, - LLVMSetExternallyInitialized, LLVMSetGlobalConstant, LLVMSetInitializer, LLVMSetLinkage, LLVMSetSection, - LLVMSetThreadLocal, LLVMSetThreadLocalMode, LLVMSetVisibility, -}; -#[llvm_versions(8..)] + use llvm_sys::core::{ LLVMDeleteGlobal, LLVMGetAlignment, LLVMGetDLLStorageClass, LLVMGetInitializer, LLVMGetLinkage, LLVMGetNextGlobal, LLVMGetPreviousGlobal, LLVMGetThreadLocalMode, LLVMGetVisibility, LLVMIsDeclaration, LLVMIsExternallyInitialized, @@ -16,24 +7,21 @@ use llvm_sys::core::{ LLVMSetGlobalConstant, LLVMSetInitializer, LLVMSetLinkage, LLVMSetThreadLocal, LLVMSetThreadLocalMode, LLVMSetVisibility, }; -#[llvm_versions(7..)] + use llvm_sys::core::{LLVMGetUnnamedAddress, LLVMSetUnnamedAddress}; -#[llvm_versions(..=6)] -use llvm_sys::core::{LLVMHasUnnamedAddr, LLVMSetUnnamedAddr}; use llvm_sys::prelude::LLVMValueRef; use llvm_sys::LLVMThreadLocalMode; -#[llvm_versions(7..)] + use llvm_sys::LLVMUnnamedAddr; use std::ffi::CStr; use std::fmt::{self, Display}; -#[llvm_versions(7..)] use crate::comdat::Comdat; use crate::module::Linkage; use crate::types::AnyTypeEnum; use crate::values::traits::AsValueRef; -#[llvm_versions(8..)] + use crate::values::MetadataValue; use crate::values::{BasicValue, BasicValueEnum, PointerValue, Value}; use crate::{DLLStorageClass, GlobalVisibility, ThreadLocalMode}; @@ -167,22 +155,10 @@ impl<'ctx> GlobalValue<'ctx> { unsafe { LLVMIsDeclaration(self.as_value_ref()) == 1 } } - #[llvm_versions(..=6)] - pub fn has_unnamed_addr(self) -> bool { - unsafe { LLVMHasUnnamedAddr(self.as_value_ref()) == 1 } - } - - #[llvm_versions(7..)] pub fn has_unnamed_addr(self) -> bool { unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) == LLVMUnnamedAddr::LLVMGlobalUnnamedAddr } } - #[llvm_versions(..=6)] - pub fn set_unnamed_addr(self, has_unnamed_addr: bool) { - unsafe { LLVMSetUnnamedAddr(self.as_value_ref(), has_unnamed_addr as i32) } - } - - #[llvm_versions(7..)] pub fn set_unnamed_addr(self, has_unnamed_addr: bool) { unsafe { if has_unnamed_addr { @@ -246,13 +222,11 @@ impl<'ctx> GlobalValue<'ctx> { } /// Sets a metadata of the given type on the GlobalValue - #[llvm_versions(8..)] pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) { unsafe { LLVMGlobalSetMetadata(self.as_value_ref(), kind_id, metadata.as_metadata_ref()) } } /// Gets a `Comdat` assigned to this `GlobalValue`, if any. - #[llvm_versions(7..)] pub fn get_comdat(self) -> Option { use llvm_sys::comdat::LLVMGetComdat; @@ -266,14 +240,12 @@ impl<'ctx> GlobalValue<'ctx> { } /// Assigns a `Comdat` to this `GlobalValue`. - #[llvm_versions(7..)] pub fn set_comdat(self, comdat: Comdat) { use llvm_sys::comdat::LLVMSetComdat; unsafe { LLVMSetComdat(self.as_value_ref(), comdat.0) } } - #[llvm_versions(7..)] pub fn get_unnamed_address(self) -> UnnamedAddress { use llvm_sys::core::LLVMGetUnnamedAddress; @@ -282,7 +254,6 @@ impl<'ctx> GlobalValue<'ctx> { UnnamedAddress::new(unnamed_address) } - #[llvm_versions(7..)] pub fn set_unnamed_address(self, address: UnnamedAddress) { use llvm_sys::core::LLVMSetUnnamedAddress; @@ -297,7 +268,6 @@ impl<'ctx> GlobalValue<'ctx> { unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) } } - #[llvm_versions(8..)] pub fn get_value_type(self) -> AnyTypeEnum<'ctx> { unsafe { AnyTypeEnum::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) } } @@ -316,7 +286,7 @@ impl Display for GlobalValue<'_> { } /// This enum determines the significance of a `GlobalValue`'s address. -#[llvm_versions(7..)] + #[llvm_enum(LLVMUnnamedAddr)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum UnnamedAddress { diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index f823fc87c92..5bd2eb9d490 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -53,7 +53,6 @@ pub enum InstructionOpcode { CleanupRet, ExtractElement, ExtractValue, - #[llvm_versions(8..)] FNeg, FAdd, FCmp, @@ -123,6 +122,7 @@ impl<'ctx> InstructionValue<'ctx> { fn is_a_alloca_inst(self) -> bool { !unsafe { LLVMIsAAllocaInst(self.as_value_ref()) }.is_null() } + #[allow(dead_code)] fn is_a_getelementptr_inst(self) -> bool { !unsafe { LLVMIsAGetElementPtrInst(self.as_value_ref()) }.is_null() } @@ -379,7 +379,8 @@ impl<'ctx> InstructionValue<'ctx> { if !self.is_a_load_inst() && !self.is_a_store_inst() { return Err("Value is not a load or store."); } - Ok(unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) }) + unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) }; + Ok(()) } // SubTypes: Only apply to memory access instructions diff --git a/src/values/metadata_value.rs b/src/values/metadata_value.rs index 4a56c36c3f9..0c8717647d9 100644 --- a/src/values/metadata_value.rs +++ b/src/values/metadata_value.rs @@ -3,9 +3,7 @@ use llvm_sys::core::{ }; use llvm_sys::prelude::LLVMValueRef; -#[llvm_versions(7..)] use llvm_sys::core::LLVMValueAsMetadata; -#[llvm_versions(7..)] use llvm_sys::prelude::LLVMMetadataRef; use crate::values::traits::AsValueRef; @@ -20,13 +18,7 @@ use std::fmt::{self, Display}; /// for the first input string that isn't known. /// /// Each LLVM version has a different set of pre-defined metadata kinds. -pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = if cfg!(feature = "llvm4-0") { - 22 -} else if cfg!(feature = "llvm5-0") { - 23 -} else if cfg!(any(feature = "llvm6-0", feature = "llvm7-0")) { - 25 -} else if cfg!(feature = "llvm8-0") { +pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = if cfg!(feature = "llvm8-0") { 26 } else if cfg!(feature = "llvm9-0") { 28 @@ -38,7 +30,7 @@ pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = if cfg!(feature = "llvm4-0") { 36 } else if cfg!(any(feature = "llvm16-0", feature = "llvm17-0")) { 39 -} else if cfg!(feature = "llvm18-0") { +} else if cfg!(feature = "llvm18-1") { 40 } else { panic!("Unhandled LLVM version") @@ -64,7 +56,6 @@ impl<'ctx> MetadataValue<'ctx> { } } - #[llvm_versions(7..)] pub(crate) fn as_metadata_ref(self) -> LLVMMetadataRef { unsafe { LLVMValueAsMetadata(self.as_value_ref()) } } diff --git a/src/values/mod.rs b/src/values/mod.rs index 04d3ac54a6c..16c1582eccc 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -21,14 +21,14 @@ mod struct_value; mod traits; mod vec_value; -#[cfg(feature = "llvm18-0")] +#[cfg(feature = "llvm18-1")] pub(crate) mod operand_bundle; #[cfg(not(any( feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" )))] mod callable_value; @@ -36,7 +36,7 @@ mod callable_value; feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" )))] pub use crate::values::callable_value::CallableValue; @@ -52,7 +52,7 @@ pub use crate::values::float_value::FloatValue; pub use crate::values::fn_value::FunctionValue; pub use crate::values::generic_value::GenericValue; pub use crate::values::global_value::GlobalValue; -#[llvm_versions(7..)] + pub use crate::values::global_value::UnnamedAddress; pub use crate::values::instruction_value::{InstructionOpcode, InstructionValue, OperandIter, OperandUseIter}; pub use crate::values::int_value::IntValue; @@ -73,8 +73,9 @@ pub use crate::values::vec_value::VectorValue; pub use llvm_sys::LLVMTailCallKind; use llvm_sys::core::{ - LLVMDumpValue, LLVMGetFirstUse, LLVMGetSection, LLVMIsAInstruction, LLVMIsConstant, LLVMIsNull, LLVMIsUndef, - LLVMPrintTypeToString, LLVMPrintValueToString, LLVMReplaceAllUsesWith, LLVMSetSection, LLVMTypeOf, + LLVMDumpValue, LLVMGetFirstUse, LLVMGetSection, LLVMGetValueName2, LLVMIsAInstruction, LLVMIsConstant, LLVMIsNull, + LLVMIsUndef, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMReplaceAllUsesWith, LLVMSetSection, + LLVMSetValueName2, LLVMTypeOf, }; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; @@ -130,34 +131,13 @@ impl<'ctx> Value<'ctx> { fn set_name(self, name: &str) { let c_string = to_c_str(name); - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))] - { - use llvm_sys::core::LLVMSetValueName; - - unsafe { - LLVMSetValueName(self.value, c_string.as_ptr()); - } - } - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - use llvm_sys::core::LLVMSetValueName2; - - unsafe { LLVMSetValueName2(self.value, c_string.as_ptr(), c_string.to_bytes().len()) } - } + unsafe { LLVMSetValueName2(self.value, c_string.as_ptr(), c_string.to_bytes().len()) } } // get_name should *not* return a LLVMString, because it is not an owned value AFAICT // TODO: Should make this take ownership of self. But what is the lifetime of the string? 'ctx? fn get_name(&self) -> &CStr { - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))] - let ptr = unsafe { - use llvm_sys::core::LLVMGetValueName; - - LLVMGetValueName(self.value) - }; - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] let ptr = unsafe { - use llvm_sys::core::LLVMGetValueName2; let mut len = 0; LLVMGetValueName2(self.value, &mut len) diff --git a/src/values/ptr_value.rs b/src/values/ptr_value.rs index d94098fc090..9efabaa591e 100644 --- a/src/values/ptr_value.rs +++ b/src/values/ptr_value.rs @@ -1,5 +1,5 @@ #[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))] -#[cfg_attr(feature = "llvm15-0", allow(deprecated))] +#[allow(deprecated)] use llvm_sys::core::{LLVMConstGEP, LLVMConstInBoundsGEP}; #[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))] use llvm_sys::core::{LLVMConstGEP2, LLVMConstInBoundsGEP2}; @@ -90,7 +90,7 @@ impl<'ctx> PointerValue<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = { LLVMConstGEP( self.as_value_ref(), @@ -135,7 +135,7 @@ impl<'ctx> PointerValue<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); #[cfg(not(feature = "llvm16-0"))] - #[cfg_attr(feature = "llvm15-0", allow(deprecated))] + #[allow(deprecated)] let value = { LLVMConstInBoundsGEP( self.as_value_ref(), diff --git a/tests/all/main.rs b/tests/all/main.rs index 2f57a23914c..1a0b41d1d87 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -7,15 +7,15 @@ mod test_attributes; mod test_basic_block; mod test_builder; mod test_context; -#[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] mod test_debug_info; mod test_execution_engine; mod test_instruction_conversion; mod test_instruction_values; +#[cfg(not(feature = "llvm8-0"))] mod test_intrinsics; mod test_module; mod test_object_file; -#[cfg(not(any(feature = "llvm17-0", feature = "llvm18-0")))] +#[cfg(not(any(feature = "llvm17-0", feature = "llvm18-1")))] mod test_passes; mod test_targets; mod test_tari_example; diff --git a/tests/all/test_builder.rs b/tests/all/test_builder.rs index 2e1869d26c6..b35666a306a 100644 --- a/tests/all/test_builder.rs +++ b/tests/all/test_builder.rs @@ -67,10 +67,6 @@ fn test_build_call() { .into_pointer_value(); #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -88,7 +84,7 @@ fn test_build_call() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] builder.build_indirect_call(fn_type2, load, &[], "call").unwrap(); builder.build_return(None).unwrap(); @@ -871,7 +867,6 @@ fn test_scalable_vector_convert_ops() { assert!(fn_value.verify(true)); } -#[llvm_versions(8..)] #[test] fn test_vector_convert_ops_respect_target_signedness() { let context = Context::create(); @@ -1317,7 +1312,6 @@ fn is_alignment_ok(align: u32) -> bool { align > 0 && align.is_power_of_two() && (align as f64).log2() < 64.0 } -#[llvm_versions(8..)] #[test] fn test_alignment_bytes() { let verify_alignment = |alignment: u32| { @@ -1355,7 +1349,6 @@ fn test_alignment_bytes() { verify_alignment(u32::MAX); } -#[llvm_versions(8..)] fn run_memcpy_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, @@ -1375,6 +1368,7 @@ fn run_memcpy_on<'ctx>( builder.position_at_end(entry); let len_value = i64_type.const_int(array_len as u64, false); + #[cfg(not(feature = "typed-pointers"))] let element_type = i32_type; let array_ptr = builder.build_array_malloc(i32_type, len_value, "array_ptr").unwrap(); @@ -1415,7 +1409,6 @@ fn run_memcpy_on<'ctx>( Ok(()) } -#[llvm_versions(8..)] #[test] fn test_memcpy() { // 1. Allocate an array with a few elements. @@ -1443,7 +1436,6 @@ fn test_memcpy() { } } -#[llvm_versions(8..)] fn run_memmove_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, @@ -1463,6 +1455,7 @@ fn run_memmove_on<'ctx>( builder.position_at_end(entry); let len_value = i64_type.const_int(array_len as u64, false); + #[cfg(not(feature = "typed-pointers"))] let element_type = i32_type; let array_ptr = builder.build_array_malloc(i32_type, len_value, "array_ptr").unwrap(); @@ -1503,7 +1496,6 @@ fn run_memmove_on<'ctx>( Ok(()) } -#[llvm_versions(8..)] #[test] fn test_memmove() { // 1. Allocate an array with a few elements. @@ -1531,7 +1523,6 @@ fn test_memmove() { } } -#[llvm_versions(8..)] fn run_memset_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, @@ -1552,6 +1543,7 @@ fn run_memset_on<'ctx>( builder.position_at_end(entry); let len_value = i64_type.const_int(array_len as u64, false); + #[cfg(not(feature = "typed-pointers"))] let element_type = i32_type; let array_ptr = builder.build_array_malloc(i32_type, len_value, "array_ptr").unwrap(); @@ -1578,7 +1570,6 @@ fn run_memset_on<'ctx>( Ok(()) } -#[llvm_versions(8..)] #[test] fn test_memset() { // 1. Allocate an array with a few elements. @@ -1633,7 +1624,7 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let i32_scalable_vec_type = i32_type.scalable_vec_type(2); let arg_types = [ @@ -1649,7 +1640,7 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] i32_scalable_vec_type.into(), ]; @@ -1669,7 +1660,7 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let i32_scalable_vec_arg = fn_value.get_nth_param(5).unwrap(); @@ -1686,7 +1677,7 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] { let i64_scalable_vec_type = i64_type.scalable_vec_type(1); diff --git a/tests/all/test_debug_info.rs b/tests/all/test_debug_info.rs index 31408f0ef92..f7ae9cabfa7 100644 --- a/tests/all/test_debug_info.rs +++ b/tests/all/test_debug_info.rs @@ -33,7 +33,7 @@ fn test_smoke() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -44,19 +44,13 @@ fn test_smoke() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); let ditype = dibuilder - .create_basic_type( - "type_name", - 0_u64, - 0x00, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::PUBLIC, - ) + .create_basic_type("type_name", 0_u64, 0x00, DIFlags::PUBLIC) .unwrap(); let subroutine_type = dibuilder.create_subroutine_type(compile_unit.get_file(), Some(ditype.as_type()), &[], DIFlags::PUBLIC); @@ -86,9 +80,9 @@ fn test_smoke() { let loc = dibuilder.create_debug_location(&context, 0, 0, lexical_block.as_debug_info_scope(), None); - #[cfg(any(feature = "llvm7-0", feature = "llvm8-0",))] + #[cfg(feature = "llvm8-0")] builder.set_current_debug_location(&context, loc); - #[cfg(not(any(feature = "llvm7-0", feature = "llvm8-0",)))] + #[cfg(not(feature = "llvm8-0"))] builder.set_current_debug_location(loc); dibuilder.finalize(); @@ -123,7 +117,7 @@ fn test_struct_with_placeholders() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -134,48 +128,16 @@ fn test_struct_with_placeholders() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); // Some byte aligned integer types. - let i32ty = dibuilder - .create_basic_type( - "i32", - 32, - 0x07, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::PUBLIC, - ) - .unwrap(); - let i64ty = dibuilder - .create_basic_type( - "i64", - 64, - 0x07, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::PUBLIC, - ) - .unwrap(); - let f32ty = dibuilder - .create_basic_type( - "f32", - 32, - 0x04, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::PUBLIC, - ) - .unwrap(); - let f64ty = dibuilder - .create_basic_type( - "f64", - 64, - 0x04, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::PUBLIC, - ) - .unwrap(); + let i32ty = dibuilder.create_basic_type("i32", 32, 0x07, DIFlags::PUBLIC).unwrap(); + let i64ty = dibuilder.create_basic_type("i64", 64, 0x07, DIFlags::PUBLIC).unwrap(); + let f32ty = dibuilder.create_basic_type("f32", 32, 0x04, DIFlags::PUBLIC).unwrap(); + let f64ty = dibuilder.create_basic_type("f64", 64, 0x04, DIFlags::PUBLIC).unwrap(); let member_sizes = [32, 64, 32, 64]; let member_types = [i32ty, i64ty, f32ty, f64ty]; @@ -255,7 +217,7 @@ fn test_no_explicit_finalize() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -266,7 +228,7 @@ fn test_no_explicit_finalize() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); @@ -276,7 +238,6 @@ fn test_no_explicit_finalize() { assert!(module.verify().is_ok()); } -#[llvm_versions(8..)] #[test] fn test_replacing_placeholder_with_placeholder() { let context = Context::create(); @@ -304,7 +265,7 @@ fn test_replacing_placeholder_with_placeholder() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -315,7 +276,7 @@ fn test_replacing_placeholder_with_placeholder() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); @@ -367,7 +328,7 @@ fn test_anonymous_basic_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -378,24 +339,17 @@ fn test_anonymous_basic_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); assert_eq!( - dibuilder.create_basic_type( - "", - 0_u64, - 0x00, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::ZERO - ), + dibuilder.create_basic_type("", 0_u64, 0x00, DIFlags::ZERO), Err("basic types must have names") ); } -#[llvm_versions(8..)] #[test] fn test_global_expressions() { let context = Context::create(); @@ -423,7 +377,7 @@ fn test_global_expressions() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -434,7 +388,7 @@ fn test_global_expressions() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); @@ -497,7 +451,7 @@ fn test_pointer_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -508,19 +462,13 @@ fn test_pointer_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); let di_type = dibuilder - .create_basic_type( - "type_name", - 8_u64, - 0x00, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::ZERO, - ) + .create_basic_type("type_name", 8_u64, 0x00, DIFlags::ZERO) .unwrap() .as_type(); @@ -555,7 +503,7 @@ fn test_reference_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -566,19 +514,13 @@ fn test_reference_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); let di_type = dibuilder - .create_basic_type( - "type_name", - 8_u64, - 0x00, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::ZERO, - ) + .create_basic_type("type_name", 8_u64, 0x00, DIFlags::ZERO) .unwrap() .as_type(); @@ -614,7 +556,7 @@ fn test_array_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", #[cfg(any( @@ -625,19 +567,13 @@ fn test_array_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] "", ); let di_type = dibuilder - .create_basic_type( - "type_name", - 8_u64, - 0x00, - #[cfg(not(feature = "llvm7-0"))] - DIFlags::ZERO, - ) + .create_basic_type("type_name", 8_u64, 0x00, DIFlags::ZERO) .unwrap() .as_type(); diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index f280a0cf325..8aa07408658 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -3,7 +3,9 @@ use inkwell::context::Context; use inkwell::types::AnyType; use inkwell::types::{AnyTypeEnum, BasicType}; use inkwell::values::{BasicValue, CallSiteValue, InstructionOpcode::*}; -use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; +#[llvm_versions(10..)] +use inkwell::AtomicRMWBinOp; +use inkwell::{AddressSpace, AtomicOrdering, FloatPredicate, IntPredicate}; #[test] #[ignore] @@ -283,7 +285,7 @@ fn test_instructions() { #[cfg(not(feature = "typed-pointers"))] { - let gep_instr = unsafe { builder.build_gep(i64_type, alloca_val, &vec![], "gep").unwrap() }; + let gep_instr = unsafe { builder.build_gep(i64_type, alloca_val, &[], "gep").unwrap() }; assert_eq!( gep_instr .as_instruction_value() @@ -436,16 +438,16 @@ fn test_mem_instructions() { let load = builder.build_load(arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); - assert_eq!(store_instruction.get_volatile().unwrap(), false); - assert_eq!(load_instruction.get_volatile().unwrap(), false); + assert!(!store_instruction.get_volatile().unwrap()); + assert!(!load_instruction.get_volatile().unwrap()); store_instruction.set_volatile(true).unwrap(); load_instruction.set_volatile(true).unwrap(); - assert_eq!(store_instruction.get_volatile().unwrap(), true); - assert_eq!(load_instruction.get_volatile().unwrap(), true); + assert!(store_instruction.get_volatile().unwrap()); + assert!(load_instruction.get_volatile().unwrap()); store_instruction.set_volatile(false).unwrap(); load_instruction.set_volatile(false).unwrap(); - assert_eq!(store_instruction.get_volatile().unwrap(), false); - assert_eq!(load_instruction.get_volatile().unwrap(), false); + assert!(!store_instruction.get_volatile().unwrap()); + assert!(!load_instruction.get_volatile().unwrap()); assert_eq!(store_instruction.get_alignment().unwrap(), 0); assert_eq!(load_instruction.get_alignment().unwrap(), 0); diff --git a/tests/all/test_intrinsics.rs b/tests/all/test_intrinsics.rs index 9adb66caa00..ae73bdcdf82 100644 --- a/tests/all/test_intrinsics.rs +++ b/tests/all/test_intrinsics.rs @@ -1,19 +1,16 @@ use inkwell::context::Context; use inkwell::intrinsics::Intrinsic; -#[llvm_versions(9..)] #[test] fn test_get_cos() { Intrinsic::find("llvm.cos").unwrap(); } -#[llvm_versions(9..)] #[test] fn test_get_nonexistent() { assert!(Intrinsic::find("nonsense").is_none()) } -#[llvm_versions(9..)] #[test] fn test_get_decl_cos() { let cos = Intrinsic::find("llvm.cos").unwrap(); @@ -31,7 +28,6 @@ fn test_get_decl_cos() { assert_eq!(decl.get_name().to_str().unwrap(), "llvm.cos.f32"); } -#[llvm_versions(9..)] #[test] fn test_get_decl_va_copy() { let va_copy = Intrinsic::find("llvm.va_copy").unwrap(); diff --git a/tests/all/test_module.rs b/tests/all/test_module.rs index aa88002d47c..426a9074db8 100644 --- a/tests/all/test_module.rs +++ b/tests/all/test_module.rs @@ -341,7 +341,6 @@ fn test_get_set_target() { assert_eq!(module.get_name().to_str(), Ok("mod")); assert_eq!(module.get_triple(), TargetTriple::create("")); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] assert_eq!(module.get_source_file_name().to_str(), Ok("mod")); module.set_name("mod2"); @@ -350,13 +349,10 @@ fn test_get_set_target() { assert_eq!(module.get_name().to_str(), Ok("mod2")); assert_eq!(module.get_triple(), triple); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - module.set_source_file_name("foo.rs"); + module.set_source_file_name("foo.rs"); - assert_eq!(module.get_source_file_name().to_str(), Ok("foo.rs")); - assert_eq!(module.get_name().to_str(), Ok("mod2")); - } + assert_eq!(module.get_source_file_name().to_str(), Ok("foo.rs")); + assert_eq!(module.get_name().to_str(), Ok("mod2")); } #[test] @@ -433,40 +429,37 @@ fn test_linking_modules() { #[test] fn test_metadata_flags() { - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - let context = Context::create(); - let module = context.create_module("my_module"); + let context = Context::create(); + let module = context.create_module("my_module"); - use inkwell::module::FlagBehavior; + use inkwell::module::FlagBehavior; - assert!(module.get_flag("some_key").is_none()); + assert!(module.get_flag("some_key").is_none()); - let md = context.metadata_string("lots of metadata here"); + let md = context.metadata_string("lots of metadata here"); - module.add_metadata_flag("some_key", FlagBehavior::Error, md); + module.add_metadata_flag("some_key", FlagBehavior::Error, md); - // These have different addresses but same value - assert!(module.get_flag("some_key").is_some()); + // These have different addresses but same value + assert!(module.get_flag("some_key").is_some()); - let f64_type = context.f64_type(); - let f64_val = f64_type.const_float(std::f64::consts::PI); + let f64_type = context.f64_type(); + let f64_val = f64_type.const_float(std::f64::consts::PI); - assert!(module.get_flag("some_key2").is_none()); + assert!(module.get_flag("some_key2").is_none()); - module.add_basic_value_flag("some_key2", FlagBehavior::Error, f64_val); + module.add_basic_value_flag("some_key2", FlagBehavior::Error, f64_val); - assert!(module.get_flag("some_key2").is_some()); + assert!(module.get_flag("some_key2").is_some()); - let struct_val = context.const_struct(&[f64_val.into()], false); + let struct_val = context.const_struct(&[f64_val.into()], false); - assert!(module.get_flag("some_key3").is_none()); + assert!(module.get_flag("some_key3").is_none()); - module.add_basic_value_flag("some_key3", FlagBehavior::Error, struct_val); + module.add_basic_value_flag("some_key3", FlagBehavior::Error, struct_val); - assert!(module.get_flag("some_key3").is_some()); - assert!(module.verify().is_ok()); - } + assert!(module.get_flag("some_key3").is_some()); + assert!(module.verify().is_ok()); } #[test] diff --git a/tests/all/test_object_file.rs b/tests/all/test_object_file.rs index 375a1cd3d67..e5cb6e741f4 100644 --- a/tests/all/test_object_file.rs +++ b/tests/all/test_object_file.rs @@ -5,12 +5,10 @@ use inkwell::types::IntType; use inkwell::values::BasicValue; use inkwell::OptimizationLevel; -#[llvm_versions(7..)] fn get_host_cpu_name() -> String { TargetMachine::get_host_cpu_name().to_string() } -#[llvm_versions(7..)] fn get_host_cpu_features() -> String { TargetMachine::get_host_cpu_features().to_string() } @@ -25,16 +23,6 @@ fn apply_target_to_module(target_machine: &TargetMachine, module: &Module) { module.set_data_layout(&target_machine.get_target_data().get_data_layout()); } -#[llvm_versions(..7)] -fn get_host_cpu_name() -> String { - "".to_string() -} - -#[llvm_versions(..7)] -fn get_host_cpu_features() -> String { - "".to_string() -} - fn get_native_target_machine() -> TargetMachine { Target::initialize_native(&InitializationConfig::default()).expect("Failed to initialize native target"); let target_triple = TargetMachine::get_default_triple(); diff --git a/tests/all/test_passes.rs b/tests/all/test_passes.rs index d1138e61362..62df8ba701f 100644 --- a/tests/all/test_passes.rs +++ b/tests/all/test_passes.rs @@ -14,10 +14,6 @@ fn test_init_all_passes_for_module() { let pass_manager = PassManager::create(()); #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -28,14 +24,7 @@ fn test_init_all_passes_for_module() { ))] pass_manager.add_argument_promotion_pass(); pass_manager.add_constant_merge_pass(); - #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm8-0", - feature = "llvm9-0" - )))] + #[cfg(not(any(feature = "llvm8-0", feature = "llvm9-0")))] pass_manager.add_merge_functions_pass(); pass_manager.add_dead_arg_elimination_pass(); pass_manager.add_function_attrs_pass(); @@ -57,8 +46,6 @@ fn test_init_all_passes_for_module() { pass_manager.add_internalize_pass(true); pass_manager.add_strip_dead_prototypes_pass(); pass_manager.add_strip_symbol_pass(); - #[cfg(feature = "llvm4-0")] - pass_manager.add_bb_vectorize_pass(); pass_manager.add_loop_vectorize_pass(); pass_manager.add_slp_vectorize_pass(); pass_manager.add_aggressive_dce_pass(); @@ -79,10 +66,6 @@ fn test_init_all_passes_for_module() { pass_manager.add_loop_reroll_pass(); pass_manager.add_loop_unroll_pass(); #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -130,19 +113,11 @@ fn test_init_all_passes_for_module() { pass_manager.add_early_cse_mem_ssa_pass(); pass_manager.add_new_gvn_pass(); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm16-0")))] + #[cfg(not(feature = "llvm16-0"))] pass_manager.add_aggressive_inst_combiner_pass(); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] pass_manager.add_loop_unroll_and_jam_pass(); - #[cfg(not(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", - feature = "llvm15-0", - feature = "llvm16-0" - )))] + #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0")))] { pass_manager.add_coroutine_early_pass(); pass_manager.add_coroutine_split_pass(); @@ -183,10 +158,7 @@ fn test_pass_manager_builder() { assert!(!fn_pass_manager.initialize()); // TODO: Test with actual changes? Would be true in that case - // REVIEW: Segfaults in 4.0 - #[cfg(not(feature = "llvm4-0"))] assert!(!fn_pass_manager.run_on(&fn_value)); - assert!(!fn_pass_manager.finalize()); let module_pass_manager = PassManager::create(()); @@ -194,10 +166,6 @@ fn test_pass_manager_builder() { pass_manager_builder.populate_module_pass_manager(&module_pass_manager); #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -215,9 +183,6 @@ fn test_pass_manager_builder() { assert!(lto_pass_manager.run_on(&module2)); } - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0"))] - assert!(!module_pass_manager.run_on(&module)); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0")))] assert!(module_pass_manager.run_on(&module)); } @@ -239,7 +204,7 @@ fn test_pass_registry() { pass_registry.initialize_ipa(); pass_registry.initialize_codegen(); pass_registry.initialize_target(); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm16-0")))] + #[cfg(not(feature = "llvm16-0"))] pass_registry.initialize_aggressive_inst_combiner(); } diff --git a/tests/all/test_targets.rs b/tests/all/test_targets.rs index dad038bdf73..4672c5a4026 100644 --- a/tests/all/test_targets.rs +++ b/tests/all/test_targets.rs @@ -97,12 +97,6 @@ fn test_target_and_target_machine() { let bad_target2 = Target::from_triple(&TargetTriple::create("sadas")); - #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0"))] - assert_eq!( - bad_target2.unwrap_err().to_string(), - "No available targets are compatible with this triple." - ); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))] assert_eq!( bad_target2.unwrap_err().to_string(), "No available targets are compatible with triple \"sadas\"" @@ -165,17 +159,14 @@ fn test_target_and_target_machine() { assert_eq!(target_machine.get_cpu().to_str(), Ok("x86-64")); assert_eq!(target_machine.get_feature_string().to_str(), Ok("+avx2")); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - // TODO: Try and find a triple that actually gets normalized.. - assert_eq!( - TargetMachine::normalize_triple(&triple).as_str().to_str(), - Ok("x86_64-pc-linux-gnu"), - ); + // TODO: Try and find a triple that actually gets normalized.. + assert_eq!( + TargetMachine::normalize_triple(&triple).as_str().to_str(), + Ok("x86_64-pc-linux-gnu"), + ); - let _host_name = TargetMachine::get_host_cpu_name(); - let _host_cpu_features = TargetMachine::get_host_cpu_features(); - } + let _host_name = TargetMachine::get_host_cpu_name(); + let _host_cpu_features = TargetMachine::get_host_cpu_features(); } #[test] diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index 8872e7c91d5..e9a0b4f0543 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -144,7 +144,6 @@ fn test_function_type() { /// Check that `FunctionType::get_param_types()` can handle metadata arguments. /// Regression test for inkwell#546 -#[llvm_versions(6..)] #[test] fn test_function_type_metadata_params() { let llvm_ir = r#" @@ -283,7 +282,7 @@ fn sized_types(global_ctx: &Context) { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] { assert!(bool_type.scalable_vec_type(42).is_sized()); @@ -342,7 +341,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_type = f64_type.scalable_vec_type(42); let array_type = f64_type.array_type(42); @@ -359,7 +358,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] scalable_vec_type.size_of(); array_type.size_of(); @@ -376,7 +375,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] scalable_vec_type.get_alignment(); array_type.get_alignment(); @@ -403,7 +402,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_zero = scalable_vec_type.const_zero(); let array_zero = array_type.const_zero(); @@ -430,7 +429,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(scalable_vec_zero.is_null()); assert!(array_zero.is_null()); @@ -478,7 +477,7 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert_eq!( scalable_vec_zero.print_to_string().to_str(), @@ -569,7 +568,7 @@ fn test_basic_type_enum() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] &int.scalable_vec_type(1), ]; diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index fbc6fe24d27..7674f155952 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -1,19 +1,20 @@ use inkwell::attributes::AttributeLoc; -#[llvm_versions(7..)] + use inkwell::comdat::ComdatSelectionKind; use inkwell::context::Context; +#[llvm_versions(15..)] use inkwell::memory_buffer::MemoryBuffer; use inkwell::module::Linkage::*; use inkwell::types::{AnyTypeEnum, StringRadix, VectorType}; +#[llvm_versions(15..)] +use inkwell::values::CallSiteValue; #[llvm_versions(18..)] use inkwell::values::OperandBundle; -use inkwell::values::{AnyValue, CallSiteValue, InstructionOpcode::*, FIRST_CUSTOM_METADATA_KIND_ID}; +use inkwell::values::{AnyValue, InstructionOpcode::*, FIRST_CUSTOM_METADATA_KIND_ID}; use inkwell::{AddressSpace, DLLStorageClass, GlobalVisibility, ThreadLocalMode}; #[llvm_versions(18..)] -pub use llvm_sys::LLVMTailCallKind::*; -#[cfg(feature = "llvm18-0")] -use llvm_sys_180 as llvm_sys; +pub use inkwell::llvm_sys::LLVMTailCallKind::*; use std::convert::TryFrom; @@ -73,7 +74,7 @@ fn test_call_site() { } #[test] -#[cfg(feature = "llvm18-0")] +#[cfg(feature = "llvm18-1")] fn test_call_site_tail_call_attributes() { let context = Context::create(); let builder = context.create_builder(); @@ -237,7 +238,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -263,7 +264,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert_eq!(scalable_vec_val.get_name().to_str(), Ok("")); assert_eq!(ppc_f128_val.get_name().to_str(), Ok("")); @@ -290,7 +291,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] scalable_vec_val.set_name("my_val15"); ppc_f128_val.set_name("my_val16"); @@ -316,7 +317,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert_eq!(scalable_vec_val.get_name().to_str(), Ok("")); assert_eq!(ppc_f128_val.get_name().to_str(), Ok("")); @@ -335,7 +336,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_type = bool_type.scalable_vec_type(1); @@ -357,7 +358,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] scalable_vec_type.into(), ]; @@ -381,7 +382,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_param = function.get_nth_param(6).unwrap().into_scalable_vector_value(); let phi_val = builder.build_phi(bool_type, "phi_node").unwrap(); @@ -399,7 +400,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert_eq!(scalable_vec_param.get_name().to_str(), Ok("")); assert_eq!(phi_val.get_name().to_str(), Ok("phi_node")); @@ -417,7 +418,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] scalable_vec_param.set_name("my_val7"); phi_val.set_name("phi"); @@ -435,7 +436,7 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert_eq!(scalable_vec_param.get_name().to_str(), Ok("my_val7")); assert_eq!(phi_val.get_name().to_str(), Ok("phi")); @@ -487,7 +488,7 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -513,7 +514,7 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(!scalable_vec_val.is_undef()); assert!(!ppc_f128_val.is_undef()); @@ -542,7 +543,7 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_undef = bool_type.scalable_vec_type(1).get_undef(); let ppc_f128_undef = ppc_f128_type.get_undef(); @@ -568,7 +569,7 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(scalable_vec_undef.is_undef()); assert!(ppc_f128_undef.is_undef()); @@ -598,7 +599,7 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_type = f64_type.scalable_vec_type(42); let ppc_f128_type = context.ppc_f128_type(); @@ -629,7 +630,7 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_val = scalable_vec_type.const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -655,7 +656,7 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(!scalable_vec_val.is_poison()); assert!(!ppc_f128_val.is_poison()); @@ -684,7 +685,7 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_poison = scalable_vec_type.get_poison(); let ppc_f128_poison = ppc_f128_type.get_poison(); @@ -710,7 +711,7 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(scalable_vec_poison.is_poison()); assert!(ppc_f128_poison.is_poison()); @@ -800,166 +801,154 @@ fn test_metadata() { assert_eq!(context.get_kind_id("type"), 19); assert_eq!(context.get_kind_id("section_prefix"), 20); assert_eq!(context.get_kind_id("absolute_symbol"), 21); + assert_eq!(context.get_kind_id("associated"), 22); + assert_eq!(context.get_kind_id("callees"), 23); + assert_eq!(context.get_kind_id("irr_loop"), 24); + assert_eq!(module.get_global_metadata_size("my_string_md"), 0); + assert_eq!(module.get_global_metadata("my_string_md").len(), 0); - #[cfg(not(feature = "llvm4-0"))] - { - assert_eq!(context.get_kind_id("associated"), 22); - } + let md_string = context.metadata_string("lots of metadata here"); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0")))] - { - assert_eq!(context.get_kind_id("callees"), 23); - assert_eq!(context.get_kind_id("irr_loop"), 24); - } + assert_eq!(md_string.get_node_size(), 0); + assert_eq!(md_string.get_node_values().len(), 0); + assert_eq!( + md_string.get_string_value().unwrap().to_str(), + Ok("lots of metadata here") + ); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - assert_eq!(module.get_global_metadata_size("my_string_md"), 0); - assert_eq!(module.get_global_metadata("my_string_md").len(), 0); - - let md_string = context.metadata_string("lots of metadata here"); - - assert_eq!(md_string.get_node_size(), 0); - assert_eq!(md_string.get_node_values().len(), 0); - assert_eq!( - md_string.get_string_value().unwrap().to_str(), - Ok("lots of metadata here") - ); - - let bool_type = context.bool_type(); - // let i8_type = context.i8_type(); - // let i16_type = context.i16_type(); - // let i32_type = context.i32_type(); - // let i64_type = context.i64_type(); - // let i128_type = context.i128_type(); - // let f16_type = context.f16_type(); - let f32_type = context.f32_type(); - // let f64_type = context.f64_type(); - // let f128_type = context.f128_type(); - // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] - // let ptr_type = context.ptr_type(AddressSpace::default()); - // let array_type = f64_type.array_type(42); - // let ppc_f128_type = context.ppc_f128_type(); - // let fn_type = bool_type.fn_type(&[i64_type.into(), array_type.into()], false); - - let bool_val = bool_type.const_int(0, false); - // let i8_val = i8_type.const_int(0, false); - // let i16_val = i16_type.const_int(0, false); - // let i32_val = i32_type.const_int(0, false); - // let i64_val = i64_type.const_int(0, false); - // let i128_val = i128_type.const_int(0, false); - // let f16_val = f16_type.const_float(0.0); - let f32_val = f32_type.const_float(0.0); - // let f64_val = f64_type.const_float(0.0); - // let f128_val = f128_type.const_float(0.0); - // let ppc_f128_val = ppc_f128_type.const_float(0.0); - // #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] - // let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); - // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))] - // let ptr_val = ptr_type.const_null(); - // let array_val = f64_type.const_array(&[f64_val]); - // let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); - // let vec_val = VectorType::const_vector(&[i8_val]); - // let fn_val = module.add_function("my_fn", fn_type, None); - - let md_node_child = context.metadata_node(&[bool_val.into(), f32_val.into()]); - let md_node = context.metadata_node(&[bool_val.into(), f32_val.into(), md_string.into(), md_node_child.into()]); - - let node_values = md_node.get_node_values(); - - assert_eq!(md_node.get_string_value(), None); - assert_eq!(node_values.len(), 4); - assert_eq!(node_values[0].into_int_value(), bool_val); - assert_eq!(node_values[1].into_float_value(), f32_val); - assert_eq!( - node_values[2].into_metadata_value().get_string_value(), - md_string.get_string_value() - ); - assert!(node_values[3].into_metadata_value().is_node()); - - assert!(module.add_global_metadata("my_md", &md_string).is_err()); - module.add_global_metadata("my_md", &md_node).unwrap(); - - assert_eq!(module.get_global_metadata_size("my_md"), 1); - - let global_md = module.get_global_metadata("my_md"); - - assert_eq!(global_md.len(), 1); - - let md = global_md[0].get_node_values(); - - assert_eq!(md.len(), 4); - assert_eq!(md[0].into_int_value(), bool_val); - assert_eq!(md[1].into_float_value(), f32_val); - assert_eq!( - md[2].into_metadata_value().get_string_value(), - md_string.get_string_value() - ); - assert!(md[3].into_metadata_value().is_node()); - - assert_eq!(module.get_global_metadata_size("other_md"), 0); - - // REVIEW: const_null_ptr/ ptr.const_null seem to cause UB. Need to test and adapt - // and see if they should be allowed to have metadata? Also, while we're at it we should - // try with undef - - // REVIEW: initial has_metadata seems inconsistent. Some have it. Some don't for kind_id 0. Some sometimes have it. - // furthermore, when they do have it, it is a SF when printing out. Unclear what can be done here. Maybe just disallow index 0? - // assert!(bool_val.has_metadata()); - // assert!(i8_val.has_metadata()); - // assert!(i16_val.has_metadata()); - // assert!(i32_val.has_metadata()); - // assert!(i64_val.has_metadata()); - // assert!(!i128_val.has_metadata()); - // assert!(!f16_val.has_metadata()); - // assert!(!f32_val.has_metadata()); - // assert!(!f64_val.has_metadata()); - // assert!(!f128_val.has_metadata()); - // assert!(!ppc_f128_val.has_metadata()); - // assert!(ptr_val.has_metadata()); - // assert!(array_val.has_metadata()); - // assert!(struct_val.has_metadata()); - // assert!(!vec_val.has_metadata()); - // assert!(!fn_val.has_metadata()); - - let builder = context.create_builder(); - let module = context.create_module("my_mod"); - let void_type = context.void_type(); - let bool_type = context.bool_type(); - let fn_type = void_type.fn_type(&[bool_type.into()], false); - let fn_value = module.add_function("my_func", fn_type, None); - - let entry_block = context.append_basic_block(fn_value, "entry"); - - builder.position_at_end(entry_block); - - let ret_instr = builder.build_return(None).unwrap(); - let ret_instr_md = context.metadata_node(&[md_string.into()]); - - assert!(ret_instr.set_metadata(ret_instr_md, 2).is_ok()); - assert!(ret_instr.has_metadata()); - assert!(ret_instr.get_metadata(1).is_none()); - - let md_node_values = ret_instr.get_metadata(2).unwrap().get_node_values(); - - assert_eq!(md_node_values.len(), 1); - assert_eq!( - md_node_values[0].into_metadata_value().get_string_value(), - md_string.get_string_value() - ); - - // New Context Metadata - let context_metadata_node = context.metadata_node(&[bool_val.into(), f32_val.into()]); - let context_metadata_string = context.metadata_string("my_context_metadata"); - - assert!(context_metadata_node.is_node()); - assert!(context_metadata_string.is_string()); - } + let bool_type = context.bool_type(); + // let i8_type = context.i8_type(); + // let i16_type = context.i16_type(); + // let i32_type = context.i32_type(); + // let i64_type = context.i64_type(); + // let i128_type = context.i128_type(); + // let f16_type = context.f16_type(); + let f32_type = context.f32_type(); + // let f64_type = context.f64_type(); + // let f128_type = context.f128_type(); + // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + // let ptr_type = context.ptr_type(AddressSpace::default()); + // let array_type = f64_type.array_type(42); + // let ppc_f128_type = context.ppc_f128_type(); + // let fn_type = bool_type.fn_type(&[i64_type.into(), array_type.into()], false); + + let bool_val = bool_type.const_int(0, false); + // let i8_val = i8_type.const_int(0, false); + // let i16_val = i16_type.const_int(0, false); + // let i32_val = i32_type.const_int(0, false); + // let i64_val = i64_type.const_int(0, false); + // let i128_val = i128_type.const_int(0, false); + // let f16_val = f16_type.const_float(0.0); + let f32_val = f32_type.const_float(0.0); + // let f64_val = f64_type.const_float(0.0); + // let f128_val = f128_type.const_float(0.0); + // let ppc_f128_val = ppc_f128_type.const_float(0.0); + // #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1")))] + // let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); + // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + // let ptr_val = ptr_type.const_null(); + // let array_val = f64_type.const_array(&[f64_val]); + // let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); + // let vec_val = VectorType::const_vector(&[i8_val]); + // let fn_val = module.add_function("my_fn", fn_type, None); + + let md_node_child = context.metadata_node(&[bool_val.into(), f32_val.into()]); + let md_node = context.metadata_node(&[bool_val.into(), f32_val.into(), md_string.into(), md_node_child.into()]); + + let node_values = md_node.get_node_values(); + + assert_eq!(md_node.get_string_value(), None); + assert_eq!(node_values.len(), 4); + assert_eq!(node_values[0].into_int_value(), bool_val); + assert_eq!(node_values[1].into_float_value(), f32_val); + assert_eq!( + node_values[2].into_metadata_value().get_string_value(), + md_string.get_string_value() + ); + assert!(node_values[3].into_metadata_value().is_node()); + + assert!(module.add_global_metadata("my_md", &md_string).is_err()); + module.add_global_metadata("my_md", &md_node).unwrap(); + + assert_eq!(module.get_global_metadata_size("my_md"), 1); + + let global_md = module.get_global_metadata("my_md"); + + assert_eq!(global_md.len(), 1); + + let md = global_md[0].get_node_values(); + + assert_eq!(md.len(), 4); + assert_eq!(md[0].into_int_value(), bool_val); + assert_eq!(md[1].into_float_value(), f32_val); + assert_eq!( + md[2].into_metadata_value().get_string_value(), + md_string.get_string_value() + ); + assert!(md[3].into_metadata_value().is_node()); + + assert_eq!(module.get_global_metadata_size("other_md"), 0); + + // REVIEW: const_null_ptr/ ptr.const_null seem to cause UB. Need to test and adapt + // and see if they should be allowed to have metadata? Also, while we're at it we should + // try with undef + + // REVIEW: initial has_metadata seems inconsistent. Some have it. Some don't for kind_id 0. Some sometimes have it. + // furthermore, when they do have it, it is a SF when printing out. Unclear what can be done here. Maybe just disallow index 0? + // assert!(bool_val.has_metadata()); + // assert!(i8_val.has_metadata()); + // assert!(i16_val.has_metadata()); + // assert!(i32_val.has_metadata()); + // assert!(i64_val.has_metadata()); + // assert!(!i128_val.has_metadata()); + // assert!(!f16_val.has_metadata()); + // assert!(!f32_val.has_metadata()); + // assert!(!f64_val.has_metadata()); + // assert!(!f128_val.has_metadata()); + // assert!(!ppc_f128_val.has_metadata()); + // assert!(ptr_val.has_metadata()); + // assert!(array_val.has_metadata()); + // assert!(struct_val.has_metadata()); + // assert!(!vec_val.has_metadata()); + // assert!(!fn_val.has_metadata()); + + let builder = context.create_builder(); + let module = context.create_module("my_mod"); + let void_type = context.void_type(); + let bool_type = context.bool_type(); + let fn_type = void_type.fn_type(&[bool_type.into()], false); + let fn_value = module.add_function("my_func", fn_type, None); + + let entry_block = context.append_basic_block(fn_value, "entry"); + + builder.position_at_end(entry_block); + + let ret_instr = builder.build_return(None).unwrap(); + let ret_instr_md = context.metadata_node(&[md_string.into()]); + + assert!(ret_instr.set_metadata(ret_instr_md, 2).is_ok()); + assert!(ret_instr.has_metadata()); + assert!(ret_instr.get_metadata(1).is_none()); + + let md_node_values = ret_instr.get_metadata(2).unwrap().get_node_values(); + + assert_eq!(md_node_values.len(), 1); + assert_eq!( + md_node_values[0].into_metadata_value().get_string_value(), + md_string.get_string_value() + ); + + // New Context Metadata + let context_metadata_node = context.metadata_node(&[bool_val.into(), f32_val.into()]); + let context_metadata_string = context.metadata_string("my_context_metadata"); + + assert!(context_metadata_node.is_node()); + assert!(context_metadata_string.is_string()); } #[test] fn test_floats() { - #[cfg(not(any(feature = "llvm15-0", feature = "llvm18-0")))] + #[cfg(not(any(feature = "llvm15-0", feature = "llvm18-1")))] { use inkwell::FloatPredicate; @@ -994,7 +983,7 @@ fn test_floats() { let f64_one = f64_type.const_float(1.); let f64_two = f64_type.const_float(2.); - #[cfg(not(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))] + #[cfg(not(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1")))] { let neg_two = f64_two.const_neg(); @@ -1138,7 +1127,6 @@ fn test_global_byte_array() { #[test] fn test_globals() { - #[llvm_versions(7..)] use inkwell::values::UnnamedAddress; let context = Context::create(); @@ -1152,7 +1140,6 @@ fn test_globals() { let global = module.add_global(i8_type, None, "my_global"); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] assert_eq!(global.get_unnamed_address(), UnnamedAddress::None); assert!(global.get_previous_global().is_none()); assert!(global.get_next_global().is_none()); @@ -1168,7 +1155,6 @@ fn test_globals() { assert_eq!(global.get_dll_storage_class(), DLLStorageClass::default()); assert_eq!(global.get_visibility(), GlobalVisibility::default()); assert_eq!(global.get_linkage(), External); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))] assert_eq!(global.get_value_type(), AnyTypeEnum::IntType(i8_type)); assert_eq!(module.get_first_global().unwrap(), global); assert_eq!(module.get_last_global().unwrap(), global); @@ -1180,7 +1166,6 @@ fn test_globals() { assert!(module.get_global("my_global").is_none()); assert_eq!(module.get_global("glob").unwrap(), global); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] global.set_unnamed_address(UnnamedAddress::Local); global.set_dll_storage_class(DLLStorageClass::Import); global.set_initializer(&i8_zero); @@ -1191,7 +1176,6 @@ fn test_globals() { global.set_section(Some("not sure what goes here")); // REVIEW: Not sure why this is Global when we set it to Local - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] assert_eq!(global.get_unnamed_address(), UnnamedAddress::Global); assert_eq!(global.get_dll_storage_class(), DLLStorageClass::Import); assert_eq!(global.get_initializer().unwrap().into_int_value(), i8_zero); @@ -1216,14 +1200,12 @@ fn test_globals() { assert_eq!(global.get_linkage(), Private); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] global.set_unnamed_address(UnnamedAddress::Global); global.set_dll_storage_class(DLLStorageClass::Export); global.set_thread_local(false); global.set_linkage(External); global.set_visibility(GlobalVisibility::Protected); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] assert_eq!(global.get_unnamed_address(), UnnamedAddress::Global); assert!(!global.is_thread_local()); assert_eq!(global.get_visibility(), GlobalVisibility::Protected); @@ -1275,23 +1257,20 @@ fn test_globals() { // REVIEW: This doesn't seem to work. LLVM bug? assert!(global2.is_externally_initialized()); - #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))] - { - assert!(global.get_comdat().is_none()); + assert!(global.get_comdat().is_none()); - let comdat = module.get_or_insert_comdat("my_comdat"); + let comdat = module.get_or_insert_comdat("my_comdat"); - assert!(global.get_comdat().is_none()); + assert!(global.get_comdat().is_none()); - global.set_comdat(comdat); + global.set_comdat(comdat); - assert_eq!(comdat, global.get_comdat().unwrap()); - assert_eq!(comdat.get_selection_kind(), ComdatSelectionKind::Any); + assert_eq!(comdat, global.get_comdat().unwrap()); + assert_eq!(comdat.get_selection_kind(), ComdatSelectionKind::Any); - comdat.set_selection_kind(ComdatSelectionKind::Largest); + comdat.set_selection_kind(ComdatSelectionKind::Largest); - assert_eq!(comdat.get_selection_kind(), ComdatSelectionKind::Largest); - } + assert_eq!(comdat.get_selection_kind(), ComdatSelectionKind::Largest); unsafe { global.delete(); @@ -1514,7 +1493,7 @@ fn test_consts() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let array_val = i8_type.const_array(&[i8_val]); @@ -1539,7 +1518,7 @@ fn test_consts() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] assert!(scalable_vec_val.is_const()); assert!(array_val.is_const()); @@ -1676,10 +1655,6 @@ fn test_non_fn_ptr_called() { builder.position_at_end(bb); #[cfg(any( - feature = "llvm4-0", - feature = "llvm5-0", - feature = "llvm6-0", - feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", @@ -1697,7 +1672,7 @@ fn test_non_fn_ptr_called() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-0" + feature = "llvm18-1" ))] builder .build_indirect_call(i8_ptr_type.fn_type(&[], false), i8_ptr_param, &[], "call") From f74e195126488b21581d6c3f53ed817c2b3f9e9a Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Fri, 25 Apr 2025 09:48:04 +0300 Subject: [PATCH 12/26] Report user's call location in case of `panic` in `into_*_value` functions (#584) Co-authored-by: Dan Kolsoi --- src/values/enums.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/values/enums.rs b/src/values/enums.rs index 576dd388ae3..bc98a18d0a8 100644 --- a/src/values/enums.rs +++ b/src/values/enums.rs @@ -163,6 +163,7 @@ impl<'ctx> AnyValueEnum<'ctx> { matches!(self, AnyValueEnum::InstructionValue(_)) } + #[track_caller] pub fn into_array_value(self) -> ArrayValue<'ctx> { if let AnyValueEnum::ArrayValue(v) = self { v @@ -171,6 +172,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_int_value(self) -> IntValue<'ctx> { if let AnyValueEnum::IntValue(v) = self { v @@ -179,6 +181,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_float_value(self) -> FloatValue<'ctx> { if let AnyValueEnum::FloatValue(v) = self { v @@ -187,6 +190,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_phi_value(self) -> PhiValue<'ctx> { if let AnyValueEnum::PhiValue(v) = self { v @@ -195,6 +199,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_function_value(self) -> FunctionValue<'ctx> { if let AnyValueEnum::FunctionValue(v) = self { v @@ -203,6 +208,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_pointer_value(self) -> PointerValue<'ctx> { if let AnyValueEnum::PointerValue(v) = self { v @@ -211,6 +217,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_struct_value(self) -> StructValue<'ctx> { if let AnyValueEnum::StructValue(v) = self { v @@ -219,6 +226,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_vector_value(self) -> VectorValue<'ctx> { if let AnyValueEnum::VectorValue(v) = self { v @@ -227,6 +235,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> { if let AnyValueEnum::ScalableVectorValue(v) = self { v @@ -235,6 +244,7 @@ impl<'ctx> AnyValueEnum<'ctx> { } } + #[track_caller] pub fn into_instruction_value(self) -> InstructionValue<'ctx> { if let AnyValueEnum::InstructionValue(v) = self { v @@ -338,6 +348,7 @@ impl<'ctx> BasicValueEnum<'ctx> { matches!(self, BasicValueEnum::ScalableVectorValue(_)) } + #[track_caller] pub fn into_array_value(self) -> ArrayValue<'ctx> { if let BasicValueEnum::ArrayValue(v) = self { v @@ -346,6 +357,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_int_value(self) -> IntValue<'ctx> { if let BasicValueEnum::IntValue(v) = self { v @@ -354,6 +366,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_float_value(self) -> FloatValue<'ctx> { if let BasicValueEnum::FloatValue(v) = self { v @@ -362,6 +375,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_pointer_value(self) -> PointerValue<'ctx> { if let BasicValueEnum::PointerValue(v) = self { v @@ -370,6 +384,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_struct_value(self) -> StructValue<'ctx> { if let BasicValueEnum::StructValue(v) = self { v @@ -378,6 +393,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_vector_value(self) -> VectorValue<'ctx> { if let BasicValueEnum::VectorValue(v) = self { v @@ -386,6 +402,7 @@ impl<'ctx> BasicValueEnum<'ctx> { } } + #[track_caller] pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> { if let BasicValueEnum::ScalableVectorValue(v) = self { v @@ -417,6 +434,7 @@ impl<'ctx> AggregateValueEnum<'ctx> { matches!(self, AggregateValueEnum::StructValue(_)) } + #[track_caller] pub fn into_array_value(self) -> ArrayValue<'ctx> { if let AggregateValueEnum::ArrayValue(v) = self { v @@ -425,6 +443,7 @@ impl<'ctx> AggregateValueEnum<'ctx> { } } + #[track_caller] pub fn into_struct_value(self) -> StructValue<'ctx> { if let AggregateValueEnum::StructValue(v) = self { v @@ -498,6 +517,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { matches!(self, BasicMetadataValueEnum::MetadataValue(_)) } + #[track_caller] pub fn into_array_value(self) -> ArrayValue<'ctx> { if let BasicMetadataValueEnum::ArrayValue(v) = self { v @@ -506,6 +526,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_int_value(self) -> IntValue<'ctx> { if let BasicMetadataValueEnum::IntValue(v) = self { v @@ -514,6 +535,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_float_value(self) -> FloatValue<'ctx> { if let BasicMetadataValueEnum::FloatValue(v) = self { v @@ -522,6 +544,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_pointer_value(self) -> PointerValue<'ctx> { if let BasicMetadataValueEnum::PointerValue(v) = self { v @@ -530,6 +553,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_struct_value(self) -> StructValue<'ctx> { if let BasicMetadataValueEnum::StructValue(v) = self { v @@ -538,6 +562,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_vector_value(self) -> VectorValue<'ctx> { if let BasicMetadataValueEnum::VectorValue(v) = self { v @@ -546,6 +571,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> { if let BasicMetadataValueEnum::ScalableVectorValue(v) = self { v @@ -554,6 +580,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { } } + #[track_caller] pub fn into_metadata_value(self) -> MetadataValue<'ctx> { if let BasicMetadataValueEnum::MetadataValue(v) = self { v From b8d81bfe7224d1ee689a8b777d6f5ba9a869b98b Mon Sep 17 00:00:00 2001 From: Daniel Kolsoi Date: Fri, 25 Apr 2025 02:59:37 -0400 Subject: [PATCH 13/26] Update versions --- .github/workflows/test.yml | 2 +- Cargo.toml | 24 ++++++++++-------------- internal_macros/Cargo.toml | 4 ++-- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 607fd542aef..676132b2bfb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CARGO_TERM_COLOR: always - DOC_LLVM_FEATURE: llvm18-0 + DOC_LLVM_FEATURE: llvm18-1 DOC_LLVM_VERSION: "18.1" DOC_PATH: target/doc diff --git a/Cargo.toml b/Cargo.toml index 077c2bd6300..e1703704092 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "inkwell" -version = "0.5.0" +version = "0.6.0" authors = ["Daniel Kolsoi "] description = "Inkwell aims to help you pen your own programming languages by safely wrapping llvm-sys." documentation = "https://thedan64.github.io/inkwell/" @@ -128,21 +128,17 @@ experimental = ["static-alloc"] nightly = ["inkwell_internals/nightly"] [dependencies] -inkwell_internals = { path = "./internal_macros", version = "0.10.0" } +inkwell_internals = { path = "./internal_macros", version = "0.11.0" } -llvm-sys-40 = { package = "llvm-sys", version = "40.4", optional = true } -llvm-sys-50 = { package = "llvm-sys", version = "50.4", optional = true } -llvm-sys-60 = { package = "llvm-sys", version = "60.6", optional = true } -llvm-sys-70 = { package = "llvm-sys", version = "70.4", optional = true } llvm-sys-80 = { package = "llvm-sys", version = "80.3", optional = true } -llvm-sys-90 = { package = "llvm-sys", version = "90.2.1", optional = true } -llvm-sys-100 = { package = "llvm-sys", version = "100.2.3", optional = true } -llvm-sys-110 = { package = "llvm-sys", version = "110.0.3", optional = true } -llvm-sys-120 = { package = "llvm-sys", version = "120.2.4", optional = true } -llvm-sys-130 = { package = "llvm-sys", version = "130.0.4", optional = true } -llvm-sys-140 = { package = "llvm-sys", version = "140.0.2", optional = true } -llvm-sys-150 = { package = "llvm-sys", version = "150.0.3", optional = true } -llvm-sys-160 = { package = "llvm-sys", version = "160.1.0", optional = true } +llvm-sys-90 = { package = "llvm-sys", version = "90.2.2", optional = true } +llvm-sys-100 = { package = "llvm-sys", version = "100.2.4", optional = true } +llvm-sys-110 = { package = "llvm-sys", version = "110.0.4", optional = true } +llvm-sys-120 = { package = "llvm-sys", version = "120.3.2", optional = true } +llvm-sys-130 = { package = "llvm-sys", version = "130.1.2", optional = true } +llvm-sys-140 = { package = "llvm-sys", version = "140.1.3", optional = true } +llvm-sys-150 = { package = "llvm-sys", version = "150.2.1", optional = true } +llvm-sys-160 = { package = "llvm-sys", version = "160.2.1", optional = true } llvm-sys-170 = { package = "llvm-sys", version = "170.2.0", optional = true } llvm-sys-181 = { package = "llvm-sys", version = "181.2.0", optional = true } diff --git a/internal_macros/Cargo.toml b/internal_macros/Cargo.toml index c49467c5227..0367b41a755 100644 --- a/internal_macros/Cargo.toml +++ b/internal_macros/Cargo.toml @@ -1,12 +1,12 @@ [package] authors = ["Daniel Kolsoi "] description = "Internal macro crate for inkwell" -edition = "2021" +edition = "2024" license = "Apache-2.0" name = "inkwell_internals" readme = "README.md" repository = "https://github.com/TheDan64/inkwell" -version = "0.10.0" +version = "0.11.0" [dependencies] proc-macro2 = "1.0" From d7e646b17dd55d417fef09a80e761bd8404c210b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 03:16:55 -0400 Subject: [PATCH 14/26] Update thiserror requirement from 1.0.48 to 2.0.11 (#564) Updates the requirements on [thiserror](https://github.com/dtolnay/thiserror) to permit the latest version. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.48...2.0.11) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Dan Kolsoi --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e1703704092..c6d7dd9b0ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -145,7 +145,7 @@ llvm-sys-181 = { package = "llvm-sys", version = "181.2.0", optional = true } either = "1.5" libc = "0.2" once_cell = "1.16" -thiserror = "1.0.48" +thiserror = "2.0.11" static-alloc = { version = "0.2", optional = true } serde = { version = "1.0", default-features = false, features = [ From e3369e70242df85978c109c75d5f57a5032d7b80 Mon Sep 17 00:00:00 2001 From: z combinator <49233942+hsqStephenZhang@users.noreply.github.com> Date: Fri, 30 May 2025 06:33:40 +0200 Subject: [PATCH 15/26] chore: fix warning of elided_lifetimes_in_paths in examples (#590) Signed-off-by: hsqStephenZhang --- README.md | 2 +- examples/jit.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44afd839fd5..fc8521d68d8 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ struct CodeGen<'ctx> { } impl<'ctx> CodeGen<'ctx> { - fn jit_compile_sum(&self) -> Option> { + fn jit_compile_sum(&self) -> Option> { let i64_type = self.context.i64_type(); let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); let function = self.module.add_function("sum", fn_type, None); diff --git a/examples/jit.rs b/examples/jit.rs index eb220a688e5..97556844840 100644 --- a/examples/jit.rs +++ b/examples/jit.rs @@ -20,7 +20,7 @@ struct CodeGen<'ctx> { } impl<'ctx> CodeGen<'ctx> { - fn jit_compile_sum(&self) -> Option> { + fn jit_compile_sum(&self) -> Option> { let i64_type = self.context.i64_type(); let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); let function = self.module.add_function("sum", fn_type, None); From eb31b0198c4919f9c527d1729847f46ef6a75438 Mon Sep 17 00:00:00 2001 From: Michael Yang Date: Fri, 6 Jun 2025 04:29:48 +0100 Subject: [PATCH 16/26] Add `get_bit_width` method for float type (#589) * feat: add `get_bit_width` method for float type * test: add `test_float_type` * fix: change bfloat to only llvm11+ --------- Co-authored-by: Dan Kolsoi --- src/types/float_type.rs | 37 ++++++++++++++++++++++++++++++++++++- tests/all/test_types.rs | 19 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/types/float_type.rs b/src/types/float_type.rs index 2fe29876fde..3ac810f5872 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMConstReal, LLVMConstRealOfStringAndSize}; +use llvm_sys::core::{LLVMConstReal, LLVMConstRealOfStringAndSize, LLVMGetTypeKind}; use llvm_sys::execution_engine::LLVMCreateGenericValueOfFloat; use llvm_sys::prelude::LLVMTypeRef; @@ -254,6 +254,41 @@ impl<'ctx> FloatType<'ctx> { self.float_type.ptr_type(address_space) } + /// Gets the bit width of a `FloatType`. + /// + /// # Example + /// ```no_run + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let f128_type = context.f128_type(); + /// + /// assert_eq!(f128_type.get_bit_width(), 128); + /// ``` + pub fn get_bit_width(self) -> u32 { + let type_kind = unsafe { LLVMGetTypeKind(self.as_type_ref()) }; + + match type_kind { + llvm_sys::LLVMTypeKind::LLVMHalfTypeKind => 16, + #[cfg(any( + feature = "llvm11-0", + feature = "llvm12-0", + feature = "llvm13-0", + feature = "llvm14-0", + feature = "llvm15-0", + feature = "llvm16-0", + feature = "llvm17-0", + feature = "llvm18-1" + ))] + llvm_sys::LLVMTypeKind::LLVMBFloatTypeKind => 16, + llvm_sys::LLVMTypeKind::LLVMFloatTypeKind => 32, + llvm_sys::LLVMTypeKind::LLVMDoubleTypeKind => 64, + llvm_sys::LLVMTypeKind::LLVMX86_FP80TypeKind => 80, + llvm_sys::LLVMTypeKind::LLVMFP128TypeKind | llvm_sys::LLVMTypeKind::LLVMPPC_FP128TypeKind => 128, + _ => unreachable!(), + } + } + /// Print the definition of a `FloatType` to `LLVMString`. pub fn print_to_string(self) -> LLVMString { self.float_type.print_to_string() diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index e9a0b4f0543..d2679b9c845 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -489,6 +489,25 @@ fn test_const_zero() { ); } +#[test] +fn test_float_type() { + let context = Context::create(); + + let f16_type = context.f16_type(); + let f32_type = context.f32_type(); + let f64_type = context.f64_type(); + let f128_type = context.f128_type(); + let x86_f80_type = context.x86_f80_type(); + let ppc_f128_type = context.ppc_f128_type(); + + assert_eq!(f16_type.get_bit_width(), 16); + assert_eq!(f32_type.get_bit_width(), 32); + assert_eq!(f64_type.get_bit_width(), 64); + assert_eq!(f128_type.get_bit_width(), 128); + assert_eq!(x86_f80_type.get_bit_width(), 80); + assert_eq!(ppc_f128_type.get_bit_width(), 128); +} + #[test] fn test_vec_type() { let context = Context::create(); From 50c16a644c6f5d5b41c27cc1620d63097cad43dd Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 9 Aug 2025 12:55:18 +0800 Subject: [PATCH 17/26] Preliminary LLVM 19/20 support (#557) * Update Cargo.toml * LLVM 19 preliminary build * rename llvm19-0 to llvm-19-1 * add llvm 19.1 to test matrix * update the bindings to use 19.1 instead of 19 * use sagudev instead of KyleMayes for LLVM 19.1 support * fixup! use sagudev instead of KyleMayes for LLVM 19.1 support * fix for metadata kind id * add llvm 20 support * fix for LLVMSetNUW * fixup! fix for LLVMSetNUW * add llvm 20.1 to ci * fixup! fixup! fix for LLVMSetNUW * fixup! fixup! fixup! fix for LLVMSetNUW * fixup! fixup! fixup! fixup! fix for LLVMSetNUW * add llvm20-1 back to feature detection * fixup! add llvm20-1 back to feature detection * add missing stuff for llvm 20 * fixup! add missing stuff for llvm 20 * try to get llvm from LLVM apt source instead * fixup! try to get llvm from LLVM apt source instead * add libpolly back * disable test_get_decl_va_copy for LLVM 19 and up for now * fix first metadata kind id for llvm 20 * fix test for llvm 20 * try out nextest * make sure jit example can run * improve Kaleidoscope example a little bit to add eval mode rather than repl * feat: support LLVM 19 and 20 in debug info * Clippy fixes * Clippy fixes --------- Co-authored-by: Dan Kolsoi Co-authored-by: Steve Fan --- .github/workflows/test.yml | 149 +++++++++++------- Cargo.toml | 15 ++ README.md | 2 +- examples/jit.rs | 2 +- .../implementation_typed_pointers.rs | 5 +- examples/kaleidoscope/main.rs | 97 +++++++----- internal_macros/src/cfg.rs | 2 +- src/attributes.rs | 2 +- src/builder.rs | 46 ++++-- src/context.rs | 88 +++++++---- src/debug_info.rs | 137 ++++++++++++++-- src/lib.rs | 24 ++- src/module.rs | 18 ++- src/types/array_type.rs | 4 +- src/types/enums.rs | 91 +++++++---- src/types/float_type.rs | 4 +- src/types/fn_type.rs | 4 +- src/types/int_type.rs | 4 +- src/types/ptr_type.rs | 4 +- src/types/scalable_vec_type.rs | 4 +- src/types/struct_type.rs | 4 +- src/types/traits.rs | 4 +- src/types/vec_type.rs | 4 +- src/values/enums.rs | 66 ++++---- src/values/float_value.rs | 11 +- src/values/int_value.rs | 33 +++- src/values/metadata_value.rs | 4 + src/values/mod.rs | 10 +- src/values/traits.rs | 2 +- tests/all/main.rs | 7 +- tests/all/test_builder.rs | 36 +++-- tests/all/test_debug_info.rs | 72 ++++++--- tests/all/test_execution_engine.rs | 4 +- tests/all/test_intrinsics.rs | 7 +- tests/all/test_targets.rs | 12 +- tests/all/test_types.rs | 32 +++- tests/all/test_values.rs | 111 +++++++++---- 37 files changed, 796 insertions(+), 325 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 676132b2bfb..e6d5c29aba9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,6 @@ name: Test Suite and Doc -on: [push, pull_request] +on: [ push, pull_request ] env: CARGO_TERM_COLOR: always @@ -13,75 +13,104 @@ jobs: name: Linting runs-on: ubuntu-latest steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Install Rust Stable - uses: dtolnay/rust-toolchain@stable - - name: Install typos - uses: taiki-e/install-action@typos - - name: Check typos - run: typos . - - name: Check code formatting - run: cargo fmt --check + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Install Rust Stable + uses: dtolnay/rust-toolchain@stable + - name: Install typos + uses: taiki-e/install-action@typos + - name: Check typos + run: typos . + - name: Check code formatting + run: cargo fmt --check tests: name: "LLVM ${{ matrix.llvm-version[0] }}: ${{ matrix.os }}" runs-on: ${{ matrix.os }} strategy: matrix: llvm-version: - - ["8.0", "8-0"] - - ["9.0", "9-0"] - - ["10.0", "10-0"] - - ["11.0", "11-0"] - - ["12.0", "12-0"] - - ["13.0", "13-0"] - - ["14.0", "14-0"] - - ["15.0", "15-0"] - - ["16.0", "16-0"] - - ["17.0", "17-0"] - - ["18.1", "18-1"] + - [ "8.0", "8-0" ] + - [ "9.0", "9-0" ] + - [ "10.0", "10-0" ] + - [ "11.0", "11-0" ] + - [ "12.0", "12-0" ] + - [ "13.0", "13-0" ] + - [ "14.0", "14-0" ] + - [ "15.0", "15-0" ] + - [ "16.0", "16-0" ] + - [ "17.0", "17-0" ] + - [ "18.1", "18-1" ] + - [ "19.1", "19-1", "19" ] + - [ "20.1", "20-1", "20" ] include: - - os: ubuntu-22.04 + - os: ubuntu-22.04 steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Install Dependencies - run: sudo apt update && sudo apt install -y libtinfo5 - - name: Install LLVM and Clang (LLVM >= 7.1) - uses: KyleMayes/install-llvm-action@v2 - with: - version: ${{ matrix.llvm-version[0] }} - - name: llvm-config - run: llvm-config --version --bindir --libdir - - name: Install Rust Stable - uses: dtolnay/rust-toolchain@stable - - name: cargo clippy - run: cargo clippy --tests --features llvm${{ matrix.llvm-version[1] }} -- -D warnings - - name: Build - run: cargo build --release --features llvm${{ matrix.llvm-version[1] }} --verbose - - name: Run tests - run: cargo test --release --features llvm${{ matrix.llvm-version[1] }} --verbose - - name: Build example - run: cargo build --example kaleidoscope --features llvm${{ matrix.llvm-version[1] }} --verbose + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Install Dependencies + run: sudo apt update && sudo apt install -y libtinfo5 + - name: Install LLVM and Clang (LLVM >= 19.1) + if: ${{ matrix.llvm-version[0] >= 19 }} + run: | + sudo apt install --no-install-recommends -y lsb-release wget software-properties-common gnupg + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{ matrix.llvm-version[2] }} + sudo apt-get update + sudo apt install --no-install-recommends -y libllvm${{ matrix.llvm-version[2] }} \ + llvm-${{ matrix.llvm-version[2] }} \ + llvm-${{ matrix.llvm-version[2] }}-dev \ + llvm-${{ matrix.llvm-version[2] }}-runtime \ + libpolly-${{ matrix.llvm-version[2] }}-dev + sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-${{ matrix.llvm-version[2] }} 10 + - name: Install LLVM and Clang (7.1 <= LLVM <= 19) + uses: KyleMayes/install-llvm-action@v2 + if: ${{ matrix.llvm-version[0] > 7 && matrix.llvm-version[0] <= 19 }} + with: + version: ${{ matrix.llvm-version[0] }} + - name: Install LLVM and Clang (LLVM <= 7) + uses: KyleMayes/install-llvm-action@v1 + if: ${{ matrix.llvm-version[0] <= 7 }} + with: + version: ${{ matrix.llvm-version[0] }} + - name: llvm-config + run: llvm-config --version --bindir --libdir + - name: Install Rust Stable + uses: moonrepo/setup-rust@v1 + with: + bins: cargo-nextest + - name: cargo clippy + run: cargo clippy --tests --features llvm${{ matrix.llvm-version[1] }} -- -D warnings + - name: Build + run: cargo build --release --features llvm${{ matrix.llvm-version[1] }} --verbose + - name: Run tests + run: | + cargo nextest run --release --features llvm${{ matrix.llvm-version[1] }} --verbose + cargo test --doc --release --features llvm${{ matrix.llvm-version[1] }} --verbose + - name: Build examples and run JIT for verification + run: | + cargo run --example kaleidoscope --features llvm${{ matrix.llvm-version[1] }} --verbose -- --dl --dp --dc -e "(1 + 2 + 3) / (2 + 3)" + cargo run --example jit --features llvm${{ matrix.llvm-version[1] }} --verbose + cargo run --example jit --features llvm${{ matrix.llvm-version[1] }} --verbose --release doc: name: Documentation runs-on: ubuntu-22.04 - needs: [lint, tests] + needs: [ lint, tests ] if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: - - uses: actions/checkout@v4 - - uses: KyleMayes/install-llvm-action@v2 - with: - version: ${{ env.DOC_LLVM_VERSION }} - - name: Install Rust Nightly - uses: dtolnay/rust-toolchain@nightly - - name: Build Documentation - run: cargo +nightly doc --features ${{ env.DOC_LLVM_FEATURE }},nightly --verbose - - name: Doc Index Page Redirection - run: echo '' > ${{ env.DOC_PATH }}/index.html - - name: Deploy Documentation - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ${{ env.DOC_PATH }} - force_orphan: true + - uses: actions/checkout@v4 + - uses: KyleMayes/install-llvm-action@v2 + with: + version: ${{ env.DOC_LLVM_VERSION }} + - name: Install Rust Nightly + uses: dtolnay/rust-toolchain@nightly + - name: Build Documentation + run: cargo +nightly doc --features ${{ env.DOC_LLVM_FEATURE }},nightly --verbose + - name: Doc Index Page Redirection + run: echo '' > ${{ env.DOC_PATH }}/index.html + - name: Deploy Documentation + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ${{ env.DOC_PATH }} + force_orphan: true diff --git a/Cargo.toml b/Cargo.toml index c6d7dd9b0ef..d0106e316b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ llvm15-0 = ["llvm-sys-150"] llvm16-0 = ["llvm-sys-160"] llvm17-0 = ["llvm-sys-170"] llvm18-1 = ["llvm-sys-181"] +llvm19-1 = ["llvm-sys-191"] +llvm20-1 = ["llvm-sys-201"] # Don't link against LLVM libraries. This is useful if another dependency is # installing LLVM. See llvm-sys for more details. We can't enable a single @@ -44,6 +46,8 @@ llvm15-0-no-llvm-linking = ["llvm15-0", "llvm-sys-150/no-llvm-linking"] llvm16-0-no-llvm-linking = ["llvm16-0", "llvm-sys-160/no-llvm-linking"] llvm17-0-no-llvm-linking = ["llvm17-0", "llvm-sys-170/no-llvm-linking"] llvm18-1-no-llvm-linking = ["llvm18-1", "llvm-sys-181/no-llvm-linking"] +llvm19-1-no-llvm-linking = ["llvm19-1", "llvm-sys-191/no-llvm-linking"] +llvm20-1-no-llvm-linking = ["llvm20-1", "llvm-sys-201/no-llvm-linking"] # Linking preference. # If none of these are enabled, it defaults to force static linking. @@ -56,6 +60,8 @@ llvm15-0-force-dynamic = ["llvm15-0", "llvm-sys-150/force-dynamic"] llvm16-0-force-dynamic = ["llvm16-0", "llvm-sys-160/force-dynamic"] llvm17-0-force-dynamic = ["llvm17-0", "llvm-sys-170/force-dynamic"] llvm18-1-force-dynamic = ["llvm18-1", "llvm-sys-181/force-dynamic"] +llvm19-1-force-dynamic = ["llvm19-1", "llvm-sys-191/force-dynamic"] +llvm20-1-force-dynamic = ["llvm20-1", "llvm-sys-201/force-dynamic"] # Prefer dynamic linking against LLVM libraries. See llvm-sys for more details llvm12-0-prefer-dynamic = ["llvm12-0", "llvm-sys-120/prefer-dynamic"] @@ -65,6 +71,8 @@ llvm15-0-prefer-dynamic = ["llvm15-0", "llvm-sys-150/prefer-dynamic"] llvm16-0-prefer-dynamic = ["llvm16-0", "llvm-sys-160/prefer-dynamic"] llvm17-0-prefer-dynamic = ["llvm17-0", "llvm-sys-170/prefer-dynamic"] llvm18-1-prefer-dynamic = ["llvm18-1", "llvm-sys-181/prefer-dynamic"] +llvm19-1-prefer-dynamic = ["llvm19-1", "llvm-sys-191/prefer-dynamic"] +llvm20-1-prefer-dynamic = ["llvm20-1", "llvm-sys-201/prefer-dynamic"] # Force static linking against LLVM libraries. See llvm-sys for more details llvm12-0-force-static = ["llvm12-0", "llvm-sys-120/force-static"] @@ -74,6 +82,8 @@ llvm15-0-force-static = ["llvm15-0", "llvm-sys-150/force-static"] llvm16-0-force-static = ["llvm16-0", "llvm-sys-160/force-static"] llvm17-0-force-static = ["llvm17-0", "llvm-sys-170/force-static"] llvm18-1-force-static = ["llvm18-1", "llvm-sys-181/force-static"] +llvm19-1-force-static = ["llvm19-1", "llvm-sys-191/force-static"] +llvm20-1-force-static = ["llvm20-1", "llvm-sys-201/force-static"] # Prefer static linking against LLVM libraries. See llvm-sys for more details llvm12-0-prefer-static = ["llvm12-0", "llvm-sys-120/prefer-static"] @@ -83,6 +93,8 @@ llvm15-0-prefer-static = ["llvm15-0", "llvm-sys-150/prefer-static"] llvm16-0-prefer-static = ["llvm16-0", "llvm-sys-160/prefer-static"] llvm17-0-prefer-static = ["llvm17-0", "llvm-sys-170/prefer-static"] llvm18-1-prefer-static = ["llvm18-1", "llvm-sys-181/prefer-static"] +llvm19-1-prefer-static = ["llvm19-1", "llvm-sys-191/prefer-static"] +llvm20-1-prefer-static = ["llvm20-1", "llvm-sys-201/prefer-static"] # Don't force linking to libffi on non-windows platforms. Without this feature # inkwell always links to libffi on non-windows platforms. @@ -141,6 +153,8 @@ llvm-sys-150 = { package = "llvm-sys", version = "150.2.1", optional = true } llvm-sys-160 = { package = "llvm-sys", version = "160.2.1", optional = true } llvm-sys-170 = { package = "llvm-sys", version = "170.2.0", optional = true } llvm-sys-181 = { package = "llvm-sys", version = "181.2.0", optional = true } +llvm-sys-191 = { package = "llvm-sys", version = "191.0.0", optional = true } +llvm-sys-201 = { package = "llvm-sys", version = "201.0.0", optional = true } either = "1.5" libc = "0.2" @@ -153,6 +167,7 @@ serde = { version = "1.0", default-features = false, features = [ ], optional = true } [dev-dependencies] +gumdrop = "0.8.1" regex = "1" [badges] diff --git a/README.md b/README.md index fc8521d68d8..5f7a98f080f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Inkwell aims to help you pen your own programming languages by safely wrapping l ## Requirements * Rust 1.56+ (Stable, Beta, or Nightly) -* One of LLVM 8-18 +* One of LLVM 8-18 (WIP: 19 and 20 are barely supported without extensive tests) ## Usage diff --git a/examples/jit.rs b/examples/jit.rs index 97556844840..acef709318f 100644 --- a/examples/jit.rs +++ b/examples/jit.rs @@ -19,7 +19,7 @@ struct CodeGen<'ctx> { execution_engine: ExecutionEngine<'ctx>, } -impl<'ctx> CodeGen<'ctx> { +impl CodeGen<'_> { fn jit_compile_sum(&self) -> Option> { let i64_type = self.context.i64_type(); let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); diff --git a/examples/kaleidoscope/implementation_typed_pointers.rs b/examples/kaleidoscope/implementation_typed_pointers.rs index 5e9ca8bfb0b..7249442a069 100644 --- a/examples/kaleidoscope/implementation_typed_pointers.rs +++ b/examples/kaleidoscope/implementation_typed_pointers.rs @@ -205,7 +205,7 @@ impl<'a> Lexer<'a> { } } -impl<'a> Iterator for Lexer<'a> { +impl Iterator for Lexer<'_> { type Item = Token; /// Lexes the next `Token` and returns it. @@ -1130,8 +1130,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { /// Compiles the specified `Prototype` into an extern LLVM `FunctionValue`. fn compile_prototype(&self, proto: &Prototype) -> Result, &'static str> { let ret_type = self.context.f64_type(); - let args_types = std::iter::repeat(ret_type) - .take(proto.args.len()) + let args_types = std::iter::repeat_n(ret_type, proto.args.len()) .map(|f| f.into()) .collect::>(); let args_types = args_types.as_slice(); diff --git a/examples/kaleidoscope/main.rs b/examples/kaleidoscope/main.rs index ecde85f5bc0..04e34484ed1 100644 --- a/examples/kaleidoscope/main.rs +++ b/examples/kaleidoscope/main.rs @@ -6,11 +6,11 @@ //! This example is supposed to be ran as a executable, which launches a REPL. //! The source code is in the following order: //! - `implementation_typed_pointers.rs`: -//! Lexer, -//! Parser, -//! Compiler. +//! - Lexer, +//! - Parser, +//! - Compiler. //! - `main.rs`: -//! Program. +//! - Program. //! //! Both the `Parser` and the `Compiler` may fail, in which case they would return //! an error represented by `Result`, for easier error reporting. @@ -34,6 +34,8 @@ use inkwell_internals::llvm_versions; mod implementation_typed_pointers; pub use implementation_typed_pointers::*; +use gumdrop::Options; + // ====================================================================================== // PROGRAM ============================================================================== // ====================================================================================== @@ -55,7 +57,7 @@ pub extern "C" fn putchard(x: f64) -> f64 { #[no_mangle] pub extern "C" fn printd(x: f64) -> f64 { - println!("{}", x); + println!("{x}"); x } @@ -110,40 +112,34 @@ fn run_passes_on(module: &Module) { /// Entry point of the program; acts as a REPL. pub fn main() { - let mut display_lexer_output = false; - let mut display_parser_output = false; - let mut display_compiler_output = false; - - for arg in std::env::args() { - match arg.as_str() { - "--dl" => display_lexer_output = true, - "--dp" => display_parser_output = true, - "--dc" => display_compiler_output = true, - _ => (), - } + #[derive(Debug, Options)] + struct Opts { + #[options(help = "print help message")] + help: bool, + #[options(long = "dl", no_short, help = "Display lexer output")] + display_lexer_output: bool, + #[options(long = "dp", no_short, help = "Display parser output")] + display_parser_output: bool, + #[options(long = "dc", no_short, help = "Display compiler output")] + display_compiler_output: bool, + #[options(short = "e", help = "Display compiler output")] + eval: Option, } + let Opts { + display_lexer_output, + display_parser_output, + display_compiler_output, + eval, + .. + } = Opts::parse_args_default_or_exit(); + let context = Context::create(); let builder = context.create_builder(); let mut previous_exprs = Vec::new(); - loop { - println!(); - print_flush!("?> "); - - // Read input from stdin - let mut input = String::new(); - io::stdin() - .read_line(&mut input) - .expect("Could not read from standard input."); - - if input.starts_with("exit") || input.starts_with("quit") { - break; - } else if input.chars().all(char::is_whitespace) { - continue; - } - + let mut compute = |input: String| { // Build precedence map let mut prec = HashMap::with_capacity(6); @@ -178,7 +174,7 @@ pub fn main() { if is_anon { println!("-> Expression parsed: \n{:?}\n", fun.body); } else { - println!("-> Function parsed: \n{:?}\n", fun); + println!("-> Function parsed: \n{fun:?}\n"); } } @@ -192,14 +188,14 @@ pub fn main() { (function, is_anon) }, Err(err) => { - println!("!> Error compiling function: {}", err); - continue; + println!("!> Error compiling function: {err}"); + return; }, } }, Err(err) => { - println!("!> Error parsing expression: {}", err); - continue; + println!("!> Error parsing expression: {err}"); + return; }, }; @@ -218,8 +214,8 @@ pub fn main() { let compiled_fn = match maybe_fn { Ok(f) => f, Err(err) => { - println!("!> Error during execution: {:?}", err); - continue; + println!("!> Error during execution: {err:?}"); + return; }, }; @@ -227,5 +223,28 @@ pub fn main() { println!("=> {}", compiled_fn.call()); } } + }; + + if let Some(input) = eval { + compute(format!("{input}\n")); + } else { + loop { + println!(); + print_flush!("?> "); + + // Read input from stdin + let mut input = String::new(); + io::stdin() + .read_line(&mut input) + .expect("Could not read from standard input."); + + if input.starts_with("exit") || input.starts_with("quit") { + break; + } else if input.chars().all(char::is_whitespace) { + continue; + } + + compute(input); + } } } diff --git a/internal_macros/src/cfg.rs b/internal_macros/src/cfg.rs index 9d5b09dd632..4437c84635c 100644 --- a/internal_macros/src/cfg.rs +++ b/internal_macros/src/cfg.rs @@ -10,7 +10,7 @@ use syn::{Lit, RangeLimits}; // This array should match the LLVM features in the top level Cargo manifest const FEATURE_VERSIONS: &[&str] = &[ "llvm8-0", "llvm9-0", "llvm10-0", "llvm11-0", "llvm12-0", "llvm13-0", "llvm14-0", "llvm15-0", "llvm16-0", - "llvm17-0", "llvm18-1", + "llvm17-0", "llvm18-1", "llvm19-1", "llvm20-1" ]; pub struct VersionRange { diff --git a/src/attributes.rs b/src/attributes.rs index 888dcf93544..17e0997202c 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -342,7 +342,7 @@ impl Attribute { /// assert_ne!(type_attribute.get_type_value(), context.i64_type().as_any_type_enum()); /// ``` #[llvm_versions(12..)] - pub fn get_type_value(&self) -> AnyTypeEnum { + pub fn get_type_value(&self) -> AnyTypeEnum<'_> { assert!(self.is_type()); // FIXME: SubTypes unsafe { AnyTypeEnum::new(LLVMGetTypeAttributeValue(self.attribute)) } diff --git a/src/builder.rs b/src/builder.rs index dfcd6c50112..b7c7348a4bd 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -9,18 +9,31 @@ use llvm_sys::core::{ LLVMBuildCondBr, LLVMBuildExactSDiv, LLVMBuildExtractElement, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPCast, LLVMBuildFPExt, LLVMBuildFPToSI, LLVMBuildFPToUI, LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub, LLVMBuildFence, LLVMBuildFree, LLVMBuildGlobalString, - LLVMBuildGlobalStringPtr, LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue, - LLVMBuildIntCast, LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad, - LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd, - LLVMBuildNUWMul, LLVMBuildNUWNeg, LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, - LLVMBuildPointerCast, LLVMBuildPtrToInt, LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, - LLVMBuildSExt, LLVMBuildSExtOrBitCast, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl, - LLVMBuildShuffleVector, LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast, - LLVMBuildUDiv, LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, - LLVMBuildZExtOrBitCast, LLVMClearInsertionPosition, LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMInsertIntoBuilder, + LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue, LLVMBuildIntCast, + LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad, LLVMBuildMalloc, + LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd, LLVMBuildNUWMul, + LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildPtrToInt, + LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, LLVMBuildSExt, LLVMBuildSExtOrBitCast, + LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl, LLVMBuildShuffleVector, LLVMBuildStore, + LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast, LLVMBuildUDiv, LLVMBuildUIToFP, + LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, LLVMBuildZExtOrBitCast, + LLVMClearInsertionPosition, LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMInsertIntoBuilder, LLVMInsertIntoBuilderWithName, LLVMPositionBuilder, LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore, LLVMSetCleanup, }; + +#[llvm_versions(..20)] +use llvm_sys::core::LLVMBuildGlobalStringPtr; + +#[llvm_versions(20..)] +use llvm_sys::core::LLVMBuildGlobalString as LLVMBuildGlobalStringPtr; + +#[llvm_versions(..17)] +use llvm_sys::core::LLVMBuildNUWNeg; + +#[llvm_versions(17..)] +use llvm_sys::core::LLVMSetNUW; + #[llvm_versions(..=14)] #[allow(deprecated)] use llvm_sys::core::{LLVMBuildCall, LLVMBuildInvoke}; @@ -2882,12 +2895,27 @@ impl<'ctx> Builder<'ctx> { } // SubType: (&self, value: &IntValue, name) -> IntValue { + #[llvm_versions(..17)] pub fn build_int_nuw_neg>(&self, value: T, name: &str) -> Result { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNUWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + unsafe { Ok(T::new(value)) } + } + + // SubType: (&self, value: &IntValue, name) -> IntValue { + #[llvm_versions(17..)] + pub fn build_int_nuw_neg>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } + let c_string = to_c_str(name); + let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + unsafe { + LLVMSetNUW(value, true.into()); + } unsafe { Ok(T::new(value)) } } diff --git a/src/context.rs b/src/context.rs index e11fc4474fc..39fcfce1830 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,14 +14,21 @@ use llvm_sys::core::LLVMMetadataTypeInContext; #[cfg(not(feature = "typed-pointers"))] use llvm_sys::core::LLVMPointerTypeInContext; use llvm_sys::core::{ - LLVMAppendBasicBlockInContext, LLVMConstStringInContext, LLVMConstStructInContext, LLVMContextCreate, - LLVMContextDispose, LLVMContextSetDiagnosticHandler, LLVMCreateBuilderInContext, LLVMCreateEnumAttribute, - LLVMCreateStringAttribute, LLVMDoubleTypeInContext, LLVMFP128TypeInContext, LLVMFloatTypeInContext, - LLVMGetGlobalContext, LLVMGetMDKindIDInContext, LLVMHalfTypeInContext, LLVMInsertBasicBlockInContext, - LLVMInt16TypeInContext, LLVMInt1TypeInContext, LLVMInt32TypeInContext, LLVMInt64TypeInContext, - LLVMInt8TypeInContext, LLVMIntTypeInContext, LLVMModuleCreateWithNameInContext, LLVMPPCFP128TypeInContext, - LLVMStructCreateNamed, LLVMStructTypeInContext, LLVMVoidTypeInContext, LLVMX86FP80TypeInContext, + LLVMAppendBasicBlockInContext, LLVMConstStructInContext, LLVMContextCreate, LLVMContextDispose, + LLVMContextSetDiagnosticHandler, LLVMCreateBuilderInContext, LLVMCreateEnumAttribute, LLVMCreateStringAttribute, + LLVMDoubleTypeInContext, LLVMFP128TypeInContext, LLVMFloatTypeInContext, LLVMGetGlobalContext, + LLVMGetMDKindIDInContext, LLVMHalfTypeInContext, LLVMInsertBasicBlockInContext, LLVMInt16TypeInContext, + LLVMInt1TypeInContext, LLVMInt32TypeInContext, LLVMInt64TypeInContext, LLVMInt8TypeInContext, LLVMIntTypeInContext, + LLVMModuleCreateWithNameInContext, LLVMPPCFP128TypeInContext, LLVMStructCreateNamed, LLVMStructTypeInContext, + LLVMVoidTypeInContext, LLVMX86FP80TypeInContext, }; + +#[llvm_versions(..19)] +use llvm_sys::core::LLVMConstStringInContext; + +#[llvm_versions(19..)] +use llvm_sys::core::LLVMConstStringInContext2; + #[allow(deprecated)] use llvm_sys::core::{LLVMMDNodeInContext, LLVMMDStringInContext}; use llvm_sys::ir_reader::LLVMParseIRInContext; @@ -361,6 +368,7 @@ impl ContextImpl { unsafe { Attribute::new(LLVMCreateTypeAttribute(self.0, kind_id, type_ref.as_type_ref())) } } + #[llvm_versions(..19)] fn const_string<'ctx>(&self, string: &[u8], null_terminated: bool) -> ArrayValue<'ctx> { unsafe { ArrayValue::new(LLVMConstStringInContext( @@ -372,6 +380,18 @@ impl ContextImpl { } } + #[llvm_versions(19..)] + fn const_string<'ctx>(&self, string: &[u8], null_terminated: bool) -> ArrayValue<'ctx> { + unsafe { + ArrayValue::new(LLVMConstStringInContext2( + self.0, + string.as_ptr() as *const ::libc::c_char, + string.len(), + !null_terminated as i32, + )) + } + } + fn set_diagnostic_handler( &self, handler: extern "C" fn(LLVMDiagnosticInfoRef, *mut c_void), @@ -474,7 +494,7 @@ impl Context { /// let builder = context.create_builder(); /// ``` #[inline] - pub fn create_builder(&self) -> Builder { + pub fn create_builder(&self) -> Builder<'_> { self.context.create_builder() } @@ -489,7 +509,7 @@ impl Context { /// let module = context.create_module("my_module"); /// ``` #[inline] - pub fn create_module(&self, name: &str) -> Module { + pub fn create_module(&self, name: &str) -> Module<'_> { self.context.create_module(name) } @@ -520,7 +540,7 @@ impl Context { // a double free in valgrind when the MemoryBuffer drops so we are `forget`ting MemoryBuffer here // for now until we can confirm this is the correct thing to do #[inline] - pub fn create_module_from_ir(&self, memory_buffer: MemoryBuffer) -> Result { + pub fn create_module_from_ir(&self, memory_buffer: MemoryBuffer) -> Result, LLVMString> { self.context.create_module_from_ir(memory_buffer) } @@ -574,7 +594,7 @@ impl Context { /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// /// builder.build_return(None).unwrap(); @@ -628,7 +648,7 @@ impl Context { /// assert_eq!(void_type.get_context(), context); /// ``` #[inline] - pub fn void_type(&self) -> VoidType { + pub fn void_type(&self) -> VoidType<'_> { self.context.void_type() } @@ -646,7 +666,7 @@ impl Context { /// assert_eq!(bool_type.get_context(), context); /// ``` #[inline] - pub fn bool_type(&self) -> IntType { + pub fn bool_type(&self) -> IntType<'_> { self.context.bool_type() } @@ -664,7 +684,7 @@ impl Context { /// assert_eq!(i8_type.get_context(), context); /// ``` #[inline] - pub fn i8_type(&self) -> IntType { + pub fn i8_type(&self) -> IntType<'_> { self.context.i8_type() } @@ -682,7 +702,7 @@ impl Context { /// assert_eq!(i16_type.get_context(), context); /// ``` #[inline] - pub fn i16_type(&self) -> IntType { + pub fn i16_type(&self) -> IntType<'_> { self.context.i16_type() } @@ -700,7 +720,7 @@ impl Context { /// assert_eq!(i32_type.get_context(), context); /// ``` #[inline] - pub fn i32_type(&self) -> IntType { + pub fn i32_type(&self) -> IntType<'_> { self.context.i32_type() } @@ -718,7 +738,7 @@ impl Context { /// assert_eq!(i64_type.get_context(), context); /// ``` #[inline] - pub fn i64_type(&self) -> IntType { + pub fn i64_type(&self) -> IntType<'_> { self.context.i64_type() } @@ -736,7 +756,7 @@ impl Context { /// assert_eq!(i128_type.get_context(), context); /// ``` #[inline] - pub fn i128_type(&self) -> IntType { + pub fn i128_type(&self) -> IntType<'_> { self.context.i128_type() } @@ -754,7 +774,7 @@ impl Context { /// assert_eq!(i42_type.get_context(), context); /// ``` #[inline] - pub fn custom_width_int_type(&self, bits: u32) -> IntType { + pub fn custom_width_int_type(&self, bits: u32) -> IntType<'_> { self.context.custom_width_int_type(bits) } @@ -772,7 +792,7 @@ impl Context { /// assert_eq!(md_type.get_context(), context); /// ``` #[inline] - pub fn metadata_type(&self) -> MetadataType { + pub fn metadata_type(&self) -> MetadataType<'_> { self.context.metadata_type() } @@ -794,7 +814,7 @@ impl Context { /// let int_type = context.ptr_sized_int_type(&target_data, None); /// ``` #[inline] - pub fn ptr_sized_int_type(&self, target_data: &TargetData, address_space: Option) -> IntType { + pub fn ptr_sized_int_type(&self, target_data: &TargetData, address_space: Option) -> IntType<'_> { self.context.ptr_sized_int_type(target_data, address_space) } @@ -812,7 +832,7 @@ impl Context { /// assert_eq!(f16_type.get_context(), context); /// ``` #[inline] - pub fn f16_type(&self) -> FloatType { + pub fn f16_type(&self) -> FloatType<'_> { self.context.f16_type() } @@ -830,7 +850,7 @@ impl Context { /// assert_eq!(f32_type.get_context(), context); /// ``` #[inline] - pub fn f32_type(&self) -> FloatType { + pub fn f32_type(&self) -> FloatType<'_> { self.context.f32_type() } @@ -848,7 +868,7 @@ impl Context { /// assert_eq!(f64_type.get_context(), context); /// ``` #[inline] - pub fn f64_type(&self) -> FloatType { + pub fn f64_type(&self) -> FloatType<'_> { self.context.f64_type() } @@ -866,7 +886,7 @@ impl Context { /// assert_eq!(x86_f80_type.get_context(), context); /// ``` #[inline] - pub fn x86_f80_type(&self) -> FloatType { + pub fn x86_f80_type(&self) -> FloatType<'_> { self.context.x86_f80_type() } @@ -885,7 +905,7 @@ impl Context { /// ``` // IEEE 754-2008’s binary128 floats according to https://internals.rust-lang.org/t/pre-rfc-introduction-of-half-and-quadruple-precision-floats-f16-and-f128/7521 #[inline] - pub fn f128_type(&self) -> FloatType { + pub fn f128_type(&self) -> FloatType<'_> { self.context.f128_type() } @@ -906,7 +926,7 @@ impl Context { /// ``` // Two 64 bits according to https://internals.rust-lang.org/t/pre-rfc-introduction-of-half-and-quadruple-precision-floats-f16-and-f128/7521 #[inline] - pub fn ppc_f128_type(&self) -> FloatType { + pub fn ppc_f128_type(&self) -> FloatType<'_> { self.context.ppc_f128_type() } @@ -926,7 +946,7 @@ impl Context { /// ``` #[cfg(not(feature = "typed-pointers"))] #[inline] - pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType { + pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType<'_> { self.context.ptr_type(address_space) } @@ -946,7 +966,7 @@ impl Context { /// ``` // REVIEW: AnyType but VoidType? FunctionType? #[inline] - pub fn struct_type(&self, field_types: &[BasicTypeEnum], packed: bool) -> StructType { + pub fn struct_type<'ctx>(&'ctx self, field_types: &[BasicTypeEnum], packed: bool) -> StructType<'ctx> { self.context.struct_type(field_types, packed) } @@ -965,7 +985,7 @@ impl Context { /// assert_eq!(struct_type.get_field_types(), &[]); /// ``` #[inline] - pub fn opaque_struct_type(&self, name: &str) -> StructType { + pub fn opaque_struct_type<'ctx>(&'ctx self, name: &str) -> StructType<'ctx> { self.context.opaque_struct_type(name) } @@ -1007,7 +1027,7 @@ impl Context { /// assert_eq!(const_struct.get_type().get_field_types(), &[i16_type.into(), f32_type.into()]); /// ``` #[inline] - pub fn const_struct(&self, values: &[BasicValueEnum], packed: bool) -> StructValue { + pub fn const_struct<'ctx>(&'ctx self, values: &[BasicValueEnum], packed: bool) -> StructValue<'ctx> { self.context.const_struct(values, packed) } @@ -1161,7 +1181,7 @@ impl Context { /// ``` // REVIEW: Seems to be unassigned to anything #[inline] - pub fn metadata_string(&self, string: &str) -> MetadataValue { + pub fn metadata_string<'ctx>(&'ctx self, string: &str) -> MetadataValue<'ctx> { self.context.metadata_string(string) } @@ -1273,7 +1293,7 @@ impl Context { /// ``` // SubTypes: Should return ArrayValue> #[inline] - pub fn const_string(&self, string: &[u8], null_terminated: bool) -> ArrayValue { + pub fn const_string<'ctx>(&'ctx self, string: &[u8], null_terminated: bool) -> ArrayValue<'ctx> { self.context.const_string(string, null_terminated) } @@ -1436,7 +1456,7 @@ impl<'ctx> ContextRef<'ctx> { /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// - /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// /// builder.build_return(None).unwrap(); diff --git a/src/debug_info.rs b/src/debug_info.rs index 1721e7e56a8..c6ce218ce24 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -123,11 +123,25 @@ use llvm_sys::debuginfo::{ LLVMDIBuilderCreateMemberType, LLVMDIBuilderCreateNameSpace, LLVMDIBuilderCreateParameterVariable, LLVMDIBuilderCreatePointerType, LLVMDIBuilderCreateReferenceType, LLVMDIBuilderCreateStructType, LLVMDIBuilderCreateSubroutineType, LLVMDIBuilderCreateUnionType, LLVMDIBuilderFinalize, - LLVMDIBuilderGetOrCreateSubrange, LLVMDIBuilderInsertDbgValueBefore, LLVMDIBuilderInsertDeclareAtEnd, - LLVMDIBuilderInsertDeclareBefore, LLVMDILocationGetColumn, LLVMDILocationGetLine, LLVMDILocationGetScope, + LLVMDIBuilderGetOrCreateSubrange, LLVMDILocationGetColumn, LLVMDILocationGetLine, LLVMDILocationGetScope, LLVMDITypeGetAlignInBits, LLVMDITypeGetOffsetInBits, LLVMDITypeGetSizeInBits, }; +#[llvm_versions(..19.1)] +use llvm_sys::debuginfo::{ + LLVMDIBuilderInsertDbgValueBefore, LLVMDIBuilderInsertDeclareAtEnd, LLVMDIBuilderInsertDeclareBefore, +}; + +#[llvm_versions(19.1..)] +use llvm_sys::debuginfo::{ + LLVMDIBuilderInsertDbgValueRecordBefore as LLVMDIBuilderInsertDbgValueBefore, + LLVMDIBuilderInsertDeclareRecordAtEnd as LLVMDIBuilderInsertDeclareAtEnd, + LLVMDIBuilderInsertDeclareRecordBefore as LLVMDIBuilderInsertDeclareBefore, +}; + +#[llvm_versions(19.1..)] +use llvm_sys::prelude::LLVMValueRef; + use llvm_sys::debuginfo::{LLVMDIBuilderCreateConstantValueExpression, LLVMDIBuilderCreateGlobalVariableExpression}; use llvm_sys::prelude::{LLVMDIBuilderRef, LLVMMetadataRef}; use std::convert::TryInto; @@ -195,7 +209,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sysroot: &str, #[cfg(any( @@ -206,7 +222,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sdk: &str, ) -> (Self, DICompileUnit<'ctx>) { @@ -245,7 +263,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sysroot, #[cfg(any( @@ -256,7 +276,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sdk, ); @@ -303,7 +325,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sysroot: &str, #[cfg(any( @@ -314,7 +338,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sdk: &str, ) -> DICompileUnit<'ctx> { @@ -348,7 +374,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] { LLVMDIBuilderCreateCompileUnit( @@ -927,7 +955,18 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) }; - unsafe { InstructionValue::new(value_ref) } + #[cfg(any(feature = "llvm19-1", feature = "llvm20-1"))] + { + // In LLVM 19+, the insert... functions return a DbgRecord, not a Value. + // We need to cast it to a ValueRef to create an InstructionValue. + // This is unsafe, but it's the only way to do it. + unsafe { InstructionValue::new(value_ref as LLVMValueRef) } + } + + #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1")))] + { + unsafe { InstructionValue::new(value_ref) } + } } /// Insert a variable declaration (`llvm.dbg.declare` intrinsic) at the end of `block` @@ -950,7 +989,18 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) }; - unsafe { InstructionValue::new(value_ref) } + #[cfg(any(feature = "llvm19-1", feature = "llvm20-1"))] + { + // In LLVM 19+, the insert... functions return a DbgRecord, not a Value. + // We need to cast it to a ValueRef to create an InstructionValue. + // This is unsafe, but it's the only way to do it. + unsafe { InstructionValue::new(value_ref as LLVMValueRef) } + } + + #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1")))] + { + unsafe { InstructionValue::new(value_ref) } + } } /// Create an expression @@ -988,7 +1038,18 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) }; - unsafe { InstructionValue::new(value_ref) } + #[cfg(any(feature = "llvm19-1", feature = "llvm20-1"))] + { + // In LLVM 19+, the insert... functions return a DbgRecord, not a Value. + // We need to cast it to a ValueRef to create an InstructionValue. + // This is unsafe, but it's the only way to do it. + unsafe { InstructionValue::new(value_ref as LLVMValueRef) } + } + + #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1")))] + { + unsafe { InstructionValue::new(value_ref) } + } } /// Construct a placeholders derived type to be used when building debug info with circular references. @@ -1590,5 +1651,57 @@ mod flags { #[llvm_versions(17..)] #[llvm_variant(LLVMDWARFSourceLanguageMojo)] Mojo, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageHIP)] + Hip, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageAssembly)] + Assembly, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageC_sharp)] + Csharp, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageGLSL)] + Glsl, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageGLSL_ES)] + GlslEs, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageHLSL)] + Hlsl, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageOpenCL_CPP)] + OpenClCpp, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageCPP_for_OpenCL)] + CppForOpenCl, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageSYCL)] + Sycl, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageRuby)] + Ruby, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageMove)] + Move, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMDWARFSourceLanguageHylo)] + Hylo, + + #[llvm_versions(20..)] + #[llvm_variant(LLVMDWARFSourceLanguageMetal)] + Metal, } } diff --git a/src/lib.rs b/src/lib.rs index eba3350a0a6..53c36e10973 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,10 @@ pub extern crate llvm_sys_160 as llvm_sys; pub extern crate llvm_sys_170 as llvm_sys; #[cfg(feature = "llvm18-1")] pub extern crate llvm_sys_181 as llvm_sys; +#[cfg(feature = "llvm19-1")] +pub extern crate llvm_sys_191 as llvm_sys; +#[cfg(feature = "llvm20-1")] +pub extern crate llvm_sys_201 as llvm_sys; #[cfg(feature = "llvm8-0")] pub extern crate llvm_sys_80 as llvm_sys; #[cfg(feature = "llvm9-0")] @@ -118,7 +122,9 @@ assert_unique_used_features! { "llvm15-0", "llvm16-0", "llvm17-0", - "llvm18-1" + "llvm18-1", + "llvm19-1", + "llvm20-1" } #[cfg(all( @@ -381,6 +387,22 @@ pub enum AtomicRMWBinOp { #[llvm_versions(15..)] #[llvm_variant(LLVMAtomicRMWBinOpFMin)] FMin, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMAtomicRMWBinOpUIncWrap)] + UIncWrap, + + #[llvm_versions(19.1..)] + #[llvm_variant(LLVMAtomicRMWBinOpUDecWrap)] + UDecWrap, + + #[llvm_versions(20..)] + #[llvm_variant(LLVMAtomicRMWBinOpUSubCond)] + USubCond, + + #[llvm_versions(20..)] + #[llvm_variant(LLVMAtomicRMWBinOpUSubSat)] + USubSat, } /// Defines the optimization level used to compile a [`Module`](crate::module::Module). diff --git a/src/module.rs b/src/module.rs index 62c5fbd3713..41509f976d0 100644 --- a/src/module.rs +++ b/src/module.rs @@ -912,7 +912,7 @@ impl<'ctx> Module<'ctx> { /// /// assert_eq!(*module.get_data_layout(), data_layout); /// ``` - pub fn get_data_layout(&self) -> Ref { + pub fn get_data_layout(&self) -> Ref<'_, DataLayout> { Ref::map(self.data_layout.borrow(), |l| { l.as_ref().expect("DataLayout should always exist until Drop") }) @@ -1545,7 +1545,9 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sysroot: &str, #[cfg(any( @@ -1556,7 +1558,9 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sdk: &str, ) -> (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>) { @@ -1583,7 +1587,9 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sysroot, #[cfg(any( @@ -1594,7 +1600,9 @@ impl<'ctx> Module<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] sdk, ) diff --git a/src/types/array_type.rs b/src/types/array_type.rs index b6675b10c20..c849536ac3b 100644 --- a/src/types/array_type.rs +++ b/src/types/array_type.rs @@ -85,7 +85,9 @@ impl<'ctx> ArrayType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/enums.rs b/src/types/enums.rs index 958fc30804c..cf116754b9e 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -131,7 +131,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::ArrayType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -139,7 +139,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::FloatType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -147,7 +147,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::IntType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -155,7 +155,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::PointerType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -163,7 +163,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::StructType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -171,7 +171,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::VectorType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -179,7 +179,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::ScalableVectorType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -187,7 +187,7 @@ impl<'ctx> BasicMetadataTypeEnum<'ctx> { if let BasicMetadataTypeEnum::MetadataType(t) = self { t } else { - panic!("Found {:?} but expected another variant", self); + panic!("Found {self:?} but expected another variant"); } } @@ -260,7 +260,9 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)), LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"), @@ -278,11 +280,15 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => AnyTypeEnum::ScalableVectorType(ScalableVectorType::new(type_)), // FIXME: should inkwell support metadata as AnyType? LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata type is not supported as AnyType."), + + #[cfg(not(feature = "llvm20-1"))] LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("FIXME: Unsupported type: MMX"), #[cfg(any( feature = "llvm12-0", @@ -291,11 +297,19 @@ impl<'ctx> AnyTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMX86_AMXTypeKind => panic!("FIXME: Unsupported type: AMX"), LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"), - #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + #[cfg(any( + feature = "llvm16-0", + feature = "llvm17-0", + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" + ))] LLVMTypeKind::LLVMTargetExtTypeKind => panic!("FIXME: Unsupported type: TargetExt"), } } @@ -309,7 +323,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::ArrayType(t) = self { t } else { - panic!("Found {:?} but expected the ArrayType variant", self); + panic!("Found {self:?} but expected the ArrayType variant"); } } @@ -317,7 +331,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::FloatType(t) = self { t } else { - panic!("Found {:?} but expected the FloatType variant", self); + panic!("Found {self:?} but expected the FloatType variant"); } } @@ -325,7 +339,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::FunctionType(t) = self { t } else { - panic!("Found {:?} but expected the FunctionType variant", self); + panic!("Found {self:?} but expected the FunctionType variant"); } } @@ -333,7 +347,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::IntType(t) = self { t } else { - panic!("Found {:?} but expected the IntType variant", self); + panic!("Found {self:?} but expected the IntType variant"); } } @@ -341,7 +355,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::PointerType(t) = self { t } else { - panic!("Found {:?} but expected the PointerType variant", self); + panic!("Found {self:?} but expected the PointerType variant"); } } @@ -349,7 +363,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::StructType(t) = self { t } else { - panic!("Found {:?} but expected the StructType variant", self); + panic!("Found {self:?} but expected the StructType variant"); } } @@ -357,7 +371,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::VectorType(t) = self { t } else { - panic!("Found {:?} but expected the VectorType variant", self); + panic!("Found {self:?} but expected the VectorType variant"); } } @@ -365,7 +379,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::ScalableVectorType(t) = self { t } else { - panic!("Found {:?} but expected the ScalableVectorType variant", self); + panic!("Found {self:?} but expected the ScalableVectorType variant"); } } @@ -373,7 +387,7 @@ impl<'ctx> AnyTypeEnum<'ctx> { if let AnyTypeEnum::VoidType(t) = self { t } else { - panic!("Found {:?} but expected the VoidType variant", self); + panic!("Found {self:?} but expected the VoidType variant"); } } @@ -460,7 +474,9 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)), LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)), @@ -476,13 +492,16 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicTypeEnum::ScalableVectorType(ScalableVectorType::new(type_)) }, LLVMTypeKind::LLVMMetadataTypeKind => panic!("Unsupported basic type: Metadata"), // see https://llvm.org/docs/LangRef.html#x86-mmx-type + #[cfg(not(feature = "llvm20-1"))] LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("Unsupported basic type: MMX"), // see https://llvm.org/docs/LangRef.html#x86-amx-type #[cfg(any( @@ -492,14 +511,22 @@ impl<'ctx> BasicTypeEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMX86_AMXTypeKind => unreachable!("Unsupported basic type: AMX"), LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"), LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"), LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"), LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"), - #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + #[cfg(any( + feature = "llvm16-0", + feature = "llvm17-0", + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" + ))] LLVMTypeKind::LLVMTargetExtTypeKind => unreachable!("Unsupported basic type: TargetExt"), } } @@ -508,7 +535,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::ArrayType(t) = self { t } else { - panic!("Found {:?} but expected the ArrayType variant", self); + panic!("Found {self:?} but expected the ArrayType variant"); } } @@ -516,7 +543,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::FloatType(t) = self { t } else { - panic!("Found {:?} but expected the FloatType variant", self); + panic!("Found {self:?} but expected the FloatType variant"); } } @@ -524,7 +551,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::IntType(t) = self { t } else { - panic!("Found {:?} but expected the IntType variant", self); + panic!("Found {self:?} but expected the IntType variant"); } } @@ -532,7 +559,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::PointerType(t) = self { t } else { - panic!("Found {:?} but expected the PointerType variant", self); + panic!("Found {self:?} but expected the PointerType variant"); } } @@ -540,7 +567,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::StructType(t) = self { t } else { - panic!("Found {:?} but expected the StructType variant", self); + panic!("Found {self:?} but expected the StructType variant"); } } @@ -548,7 +575,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::VectorType(t) = self { t } else { - panic!("Found {:?} but expected the VectorType variant", self); + panic!("Found {self:?} but expected the VectorType variant"); } } @@ -556,7 +583,7 @@ impl<'ctx> BasicTypeEnum<'ctx> { if let BasicTypeEnum::ScalableVectorType(t) = self { t } else { - panic!("Found {:?} but expected the ScalableVectorType variant", self); + panic!("Found {self:?} but expected the ScalableVectorType variant"); } } diff --git a/src/types/float_type.rs b/src/types/float_type.rs index 3ac810f5872..73c93cadffe 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -244,7 +244,9 @@ impl<'ctx> FloatType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index 21f35015ecc..78c5245d97e 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -53,7 +53,9 @@ impl<'ctx> FunctionType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/int_type.rs b/src/types/int_type.rs index cd1d33e4428..fe513635fdf 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -331,7 +331,9 @@ impl<'ctx> IntType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/ptr_type.rs b/src/types/ptr_type.rs index e649687a3e2..69826df2aa9 100644 --- a/src/types/ptr_type.rs +++ b/src/types/ptr_type.rs @@ -100,7 +100,9 @@ impl<'ctx> PointerType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/scalable_vec_type.rs b/src/types/scalable_vec_type.rs index d1207c3af2b..344068ba887 100644 --- a/src/types/scalable_vec_type.rs +++ b/src/types/scalable_vec_type.rs @@ -180,7 +180,9 @@ impl<'ctx> ScalableVectorType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index 96b62bede41..99d54f651c1 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -209,7 +209,9 @@ impl<'ctx> StructType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/traits.rs b/src/types/traits.rs index a67c685cf32..1fd694c8383 100644 --- a/src/types/traits.rs +++ b/src/types/traits.rs @@ -137,7 +137,9 @@ pub unsafe trait BasicType<'ctx>: AnyType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/types/vec_type.rs b/src/types/vec_type.rs index 7ae1fb01a62..c32180c60b7 100644 --- a/src/types/vec_type.rs +++ b/src/types/vec_type.rs @@ -208,7 +208,9 @@ impl<'ctx> VectorType<'ctx> { all(feature = "llvm15-0", not(feature = "typed-pointers")), all(feature = "llvm16-0", not(feature = "typed-pointers")), feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ), deprecated( note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead." diff --git a/src/values/enums.rs b/src/values/enums.rs index bc98a18d0a8..13bc82eb9a1 100644 --- a/src/values/enums.rs +++ b/src/values/enums.rs @@ -102,7 +102,9 @@ impl<'ctx> AnyValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { AnyValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) @@ -168,7 +170,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::ArrayValue(v) = self { v } else { - panic!("Found {:?} but expected the ArrayValue variant", self) + panic!("Found {self:?} but expected the ArrayValue variant") } } @@ -177,7 +179,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::IntValue(v) = self { v } else { - panic!("Found {:?} but expected the IntValue variant", self) + panic!("Found {self:?} but expected the IntValue variant") } } @@ -186,7 +188,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::FloatValue(v) = self { v } else { - panic!("Found {:?} but expected the FloatValue variant", self) + panic!("Found {self:?} but expected the FloatValue variant") } } @@ -195,7 +197,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::PhiValue(v) = self { v } else { - panic!("Found {:?} but expected the PhiValue variant", self) + panic!("Found {self:?} but expected the PhiValue variant") } } @@ -204,7 +206,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::FunctionValue(v) = self { v } else { - panic!("Found {:?} but expected the FunctionValue variant", self) + panic!("Found {self:?} but expected the FunctionValue variant") } } @@ -213,7 +215,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::PointerValue(v) = self { v } else { - panic!("Found {:?} but expected the PointerValue variant", self) + panic!("Found {self:?} but expected the PointerValue variant") } } @@ -222,7 +224,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::StructValue(v) = self { v } else { - panic!("Found {:?} but expected the StructValue variant", self) + panic!("Found {self:?} but expected the StructValue variant") } } @@ -231,7 +233,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::VectorValue(v) = self { v } else { - panic!("Found {:?} but expected the VectorValue variant", self) + panic!("Found {self:?} but expected the VectorValue variant") } } @@ -240,7 +242,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::ScalableVectorValue(v) = self { v } else { - panic!("Found {:?} but expected the ScalableVectorValue variant", self) + panic!("Found {self:?} but expected the ScalableVectorValue variant") } } @@ -249,7 +251,7 @@ impl<'ctx> AnyValueEnum<'ctx> { if let AnyValueEnum::InstructionValue(v) = self { v } else { - panic!("Found {:?} but expected the InstructionValue variant", self) + panic!("Found {self:?} but expected the InstructionValue variant") } } } @@ -281,7 +283,9 @@ impl<'ctx> BasicValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) @@ -353,7 +357,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::ArrayValue(v) = self { v } else { - panic!("Found {:?} but expected the ArrayValue variant", self) + panic!("Found {self:?} but expected the ArrayValue variant") } } @@ -362,7 +366,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::IntValue(v) = self { v } else { - panic!("Found {:?} but expected the IntValue variant", self) + panic!("Found {self:?} but expected the IntValue variant") } } @@ -371,7 +375,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::FloatValue(v) = self { v } else { - panic!("Found {:?} but expected the FloatValue variant", self) + panic!("Found {self:?} but expected the FloatValue variant") } } @@ -380,7 +384,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::PointerValue(v) = self { v } else { - panic!("Found {:?} but expected PointerValue variant", self) + panic!("Found {self:?} but expected PointerValue variant") } } @@ -389,7 +393,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::StructValue(v) = self { v } else { - panic!("Found {:?} but expected the StructValue variant", self) + panic!("Found {self:?} but expected the StructValue variant") } } @@ -398,7 +402,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::VectorValue(v) = self { v } else { - panic!("Found {:?} but expected the VectorValue variant", self) + panic!("Found {self:?} but expected the VectorValue variant") } } @@ -407,7 +411,7 @@ impl<'ctx> BasicValueEnum<'ctx> { if let BasicValueEnum::ScalableVectorValue(v) = self { v } else { - panic!("Found {:?} but expected the ScalableVectorValue variant", self) + panic!("Found {self:?} but expected the ScalableVectorValue variant") } } } @@ -439,7 +443,7 @@ impl<'ctx> AggregateValueEnum<'ctx> { if let AggregateValueEnum::ArrayValue(v) = self { v } else { - panic!("Found {:?} but expected the ArrayValue variant", self) + panic!("Found {self:?} but expected the ArrayValue variant") } } @@ -448,7 +452,7 @@ impl<'ctx> AggregateValueEnum<'ctx> { if let AggregateValueEnum::StructValue(v) = self { v } else { - panic!("Found {:?} but expected the StructValue variant", self) + panic!("Found {self:?} but expected the StructValue variant") } } } @@ -475,7 +479,9 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicMetadataValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) @@ -522,7 +528,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::ArrayValue(v) = self { v } else { - panic!("Found {:?} but expected the ArrayValue variant", self) + panic!("Found {self:?} but expected the ArrayValue variant") } } @@ -531,7 +537,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::IntValue(v) = self { v } else { - panic!("Found {:?} but expected the IntValue variant", self) + panic!("Found {self:?} but expected the IntValue variant") } } @@ -540,7 +546,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::FloatValue(v) = self { v } else { - panic!("Found {:?} but expected FloatValue variant", self) + panic!("Found {self:?} but expected FloatValue variant") } } @@ -549,7 +555,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::PointerValue(v) = self { v } else { - panic!("Found {:?} but expected the PointerValue variant", self) + panic!("Found {self:?} but expected the PointerValue variant") } } @@ -558,7 +564,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::StructValue(v) = self { v } else { - panic!("Found {:?} but expected the StructValue variant", self) + panic!("Found {self:?} but expected the StructValue variant") } } @@ -567,7 +573,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::VectorValue(v) = self { v } else { - panic!("Found {:?} but expected the VectorValue variant", self) + panic!("Found {self:?} but expected the VectorValue variant") } } @@ -576,7 +582,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::ScalableVectorValue(v) = self { v } else { - panic!("Found {:?} but expected the ScalableVectorValue variant", self) + panic!("Found {self:?} but expected the ScalableVectorValue variant") } } @@ -585,7 +591,7 @@ impl<'ctx> BasicMetadataValueEnum<'ctx> { if let BasicMetadataValueEnum::MetadataValue(v) = self { v } else { - panic!("Found {:?} but expected MetaData variant", self) + panic!("Found {self:?} but expected MetaData variant") } } } diff --git a/src/values/float_value.rs b/src/values/float_value.rs index ba396be5186..96eae6f904f 100644 --- a/src/values/float_value.rs +++ b/src/values/float_value.rs @@ -1,8 +1,10 @@ #[llvm_versions(..=17)] use crate::types::IntType; +#[llvm_versions(..=18)] +use llvm_sys::core::LLVMConstFCmp; #[llvm_versions(..=15)] use llvm_sys::core::LLVMConstFNeg; -use llvm_sys::core::{LLVMConstFCmp, LLVMConstRealGetDouble}; +use llvm_sys::core::LLVMConstRealGetDouble; #[llvm_versions(..=17)] use llvm_sys::core::{LLVMConstFPCast, LLVMConstFPExt, LLVMConstFPToSI, LLVMConstFPToUI, LLVMConstFPTrunc}; use llvm_sys::prelude::LLVMValueRef; @@ -15,8 +17,10 @@ use std::fmt::{self, Display}; use crate::types::AsTypeRef; use crate::types::FloatType; use crate::values::traits::AsValueRef; -use crate::values::{InstructionValue, IntValue, Value}; -use crate::FloatPredicate; +use crate::values::{InstructionValue, Value}; + +#[llvm_versions(..=18)] +use crate::{values::IntValue, FloatPredicate}; use super::AnyValue; @@ -136,6 +140,7 @@ impl<'ctx> FloatValue<'ctx> { } // SubType: rhs same as lhs; return IntValue + #[llvm_versions(..=18)] pub fn const_compare(self, op: FloatPredicate, rhs: FloatValue<'ctx>) -> IntValue<'ctx> { unsafe { IntValue::new(LLVMConstFCmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) } } diff --git a/src/values/int_value.rs b/src/values/int_value.rs index 145a777e951..14877f28cbc 100644 --- a/src/values/int_value.rs +++ b/src/values/int_value.rs @@ -1,16 +1,23 @@ -#[llvm_versions(..=16)] -use llvm_sys::core::LLVMConstSelect; #[llvm_versions(..=17)] use llvm_sys::core::{ LLVMConstAShr, LLVMConstAnd, LLVMConstIntCast, LLVMConstLShr, LLVMConstOr, LLVMConstSExt, LLVMConstSExtOrBitCast, LLVMConstSIToFP, LLVMConstUIToFP, LLVMConstZExt, LLVMConstZExtOrBitCast, }; use llvm_sys::core::{ - LLVMConstAdd, LLVMConstBitCast, LLVMConstICmp, LLVMConstIntGetSExtValue, LLVMConstIntGetZExtValue, - LLVMConstIntToPtr, LLVMConstMul, LLVMConstNSWAdd, LLVMConstNSWMul, LLVMConstNSWNeg, LLVMConstNSWSub, - LLVMConstNUWAdd, LLVMConstNUWMul, LLVMConstNUWNeg, LLVMConstNUWSub, LLVMConstNeg, LLVMConstNot, LLVMConstShl, - LLVMConstSub, LLVMConstTrunc, LLVMConstTruncOrBitCast, LLVMConstXor, LLVMIsAConstantInt, + LLVMConstAdd, LLVMConstBitCast, LLVMConstIntGetSExtValue, LLVMConstIntGetZExtValue, LLVMConstIntToPtr, + LLVMConstMul, LLVMConstNSWAdd, LLVMConstNSWMul, LLVMConstNSWNeg, LLVMConstNSWSub, LLVMConstNUWAdd, LLVMConstNUWMul, + LLVMConstNUWSub, LLVMConstNeg, LLVMConstNot, LLVMConstSub, LLVMConstTrunc, LLVMConstTruncOrBitCast, LLVMConstXor, + LLVMIsAConstantInt, }; +#[llvm_versions(..=16)] +use llvm_sys::core::{LLVMConstNUWNeg, LLVMConstSelect}; + +#[llvm_versions(17..)] +use llvm_sys::core::LLVMSetNUW; + +#[llvm_versions(..=18)] +use llvm_sys::core::{LLVMConstICmp, LLVMConstShl}; + use llvm_sys::prelude::LLVMValueRef; use std::convert::TryFrom; @@ -26,6 +33,8 @@ use crate::values::FloatValue; #[llvm_versions(..=16)] use crate::values::{BasicValue, BasicValueEnum}; use crate::values::{InstructionValue, PointerValue, Value}; + +#[llvm_versions(..=18)] use crate::IntPredicate; use super::AnyValue; @@ -93,10 +102,20 @@ impl<'ctx> IntValue<'ctx> { unsafe { IntValue::new(LLVMConstNSWNeg(self.as_value_ref())) } } + #[llvm_versions(..17)] pub fn const_nuw_neg(self) -> Self { unsafe { IntValue::new(LLVMConstNUWNeg(self.as_value_ref())) } } + #[llvm_versions(17..)] + pub fn const_nuw_neg(self) -> Self { + let value = unsafe { LLVMConstNeg(self.as_value_ref()) }; + unsafe { + LLVMSetNUW(value, true.into()); + } + unsafe { IntValue::new(value) } + } + pub fn const_add(self, rhs: IntValue<'ctx>) -> Self { unsafe { IntValue::new(LLVMConstAdd(self.as_value_ref(), rhs.as_value_ref())) } } @@ -202,6 +221,7 @@ impl<'ctx> IntValue<'ctx> { } // TODO: Give shift methods more descriptive names + #[llvm_versions(..=18)] pub fn const_shl(self, rhs: IntValue<'ctx>) -> Self { unsafe { IntValue::new(LLVMConstShl(self.as_value_ref(), rhs.as_value_ref())) } } @@ -269,6 +289,7 @@ impl<'ctx> IntValue<'ctx> { } // SubType: rhs same as lhs; return IntValue + #[llvm_versions(..=18)] pub fn const_int_compare(self, op: IntPredicate, rhs: IntValue<'ctx>) -> IntValue<'ctx> { unsafe { IntValue::new(LLVMConstICmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) } } diff --git a/src/values/metadata_value.rs b/src/values/metadata_value.rs index 0c8717647d9..2db3d5d050e 100644 --- a/src/values/metadata_value.rs +++ b/src/values/metadata_value.rs @@ -32,6 +32,10 @@ pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = if cfg!(feature = "llvm8-0") { 39 } else if cfg!(feature = "llvm18-1") { 40 +} else if cfg!(feature = "llvm19-1") { + 41 +} else if cfg!(feature = "llvm20-1") { + 42 } else { panic!("Unhandled LLVM version") }; diff --git a/src/values/mod.rs b/src/values/mod.rs index 16c1582eccc..a4db54f4b9b 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -21,14 +21,16 @@ mod struct_value; mod traits; mod vec_value; -#[cfg(feature = "llvm18-1")] +#[cfg(any(feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] pub(crate) mod operand_bundle; #[cfg(not(any( feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" )))] mod callable_value; @@ -36,7 +38,9 @@ mod callable_value; feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" )))] pub use crate::values::callable_value::CallableValue; diff --git a/src/values/traits.rs b/src/values/traits.rs index 760a30cbf71..9555477a385 100644 --- a/src/values/traits.rs +++ b/src/values/traits.rs @@ -122,7 +122,7 @@ pub unsafe trait BasicValue<'ctx>: AnyValue<'ctx> { unsafe { Some(InstructionValue::new(self.as_value_ref())) } } - fn get_first_use(&self) -> Option { + fn get_first_use(&self) -> Option> { unsafe { Value::new(self.as_value_ref()).get_first_use() } } diff --git a/tests/all/main.rs b/tests/all/main.rs index 1a0b41d1d87..a9b0027854c 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -15,7 +15,12 @@ mod test_instruction_values; mod test_intrinsics; mod test_module; mod test_object_file; -#[cfg(not(any(feature = "llvm17-0", feature = "llvm18-1")))] +#[cfg(not(any( + feature = "llvm17-0", + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" +)))] mod test_passes; mod test_targets; mod test_tari_example; diff --git a/tests/all/test_builder.rs b/tests/all/test_builder.rs index b35666a306a..043e600d006 100644 --- a/tests/all/test_builder.rs +++ b/tests/all/test_builder.rs @@ -84,7 +84,9 @@ fn test_build_call() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] builder.build_indirect_call(fn_type2, load, &[], "call").unwrap(); builder.build_return(None).unwrap(); @@ -1322,11 +1324,10 @@ fn test_alignment_bytes() { if is_alignment_ok(alignment) { assert!( result.is_ok() && module.verify().is_ok(), - "alignment of {} was a power of 2 under 2^64, but did not verify for memcpy.", - alignment + "alignment of {alignment} was a power of 2 under 2^64, but did not verify for memcpy." ); } else { - assert!(result.is_err(), "alignment of {} was a power of 2 under 2^64, yet verification passed for memcpy when it should not have.", alignment); + assert!(result.is_err(), "alignment of {alignment} was a power of 2 under 2^64, yet verification passed for memcpy when it should not have."); } let result = run_memmove_on(&context, &module, alignment); @@ -1334,11 +1335,10 @@ fn test_alignment_bytes() { if is_alignment_ok(alignment) { assert!( result.is_ok() && module.verify().is_ok(), - "alignment of {} was a power of 2 under 2^64, but did not verify for memmove.", - alignment + "alignment of {alignment} was a power of 2 under 2^64, but did not verify for memmove." ); } else { - assert!(result.is_err(), "alignment of {} was a power of 2 under 2^64, yet verification passed for memmove when it should not have.", alignment); + assert!(result.is_err(), "alignment of {alignment} was a power of 2 under 2^64, yet verification passed for memmove when it should not have."); } }; @@ -1421,7 +1421,7 @@ fn test_memcpy() { // Verify the module if let Err(errors) = module.verify() { - panic!("Errors defining module: {:?}", errors); + panic!("Errors defining module: {errors:?}"); } let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); @@ -1508,7 +1508,7 @@ fn test_memmove() { // Verify the module if let Err(errors) = module.verify() { - panic!("Errors defining module: {:?}", errors); + panic!("Errors defining module: {errors:?}"); } let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); @@ -1582,7 +1582,7 @@ fn test_memset() { // Verify the module if let Err(errors) = module.verify() { - panic!("Errors defining module: {:?}", errors); + panic!("Errors defining module: {errors:?}"); } let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); @@ -1624,7 +1624,9 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let i32_scalable_vec_type = i32_type.scalable_vec_type(2); let arg_types = [ @@ -1640,7 +1642,9 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] i32_scalable_vec_type.into(), ]; @@ -1660,7 +1664,9 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let i32_scalable_vec_arg = fn_value.get_nth_param(5).unwrap(); @@ -1677,7 +1683,9 @@ fn test_bit_cast() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] { let i64_scalable_vec_type = i64_type.scalable_vec_type(1); diff --git a/tests/all/test_debug_info.rs b/tests/all/test_debug_info.rs index f7ae9cabfa7..8b4ce5c7ac4 100644 --- a/tests/all/test_debug_info.rs +++ b/tests/all/test_debug_info.rs @@ -33,7 +33,9 @@ fn test_smoke() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -44,7 +46,9 @@ fn test_smoke() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -117,7 +121,9 @@ fn test_struct_with_placeholders() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -128,7 +134,9 @@ fn test_struct_with_placeholders() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -217,7 +225,9 @@ fn test_no_explicit_finalize() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -228,7 +238,9 @@ fn test_no_explicit_finalize() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -265,7 +277,9 @@ fn test_replacing_placeholder_with_placeholder() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -276,7 +290,9 @@ fn test_replacing_placeholder_with_placeholder() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -328,7 +344,9 @@ fn test_anonymous_basic_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -339,7 +357,9 @@ fn test_anonymous_basic_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -377,7 +397,9 @@ fn test_global_expressions() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -388,7 +410,9 @@ fn test_global_expressions() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -451,7 +475,9 @@ fn test_pointer_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -462,7 +488,9 @@ fn test_pointer_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -503,7 +531,9 @@ fn test_reference_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -514,7 +544,9 @@ fn test_reference_types() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); @@ -556,7 +588,9 @@ fn test_array_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", #[cfg(any( @@ -567,7 +601,9 @@ fn test_array_type() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] "", ); diff --git a/tests/all/test_execution_engine.rs b/tests/all/test_execution_engine.rs index 7f4c880f271..925f6d3a604 100644 --- a/tests/all/test_execution_engine.rs +++ b/tests/all/test_execution_engine.rs @@ -113,11 +113,11 @@ fn test_jit_execution_engine() { let ret = unsafe { execution_engine.run_function_as_main(main, &["input", "bar"]) }; - assert_eq!(ret, 1, "unexpected main return code: {}", ret); + assert_eq!(ret, 1, "unexpected main return code: {ret}"); let ret = unsafe { execution_engine.run_function_as_main(main, &["input", "bar", "baz"]) }; - assert_eq!(ret, 42, "unexpected main return code: {}", ret); + assert_eq!(ret, 42, "unexpected main return code: {ret}"); } // #[test] diff --git a/tests/all/test_intrinsics.rs b/tests/all/test_intrinsics.rs index ae73bdcdf82..099b8f5c294 100644 --- a/tests/all/test_intrinsics.rs +++ b/tests/all/test_intrinsics.rs @@ -28,11 +28,16 @@ fn test_get_decl_cos() { assert_eq!(decl.get_name().to_str().unwrap(), "llvm.cos.f32"); } +#[llvm_versions(..19)] #[test] fn test_get_decl_va_copy() { let va_copy = Intrinsic::find("llvm.va_copy").unwrap(); - assert!(!va_copy.is_overloaded()); + // Looks like starting from LLVM 19, this is overloaded? + #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1")))] + { + assert!(!va_copy.is_overloaded()); + } let context = Context::create(); let module = context.create_module("my_module"); diff --git a/tests/all/test_targets.rs b/tests/all/test_targets.rs index 4672c5a4026..81443882bde 100644 --- a/tests/all/test_targets.rs +++ b/tests/all/test_targets.rs @@ -27,7 +27,11 @@ fn write_target_machine_to_memory_buffer(target_machine: TargetMachine) { let string = from_utf8(buffer.as_slice()).unwrap(); - assert!(string.contains(".text")); + // Not sure why starting since LLVM 20, text section was removed... + #[cfg(not(any(feature = "llvm20-1")))] + { + assert!(string.contains(".text")); + } assert!(string.contains(".file")); assert!(string.contains("my_module")); assert!(string.contains(".section")); @@ -392,7 +396,11 @@ fn test_write_target_machine_to_file() { let string = from_utf8(&contents).unwrap(); - assert!(string.contains(".text")); + // Not sure why starting since LLVM 20, text section was removed... + #[cfg(not(any(feature = "llvm20-1")))] + { + assert!(string.contains(".text")); + } assert!(string.contains(".file")); assert!(string.contains("my_module")); assert!(string.contains(".section")); diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index d2679b9c845..3151bf3e5d4 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -282,7 +282,9 @@ fn sized_types(global_ctx: &Context) { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] { assert!(bool_type.scalable_vec_type(42).is_sized()); @@ -341,7 +343,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_type = f64_type.scalable_vec_type(42); let array_type = f64_type.array_type(42); @@ -358,7 +362,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] scalable_vec_type.size_of(); array_type.size_of(); @@ -375,7 +381,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] scalable_vec_type.get_alignment(); array_type.get_alignment(); @@ -402,7 +410,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_zero = scalable_vec_type.const_zero(); let array_zero = array_type.const_zero(); @@ -429,7 +439,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(scalable_vec_zero.is_null()); assert!(array_zero.is_null()); @@ -477,7 +489,9 @@ fn test_const_zero() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert_eq!( scalable_vec_zero.print_to_string().to_str(), @@ -587,7 +601,9 @@ fn test_basic_type_enum() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] &int.scalable_vec_type(1), ]; diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index 7674f155952..65c7364e8f5 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -74,7 +74,7 @@ fn test_call_site() { } #[test] -#[cfg(feature = "llvm18-1")] +#[cfg(any(feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] fn test_call_site_tail_call_attributes() { let context = Context::create(); let builder = context.create_builder(); @@ -238,7 +238,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -264,7 +266,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert_eq!(scalable_vec_val.get_name().to_str(), Ok("")); assert_eq!(ppc_f128_val.get_name().to_str(), Ok("")); @@ -291,7 +295,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] scalable_vec_val.set_name("my_val15"); ppc_f128_val.set_name("my_val16"); @@ -317,7 +323,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert_eq!(scalable_vec_val.get_name().to_str(), Ok("")); assert_eq!(ppc_f128_val.get_name().to_str(), Ok("")); @@ -336,7 +344,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_type = bool_type.scalable_vec_type(1); @@ -358,7 +368,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] scalable_vec_type.into(), ]; @@ -382,7 +394,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_param = function.get_nth_param(6).unwrap().into_scalable_vector_value(); let phi_val = builder.build_phi(bool_type, "phi_node").unwrap(); @@ -400,7 +414,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert_eq!(scalable_vec_param.get_name().to_str(), Ok("")); assert_eq!(phi_val.get_name().to_str(), Ok("phi_node")); @@ -418,7 +434,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] scalable_vec_param.set_name("my_val7"); phi_val.set_name("phi"); @@ -436,7 +454,9 @@ fn test_set_get_name() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert_eq!(scalable_vec_param.get_name().to_str(), Ok("my_val7")); assert_eq!(phi_val.get_name().to_str(), Ok("phi")); @@ -488,7 +508,9 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -514,7 +536,9 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(!scalable_vec_val.is_undef()); assert!(!ppc_f128_val.is_undef()); @@ -543,7 +567,9 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_undef = bool_type.scalable_vec_type(1).get_undef(); let ppc_f128_undef = ppc_f128_type.get_undef(); @@ -569,7 +595,9 @@ fn test_undef() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(scalable_vec_undef.is_undef()); assert!(ppc_f128_undef.is_undef()); @@ -599,7 +627,9 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_type = f64_type.scalable_vec_type(42); let ppc_f128_type = context.ppc_f128_type(); @@ -630,7 +660,9 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_val = scalable_vec_type.const_zero(); let ppc_f128_val = ppc_f128_type.const_float(0.0); @@ -656,7 +688,9 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(!scalable_vec_val.is_poison()); assert!(!ppc_f128_val.is_poison()); @@ -685,7 +719,9 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_poison = scalable_vec_type.get_poison(); let ppc_f128_poison = ppc_f128_type.get_poison(); @@ -711,7 +747,9 @@ fn test_poison() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(scalable_vec_poison.is_poison()); assert!(ppc_f128_poison.is_poison()); @@ -826,7 +864,7 @@ fn test_metadata() { let f32_type = context.f32_type(); // let f64_type = context.f64_type(); // let f128_type = context.f128_type(); - // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] // let ptr_type = context.ptr_type(AddressSpace::default()); // let array_type = f64_type.array_type(42); // let ppc_f128_type = context.ppc_f128_type(); @@ -843,9 +881,9 @@ fn test_metadata() { // let f64_val = f64_type.const_float(0.0); // let f128_val = f128_type.const_float(0.0); // let ppc_f128_val = ppc_f128_type.const_float(0.0); - // #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1")))] + // #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1")))] // let ptr_val = bool_type.ptr_type(AddressSpace::default()).const_null(); - // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1"))] + // #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1", feature = "llvm19-1", feature = "llvm20-1"))] // let ptr_val = ptr_type.const_null(); // let array_val = f64_type.const_array(&[f64_val]); // let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); @@ -948,7 +986,12 @@ fn test_metadata() { #[test] fn test_floats() { - #[cfg(not(any(feature = "llvm15-0", feature = "llvm18-1")))] + #[cfg(not(any( + feature = "llvm15-0", + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" + )))] { use inkwell::FloatPredicate; @@ -983,7 +1026,13 @@ fn test_floats() { let f64_one = f64_type.const_float(1.); let f64_two = f64_type.const_float(2.); - #[cfg(not(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-1")))] + #[cfg(not(any( + feature = "llvm16-0", + feature = "llvm17-0", + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" + )))] { let neg_two = f64_two.const_neg(); @@ -1493,7 +1542,9 @@ fn test_consts() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] let scalable_vec_val = f64_type.scalable_vec_type(42).const_zero(); let array_val = i8_type.const_array(&[i8_val]); @@ -1518,7 +1569,9 @@ fn test_consts() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] assert!(scalable_vec_val.is_const()); assert!(array_val.is_const()); @@ -1672,7 +1725,9 @@ fn test_non_fn_ptr_called() { feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", - feature = "llvm18-1" + feature = "llvm18-1", + feature = "llvm19-1", + feature = "llvm20-1" ))] builder .build_indirect_call(i8_ptr_type.fn_type(&[], false), i8_ptr_param, &[], "call") From 0b0a2c0b2eb5e458767093c2ab8c56cbd05ec4c9 Mon Sep 17 00:00:00 2001 From: Null <1135547+ErisianArchitect@users.noreply.github.com> Date: Wed, 13 Aug 2025 20:10:37 -0700 Subject: [PATCH 18/26] Removes uneccesary less-than 64-bit check on 32-bit value. (#593) --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index b7c7348a4bd..b38358fa357 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -3696,7 +3696,7 @@ fn is_alignment_ok(align: u32) -> bool { // This replicates the assertions LLVM runs. // // See https://github.com/TheDan64/inkwell/issues/168 - align > 0 && align.is_power_of_two() && (align as f64).log2() < 64.0 + align > 0 && align.is_power_of_two() } impl Drop for Builder<'_> { From 279ef78b3507a431e48767748c2335aef26b7d9f Mon Sep 17 00:00:00 2001 From: Null <1135547+ErisianArchitect@users.noreply.github.com> Date: Sat, 16 Aug 2025 07:35:27 -0700 Subject: [PATCH 19/26] Removed unnecessary checks from is_alignment_ok (#596) --- src/builder.rs | 3 ++- tests/all/test_builder.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b38358fa357..12d22d5349b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -3696,7 +3696,8 @@ fn is_alignment_ok(align: u32) -> bool { // This replicates the assertions LLVM runs. // // See https://github.com/TheDan64/inkwell/issues/168 - align > 0 && align.is_power_of_two() + // is_power_of_two returns false for 0. + align.is_power_of_two() } impl Drop for Builder<'_> { diff --git a/tests/all/test_builder.rs b/tests/all/test_builder.rs index 043e600d006..932b0191fd8 100644 --- a/tests/all/test_builder.rs +++ b/tests/all/test_builder.rs @@ -1311,7 +1311,8 @@ fn is_alignment_ok(align: u32) -> bool { // This replicates the assertions LLVM runs. // // See https://github.com/TheDan64/inkwell/issues/168 - align > 0 && align.is_power_of_two() && (align as f64).log2() < 64.0 + // is_power_of_two returns false for 0. + align.is_power_of_two() } #[test] From 7077b706d4cb3d92092cf27f52a9652b424d858e Mon Sep 17 00:00:00 2001 From: Null <1135547+ErisianArchitect@users.noreply.github.com> Date: Tue, 2 Sep 2025 22:58:58 -0700 Subject: [PATCH 20/26] More specific errors. (#598) * Add error.rs, create Error enum, and import Error into crate namespace. * More specific error types. * Fixes typo. * Alignment of 0 is invalid. * Missing #[from] attribute. * Formatting. * More formatting. * Hopefully final formatting commit. * Changes the alignment assertions to != 0, 0 is not a legal alignment. * Changed assertion to check if alignment is 16, which is the last valid set value. * Corrected BitwidthError message. --- src/builder.rs | 101 ++++++++++----------- src/debug_info.rs | 4 +- src/error.rs | 30 +++++++ src/lib.rs | 2 + src/module.rs | 4 +- src/values/instruction_value.rs | 128 +++++++++++++++++++-------- src/values/mod.rs | 4 +- tests/all/test_debug_info.rs | 2 +- tests/all/test_instruction_values.rs | 10 +-- 9 files changed, 183 insertions(+), 102 deletions(-) create mode 100644 src/error.rs diff --git a/src/builder.rs b/src/builder.rs index 12d22d5349b..29d3f69ad42 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -66,6 +66,7 @@ use crate::values::{ PointerMathValue, PointerValue, StructValue, VectorBaseValue, }; +use crate::error::AlignmentError; use crate::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; use std::cell::Cell; @@ -77,23 +78,35 @@ enum PositionState { Set, } +#[derive(Error, Debug, PartialEq, Eq)] +pub enum OrderingError { + #[error("Both success and failure orderings must be monotonic or stronger.")] + WeakerThanMonotic, + #[error("The failure ordering may not be stronger than the success ordering.")] + WeakerSuccessOrdering, + #[error("The failure ordering may not be release or acquire release.")] + ReleaseOrAcqRel, +} + /// Errors that can be generated by the Builder. All `build_*` methods return a `Result<_, BuilderError>`, which must be handled. #[derive(Error, Debug, PartialEq, Eq)] pub enum BuilderError { #[error("Builder position is not set")] UnsetPosition, #[error("Alignment error")] - AlignmentError(&'static str), + AlignmentError(#[from] crate::error::AlignmentError), #[error("Aggregate extract index out of range")] ExtractOutOfRange, - #[error("Bitwidth of a value is incorrect")] - BitwidthError(&'static str), + #[error("The bitwidth of value must be a power of 2 and greater than or equal to 8.")] + BitwidthError, #[error("Pointee type does not match the value's type")] - PointeeTypeMismatch(&'static str), - #[error("Values do not have the same type")] - ValueTypeMismatch(&'static str), + PointeeTypeMismatch, + #[error("Values must have the same type")] + NotSameType, + #[error("Values must have pointer or integer type")] + NotPointerOrInteger, #[error("Ordering error or mismatch")] - OrderingError(&'static str), + OrderingError(OrderingError), #[error("GEP pointee is not a struct")] GEPPointee, #[error("GEP index out of range")] @@ -1436,9 +1449,7 @@ impl<'ctx> Builder<'ctx> { #[cfg(feature = "llvm16-0")] let value = { if lhs_ptr.get_type().as_basic_type_enum() != rhs_ptr.get_type().as_basic_type_enum() { - return Err(BuilderError::ValueTypeMismatch( - "The values must have the same pointer type.", - )); + return Err(BuilderError::NotSameType); } unsafe { @@ -1718,15 +1729,15 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } if !is_alignment_ok(src_align_bytes) { - return Err(BuilderError::AlignmentError( - "The src_align_bytes argument to build_memcpy was not a power of 2.", - )); + return Err(BuilderError::AlignmentError(AlignmentError::SrcNonPowerOfTwo( + src_align_bytes, + ))); } if !is_alignment_ok(dest_align_bytes) { - return Err(BuilderError::AlignmentError( - "The dest_align_bytes argument to build_memcpy was not a power of 2.", - )); + return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo( + dest_align_bytes, + ))); } let value = unsafe { @@ -1765,15 +1776,15 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } if !is_alignment_ok(src_align_bytes) { - return Err(BuilderError::AlignmentError( - "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.", - )); + return Err(BuilderError::AlignmentError(AlignmentError::SrcNonPowerOfTwo( + src_align_bytes, + ))); } if !is_alignment_ok(dest_align_bytes) { - return Err(BuilderError::AlignmentError( - "The dest_align_bytes argument to build_memmove was not a power of 2 under 2^64.", - )); + return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo( + dest_align_bytes, + ))); } let value = unsafe { @@ -1811,9 +1822,9 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } if !is_alignment_ok(dest_align_bytes) { - return Err(BuilderError::AlignmentError( - "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.", - )); + return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo( + dest_align_bytes, + ))); } let value = unsafe { @@ -1837,9 +1848,7 @@ impl<'ctx> Builder<'ctx> { } // LLVMBuildMalloc segfaults if ty is unsized if !ty.is_sized() { - return Err(BuilderError::AlignmentError( - "Cannot build malloc call for an unsized type", - )); + return Err(BuilderError::AlignmentError(AlignmentError::Unsized)); } let c_string = to_c_str(name); @@ -1862,9 +1871,7 @@ impl<'ctx> Builder<'ctx> { } // LLVMBuildArrayMalloc segfaults if ty is unsized if !ty.is_sized() { - return Err(BuilderError::AlignmentError( - "Cannot build array malloc call for an unsized type", - )); + return Err(BuilderError::AlignmentError(AlignmentError::Unsized)); } let c_string = to_c_str(name); @@ -3507,16 +3514,12 @@ impl<'ctx> Builder<'ctx> { // "The type of ‘’ must be an integer type whose bit width is a power of two greater than or equal to eight and less than or equal to a target-specific size limit. The type of the ‘’ operand must be a pointer to that type." -- https://releases.llvm.org/3.6.2/docs/LangRef.html#atomicrmw-instruction if value.get_type().get_bit_width() < 8 || !value.get_type().get_bit_width().is_power_of_two() { - return Err(BuilderError::BitwidthError( - "The bitwidth of value must be a power of 2 and greater than 8.", - )); + return Err(BuilderError::BitwidthError); } #[cfg(feature = "typed-pointers")] if ptr.get_type().get_element_type() != value.get_type().into() { - return Err(BuilderError::PointeeTypeMismatch( - "Pointer's pointee type must match the value's type.", - )); + return Err(BuilderError::PointeeTypeMismatch); } let val = unsafe { @@ -3584,38 +3587,26 @@ impl<'ctx> Builder<'ctx> { let cmp = cmp.as_basic_value_enum(); let new = new.as_basic_value_enum(); if cmp.get_type() != new.get_type() { - return Err(BuilderError::ValueTypeMismatch( - "The value to compare against and the value to replace with must have the same type.", - )); + return Err(BuilderError::NotSameType); } if !cmp.is_int_value() && !cmp.is_pointer_value() { - return Err(BuilderError::ValueTypeMismatch( - "The values must have pointer or integer type.", - )); + return Err(BuilderError::NotPointerOrInteger); } #[cfg(feature = "typed-pointers")] if ptr.get_type().get_element_type().as_basic_type_enum() != cmp.get_type() { - return Err(BuilderError::PointeeTypeMismatch( - "The pointer does not point to an element of the value type.", - )); + return Err(BuilderError::PointeeTypeMismatch); } // "Both ordering parameters must be at least monotonic, the ordering constraint on failure must be no stronger than that on success, and the failure ordering cannot be either release or acq_rel." -- https://llvm.org/docs/LangRef.html#cmpxchg-instruction if success < AtomicOrdering::Monotonic || failure < AtomicOrdering::Monotonic { - return Err(BuilderError::OrderingError( - "Both success and failure orderings must be Monotonic or stronger.", - )); + return Err(BuilderError::OrderingError(OrderingError::WeakerThanMonotic)); } if failure > success { - return Err(BuilderError::OrderingError( - "The failure ordering may not be stronger than the success ordering.", - )); + return Err(BuilderError::OrderingError(OrderingError::WeakerSuccessOrdering)); } if failure == AtomicOrdering::Release || failure == AtomicOrdering::AcquireRelease { - return Err(BuilderError::OrderingError( - "The failure ordering may not be release or acquire release.", - )); + return Err(BuilderError::OrderingError(OrderingError::ReleaseOrAcqRel)); } let val = unsafe { diff --git a/src/debug_info.rs b/src/debug_info.rs index c6ce218ce24..e33da152d24 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -537,11 +537,11 @@ impl<'ctx> DebugInfoBuilder<'ctx> { size_in_bits: u64, encoding: LLVMDWARFTypeEncoding, flags: DIFlags, - ) -> Result, &'static str> { + ) -> Result, crate::error::Error> { if name.is_empty() { // Also, LLVM returns the same type if you ask for the same // (name, size_in_bits, encoding). - return Err("basic types must have names"); + return Err(crate::error::Error::EmptyNameError); } let metadata_ref = unsafe { LLVMDIBuilderCreateBasicType( diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000000..3e6e10831c3 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,30 @@ +/// Errors for operations involving alignment. +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum AlignmentError { + #[error("{0} is not a power of two and cannot be used for alignment")] + NonPowerOfTwo(u32), + #[error("The src_align_bytes argument was not a power of two.")] + SrcNonPowerOfTwo(u32), + #[error("The dest_align_bytes argument was not a power of two.")] + DestNonPowerOfTwo(u32), + #[error( + "Type is unsized and cannot be aligned. \ + Suggestion: Align memory manually." + )] + Unsized, + #[error("Value is not an alloca, load, or store instruction.")] + UnalignedInstruction, +} + +/// The top-level Error type for the inkwell crate. +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum Error { + #[error("Builder Error: {0}")] + BuilderError(#[from] crate::builder::BuilderError), + #[error("InstructionValue Error: {0}")] + InstructionValueError(#[from] crate::values::InstructionValueError), + #[error("Basic types must have names.")] + EmptyNameError, + #[error("Metadata is expected to be a node.")] + GlobalMetadataError, +} diff --git a/src/lib.rs b/src/lib.rs index 53c36e10973..3788bf4a86f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,7 @@ pub mod comdat; pub mod context; pub mod data_layout; pub mod debug_info; +pub mod error; pub mod execution_engine; #[cfg(not(feature = "llvm8-0"))] pub mod intrinsics; @@ -78,6 +79,7 @@ use llvm_sys::{ use llvm_sys::LLVMInlineAsmDialect; pub use either::Either; +pub use error::Error; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::convert::TryFrom; diff --git a/src/module.rs b/src/module.rs index 41509f976d0..ed096ecfa8f 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1037,9 +1037,9 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(md_1[0].into_int_value(), bool_val); /// assert_eq!(md_1[1].into_float_value(), f32_val); /// ``` - pub fn add_global_metadata(&self, key: &str, metadata: &MetadataValue<'ctx>) -> Result<(), &'static str> { + pub fn add_global_metadata(&self, key: &str, metadata: &MetadataValue<'ctx>) -> Result<(), crate::Error> { if !metadata.is_node() { - return Err("metadata is expected to be a node."); + return Err(crate::Error::GlobalMetadataError); } let c_string = to_c_str(key); diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 5bd2eb9d490..043007c9c49 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -20,6 +20,7 @@ use llvm_sys::LLVMOpcode; use std::{ffi::CStr, fmt, fmt::Display}; +use crate::error::AlignmentError; use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, MetadataValue, Value}; use crate::{basic_block::BasicBlock, types::AnyTypeEnum}; use crate::{types::BasicTypeEnum, values::traits::AsValueRef}; @@ -27,6 +28,61 @@ use crate::{AtomicOrdering, FloatPredicate, IntPredicate}; use super::AnyValue; +/// Errors for atomic operations on load/store instructions. +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum AtomicError { + #[error("The release ordering is not valid on load instructions.")] + ReleaseOnLoad, + #[error("The acq_rel ordering is not valid on load or store instructions.")] + AcquireRelease, + #[error("The acquire ordering is not valid on store instructions.")] + AcquireOnStore, +} + +/// Errors for InstructionValue. +#[llvm_versions(..=9)] +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum InstructionValueError { + #[error("Cannot set name of a void-type instruction.")] + CannotNameVoidTypeInst, + #[error("Value is not a load or store instruction.")] + NotMemoryAccessInst, + #[error("Value is not a load or store instruction.")] + NotLoadOrStoreInst, + #[error("Value is not an alloca instruction.")] + NotAllocaInst, + #[error("Alignment Error: {0}")] + AlignmentError(AlignmentError), + #[error("Not a GEP instruction.")] + NotGEPInst, + #[error("Atomic Error: {0}")] + AtomicError(#[from] AtomicError), + #[error("Metadata is expected to be a node.")] + ExpectedNode, +} + +/// Errors for InstructionValue. +#[llvm_versions(10..)] +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum InstructionValueError { + #[error("Cannot set name of a void-type instruction.")] + CannotNameVoidTypeInst, + #[error("Value is not a load, store, atomicrmw or cmpxchg instruction.")] + NotMemoryAccessInst, + #[error("Value is not a load or store instruction.")] + NotLoadOrStoreInst, + #[error("Value is not an alloca instruction.")] + NotAllocaInst, + #[error("Alignment Error: {0}")] + AlignmentError(AlignmentError), + #[error("Not a GEP instruction.")] + NotGEPInst, + #[error("Atomic Error: {0}")] + AtomicError(AtomicError), + #[error("Metadata is expected to be a node.")] + ExpectedNode, +} + // REVIEW: Split up into structs for SubTypes on InstructionValues? // REVIEW: This should maybe be split up into InstructionOpcode and ConstOpcode? // see LLVMGetConstOpcode @@ -179,9 +235,9 @@ impl<'ctx> InstructionValue<'ctx> { } /// Set name of the `InstructionValue`. - pub fn set_name(&self, name: &str) -> Result<(), &'static str> { + pub fn set_name(&self, name: &str) -> Result<(), InstructionValueError> { if self.get_type().is_void_type() { - Err("Cannot set name of a void-type instruction!") + Err(InstructionValueError::CannotNameVoidTypeInst) } else { self.instruction_value.set_name(name); Ok(()) @@ -350,11 +406,11 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to memory access instructions /// Returns whether or not a memory access instruction is volatile. #[llvm_versions(..=9)] - pub fn get_volatile(self) -> Result { + pub fn get_volatile(self) -> Result { // Although cmpxchg and atomicrmw can have volatile, LLVM's C API // does not export that functionality until 10.0. if !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not a load or store."); + return Err(InstructionValueError::NotMemoryAccessInst); } Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1) } @@ -362,10 +418,10 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to memory access instructions /// Returns whether or not a memory access instruction is volatile. #[llvm_versions(10..)] - pub fn get_volatile(self) -> Result { + pub fn get_volatile(self) -> Result { if !self.is_a_load_inst() && !self.is_a_store_inst() && !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst() { - return Err("Value is not a load, store, atomicrmw or cmpxchg."); + return Err(InstructionValueError::NotMemoryAccessInst); } Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1) } @@ -373,11 +429,11 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to memory access instructions /// Sets whether or not a memory access instruction is volatile. #[llvm_versions(..=9)] - pub fn set_volatile(self, volatile: bool) -> Result<(), &'static str> { + pub fn set_volatile(self, volatile: bool) -> Result<(), InstructionValueError> { // Although cmpxchg and atomicrmw can have volatile, LLVM's C API // does not export that functionality until 10.0. if !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not a load or store."); + return Err(InstructionValueError::NotMemoryAccessInst); } unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) }; Ok(()) @@ -386,10 +442,10 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to memory access instructions /// Sets whether or not a memory access instruction is volatile. #[llvm_versions(10..)] - pub fn set_volatile(self, volatile: bool) -> Result<(), &'static str> { + pub fn set_volatile(self, volatile: bool) -> Result<(), InstructionValueError> { if !self.is_a_load_inst() && !self.is_a_store_inst() && !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst() { - return Err("Value is not a load, store, atomicrmw or cmpxchg."); + return Err(InstructionValueError::NotMemoryAccessInst); } unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) }; Ok(()) @@ -397,9 +453,9 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to alloca instruction /// Returns the type that is allocated by the alloca instruction. - pub fn get_allocated_type(self) -> Result, &'static str> { + pub fn get_allocated_type(self) -> Result, InstructionValueError> { if !self.is_a_alloca_inst() { - return Err("Value is not an alloca."); + return Err(InstructionValueError::NotAllocaInst); } Ok(unsafe { BasicTypeEnum::new(LLVMGetAllocatedType(self.as_value_ref())) }) } @@ -407,37 +463,37 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to GetElementPtr instruction /// Returns the source element type of the given GEP. #[llvm_versions(14..)] - pub fn get_gep_source_element_type(self) -> Result, &'static str> { + pub fn get_gep_source_element_type(self) -> Result, InstructionValueError> { if !self.is_a_getelementptr_inst() { - return Err("Value is not a GEP."); + return Err(InstructionValueError::NotGEPInst); } Ok(unsafe { BasicTypeEnum::new(LLVMGetGEPSourceElementType(self.as_value_ref())) }) } // SubTypes: Only apply to memory access and alloca instructions /// Returns alignment on a memory access instruction or alloca. - pub fn get_alignment(self) -> Result { + pub fn get_alignment(self) -> Result { if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not an alloca, load or store."); + return Err(InstructionValueError::AlignmentError( + AlignmentError::UnalignedInstruction, + )); } Ok(unsafe { LLVMGetAlignment(self.as_value_ref()) }) } // SubTypes: Only apply to memory access and alloca instructions /// Sets alignment on a memory access instruction or alloca. - pub fn set_alignment(self, alignment: u32) -> Result<(), &'static str> { - #[cfg(any(feature = "llvm11-0", feature = "llvm12-0"))] - { - if alignment == 0 { - return Err("Alignment cannot be 0"); - } - } - //The alignment = 0 check above covers LLVM >= 11, the != 0 check here keeps older versions compatible - if !alignment.is_power_of_two() && alignment != 0 { - return Err("Alignment is not a power of 2!"); + pub fn set_alignment(self, alignment: u32) -> Result<(), InstructionValueError> { + // Zero check is unnecessary as 0 is not a power of two. + if !alignment.is_power_of_two() { + return Err(InstructionValueError::AlignmentError(AlignmentError::NonPowerOfTwo( + alignment, + ))); } if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not an alloca, load or store."); + return Err(InstructionValueError::AlignmentError( + AlignmentError::UnalignedInstruction, + )); } unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) }; Ok(()) @@ -445,31 +501,31 @@ impl<'ctx> InstructionValue<'ctx> { // SubTypes: Only apply to memory access instructions /// Returns atomic ordering on a memory access instruction. - pub fn get_atomic_ordering(self) -> Result { + pub fn get_atomic_ordering(self) -> Result { if !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not a load or store."); + return Err(InstructionValueError::NotLoadOrStoreInst); } Ok(unsafe { LLVMGetOrdering(self.as_value_ref()) }.into()) } // SubTypes: Only apply to memory access instructions /// Sets atomic ordering on a memory access instruction. - pub fn set_atomic_ordering(self, ordering: AtomicOrdering) -> Result<(), &'static str> { + pub fn set_atomic_ordering(self, ordering: AtomicOrdering) -> Result<(), InstructionValueError> { // Although fence and atomicrmw both have an ordering, the LLVM C API // does not support them. The cmpxchg instruction has two orderings and // does not work with this API. if !self.is_a_load_inst() && !self.is_a_store_inst() { - return Err("Value is not a load or store instruction."); + return Err(InstructionValueError::NotLoadOrStoreInst); } match ordering { AtomicOrdering::Release if self.is_a_load_inst() => { - return Err("The release ordering is not valid on load instructions.") + return Err(InstructionValueError::AtomicError(AtomicError::ReleaseOnLoad)) }, AtomicOrdering::AcquireRelease => { - return Err("The acq_rel ordering is not valid on load or store instructions.") + return Err(InstructionValueError::AtomicError(AtomicError::AcquireRelease)) }, AtomicOrdering::Acquire if self.is_a_store_inst() => { - return Err("The acquire ordering is not valid on store instructions.") + return Err(InstructionValueError::AtomicError(AtomicError::AcquireOnStore)) }, _ => {}, }; @@ -849,9 +905,9 @@ impl<'ctx> InstructionValue<'ctx> { /// Determines whether or not this `Instruction` has any associated metadata /// `kind_id`. - pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) -> Result<(), &'static str> { + pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) -> Result<(), InstructionValueError> { if !metadata.is_node() { - return Err("metadata is expected to be a node."); + return Err(InstructionValueError::ExpectedNode); } unsafe { diff --git a/src/values/mod.rs b/src/values/mod.rs index a4db54f4b9b..9edca9206a2 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -58,7 +58,9 @@ pub use crate::values::generic_value::GenericValue; pub use crate::values::global_value::GlobalValue; pub use crate::values::global_value::UnnamedAddress; -pub use crate::values::instruction_value::{InstructionOpcode, InstructionValue, OperandIter, OperandUseIter}; +pub use crate::values::instruction_value::{ + AtomicError, InstructionOpcode, InstructionValue, InstructionValueError, OperandIter, OperandUseIter, +}; pub use crate::values::int_value::IntValue; pub use crate::values::metadata_value::{MetadataValue, FIRST_CUSTOM_METADATA_KIND_ID}; pub use crate::values::phi_value::IncomingIter; diff --git a/tests/all/test_debug_info.rs b/tests/all/test_debug_info.rs index 8b4ce5c7ac4..b7ca7cffd8f 100644 --- a/tests/all/test_debug_info.rs +++ b/tests/all/test_debug_info.rs @@ -366,7 +366,7 @@ fn test_anonymous_basic_type() { assert_eq!( dibuilder.create_basic_type("", 0_u64, 0x00, DIFlags::ZERO), - Err("basic types must have names") + Err(inkwell::Error::EmptyNameError) ); } diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 8aa07408658..6eaed48b414 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -455,13 +455,13 @@ fn test_mem_instructions() { assert!(load_instruction.set_alignment(16).is_ok()); assert_eq!(store_instruction.get_alignment().unwrap(), 16); assert_eq!(load_instruction.get_alignment().unwrap(), 16); - assert!(store_instruction.set_alignment(0).is_ok()); - assert!(load_instruction.set_alignment(0).is_ok()); - assert_eq!(store_instruction.get_alignment().unwrap(), 0); - assert_eq!(load_instruction.get_alignment().unwrap(), 0); + assert!(store_instruction.set_alignment(0).is_err()); + assert!(load_instruction.set_alignment(0).is_err()); + assert_eq!(store_instruction.get_alignment().unwrap(), 16); + assert_eq!(load_instruction.get_alignment().unwrap(), 16); assert!(store_instruction.set_alignment(14).is_err()); - assert_eq!(store_instruction.get_alignment().unwrap(), 0); + assert_eq!(store_instruction.get_alignment().unwrap(), 16); let fadd_instruction = builder .build_float_add(load.into_float_value(), f32_val, "") From e29a3d068f35918316777508afcbc96b5c80537c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=82=A4=E3=83=A9?= Date: Wed, 3 Sep 2025 22:50:21 +0800 Subject: [PATCH 21/26] feat: make BasicBlock::new publicly accessible (#601) * Update basic_block.rs * docs: Add documentation for BasicBlock::new method --------- Co-authored-by: Dan Kolsoi --- src/basic_block.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/basic_block.rs b/src/basic_block.rs index f7996d6e341..da41ee85c38 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -31,7 +31,12 @@ pub struct BasicBlock<'ctx> { } impl<'ctx> BasicBlock<'ctx> { - pub(crate) unsafe fn new(basic_block: LLVMBasicBlockRef) -> Option { + /// Create a basic block from an [LLVMBasicBlockRef]. + /// + /// # Safety + /// + /// The ref must be valid and point to a valid LLVM basic block. + pub unsafe fn new(basic_block: LLVMBasicBlockRef) -> Option { if basic_block.is_null() { return None; } From 075db5c0f535c500f9e801313e570206ab28f613 Mon Sep 17 00:00:00 2001 From: Quincy Poynter <78283505+qlpoynter@users.noreply.github.com> Date: Mon, 22 Sep 2025 17:11:59 -0700 Subject: [PATCH 22/26] Fix comment typos in `test_conversion_to_pointer_value` (#605) --- tests/all/test_instruction_conversion.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/all/test_instruction_conversion.rs b/tests/all/test_instruction_conversion.rs index 371319698ad..eadabf93670 100644 --- a/tests/all/test_instruction_conversion.rs +++ b/tests/all/test_instruction_conversion.rs @@ -103,7 +103,7 @@ fn test_conversion_to_pointer_value() { let module = context.create_module("testing"); let builder = context.create_builder(); - // Create a function whose the first parameter is of IntType + // Create a function with no parameters let fn_type = context.void_type().fn_type(&[], false); let function = module.add_function("testing", fn_type, None); let basic_block = context.append_basic_block(function, "entry"); @@ -120,7 +120,7 @@ fn test_conversion_to_pointer_value() { .as_instruction() .unwrap(); - // Test the instruction conversion to a FloatValue + // Test the instruction conversion to a PointerValue let ptr_conversion: Result = alloca_instr.try_into(); assert!(ptr_conversion.is_ok()); From 0f8d2d6c9061cfe80d3e83b75ea00f6df94ee562 Mon Sep 17 00:00:00 2001 From: Null <1135547+ErisianArchitect@users.noreply.github.com> Date: Fri, 17 Oct 2025 19:31:08 -0700 Subject: [PATCH 23/26] All tests passing on Windows. (#608) * test_default_triple fix * All tests passing on Windows. * Formatting. * Formatting. * Formatting. * Forgot to configure windows dep for windows. * I think it should work now. * I don't know what I'm doing. * Hopefully this satisfies clippy. * I could have sworn that I just committed this. --- Cargo.toml | 7 ++++ tests/all/test_execution_engine.rs | 63 ++++++++++++++++++++++++++++++ tests/all/test_module.rs | 34 ++++++++++++---- tests/all/test_object_file.rs | 3 ++ tests/all/test_targets.rs | 19 +++++---- 5 files changed, 111 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0106e316b8..ea6a8b26de4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -170,5 +170,12 @@ serde = { version = "1.0", default-features = false, features = [ gumdrop = "0.8.1" regex = "1" +[target.'cfg(windows)'.dev-dependencies.windows] +version = "0.62.2" +features = [ + "Win32_System_SystemInformation", + "Win32_System_Memory" +] + [badges] codecov = { repository = "TheDan64/inkwell" } diff --git a/tests/all/test_execution_engine.rs b/tests/all/test_execution_engine.rs index 925f6d3a604..84b7dd7e190 100644 --- a/tests/all/test_execution_engine.rs +++ b/tests/all/test_execution_engine.rs @@ -8,6 +8,15 @@ use inkwell::module::Linkage; use inkwell::targets::{CodeModel, InitializationConfig, Target}; use inkwell::{AddressSpace, IntPredicate, OptimizationLevel}; +#[cfg(target_os = "windows")] +use windows::Win32::System::{ + Memory::{ + VirtualAlloc, VirtualFree, VirtualProtect, MEM_COMMIT, MEM_RELEASE, MEM_RESERVE, PAGE_EXECUTE_READ, + PAGE_READWRITE, + }, + SystemInformation::{GetSystemInfo, SYSTEM_INFO}, +}; + type Thunk = unsafe extern "C" fn(); #[test] @@ -374,8 +383,20 @@ struct MockMemoryManagerData { impl MockMemoryManager { pub fn new() -> Self { let capacity_bytes = 128 * 1024; + #[cfg(unix)] let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }; + #[cfg(target_os = "windows")] + let page_size = { + let mut info = std::mem::MaybeUninit::::uninit(); + unsafe { + GetSystemInfo(info.as_mut_ptr()); + } + let info = unsafe { info.assume_init() }; + info.dwPageSize as usize + }; + + #[cfg(unix)] let code_buff_ptr = unsafe { std::ptr::NonNull::new_unchecked(libc::mmap( std::ptr::null_mut(), @@ -387,6 +408,14 @@ impl MockMemoryManager { ) as *mut u8) }; + #[cfg(target_os = "windows")] + let code_buff_ptr = unsafe { + std::ptr::NonNull::new_unchecked( + VirtualAlloc(None, capacity_bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE).cast::(), + ) + }; + + #[cfg(unix)] let data_buff_ptr = unsafe { std::ptr::NonNull::new_unchecked(libc::mmap( std::ptr::null_mut(), @@ -398,6 +427,13 @@ impl MockMemoryManager { ) as *mut u8) }; + #[cfg(target_os = "windows")] + let data_buff_ptr = unsafe { + std::ptr::NonNull::new_unchecked( + VirtualAlloc(None, capacity_bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE).cast::(), + ) + }; + Self { data: Rc::new(RefCell::new(MockMemoryManagerData { fixed_capacity_bytes: capacity_bytes, @@ -460,6 +496,7 @@ impl McjitMemoryManager for MockMemoryManager { data.finalize_calls += 1; + #[cfg(unix)] unsafe { libc::mprotect( data.code_buff_ptr.as_ptr() as *mut libc::c_void, @@ -473,6 +510,25 @@ impl McjitMemoryManager for MockMemoryManager { ); } + #[cfg(windows)] + unsafe { + let mut old_protect = PAGE_READWRITE; + VirtualProtect( + data.code_buff_ptr.as_ptr() as *mut _, + data.fixed_capacity_bytes, + PAGE_EXECUTE_READ, + &mut old_protect, + ) + .expect("VirtualProtect failed"); + VirtualProtect( + data.data_buff_ptr.as_ptr() as *mut _, + data.fixed_capacity_bytes, + PAGE_READWRITE, + &mut old_protect, + ) + .expect("VirtualProtect failed"); + } + Ok(()) } @@ -481,6 +537,7 @@ impl McjitMemoryManager for MockMemoryManager { data.destroy_calls += 1; + #[cfg(unix)] unsafe { libc::munmap( data.code_buff_ptr.as_ptr() as *mut libc::c_void, @@ -491,5 +548,11 @@ impl McjitMemoryManager for MockMemoryManager { data.fixed_capacity_bytes, ); } + + #[cfg(windows)] + unsafe { + VirtualFree(data.code_buff_ptr.as_ptr() as *mut _, 0, MEM_RELEASE).expect("Failed to free memory."); + VirtualFree(data.data_buff_ptr.as_ptr() as *mut _, 0, MEM_RELEASE).expect("Failed to free memory."); + } } } diff --git a/tests/all/test_module.rs b/tests/all/test_module.rs index 426a9074db8..5ee645912e7 100644 --- a/tests/all/test_module.rs +++ b/tests/all/test_module.rs @@ -305,7 +305,7 @@ fn test_clone() { } #[test] -fn test_print_to_file() { +fn test_print_to_file_good_path() { let context = Context::create(); let module = context.create_module("mod"); let void_type = context.void_type(); @@ -317,13 +317,6 @@ fn test_print_to_file() { builder.position_at_end(basic_block); builder.build_return(None).unwrap(); - let bad_path = Path::new("/tmp/some/silly/path/that/sure/doesn't/exist"); - - assert_eq!( - module.print_to_file(bad_path).unwrap_err().to_str(), - Ok("No such file or directory") - ); - let mut temp_path = temp_dir(); temp_path.push("module"); @@ -331,6 +324,31 @@ fn test_print_to_file() { assert!(module.print_to_file(&temp_path).is_ok()); } +#[test] +fn test_print_to_file_bad_path() { + let context = Context::create(); + let module = context.create_module("mod"); + let void_type = context.void_type(); + let fn_type = void_type.fn_type(&[], false); + let f = module.add_function("f", fn_type, None); + let basic_block = context.append_basic_block(f, "entry"); + let builder = context.create_builder(); + + builder.position_at_end(basic_block); + builder.build_return(None).unwrap(); + + #[cfg(unix)] + let bad_path = Path::new("/tmp/some/silly/path/that/sure/doesn't/exist"); + #[cfg(windows)] + let bad_path = Path::new("/does/not/exist/hopefully"); + + match module.print_to_file(bad_path).unwrap_err().to_str() { + Ok("no such file or directory") | Ok("No such file or directory") => (), + Ok(err) => panic!("Some other error: {err}"), + Err(_) => panic!("Should have failed."), + } +} + #[test] fn test_get_set_target() { Target::initialize_x86(&Default::default()); diff --git a/tests/all/test_object_file.rs b/tests/all/test_object_file.rs index e5cb6e741f4..82449af465f 100644 --- a/tests/all/test_object_file.rs +++ b/tests/all/test_object_file.rs @@ -154,7 +154,10 @@ fn test_symbol_iterator() { "a" => { assert!(!has_symbol_a); has_symbol_a = true; + #[cfg(unix)] assert_eq!(symbol.size(), 1); + #[cfg(windows)] + assert_eq!(symbol.size(), 0); }, "b" => { assert!(!has_symbol_b); diff --git a/tests/all/test_targets.rs b/tests/all/test_targets.rs index 81443882bde..40768fdbf50 100644 --- a/tests/all/test_targets.rs +++ b/tests/all/test_targets.rs @@ -186,6 +186,8 @@ fn test_default_triple() { vec!["pc", "unknown", "redhat"] } else if cfg!(target_os = "macos") { vec!["apple"] + } else if cfg!(target_os = "windows") { + vec!["pc", "unknown", "uwp"] } else { vec![] }; @@ -193,13 +195,16 @@ fn test_default_triple() { let has_known_vendor = vendors.iter().any(|vendor| default_triple.contains(*vendor)); assert!(has_known_vendor, "Target triple '{default_triple}' has unknown vendor"); - let os = [ - #[cfg(target_os = "linux")] - "linux", - #[cfg(target_os = "macos")] - "darwin", - ]; - let has_known_os = os.iter().any(|os| default_triple.contains(*os)); + let has_known_os = if cfg!(target_os = "linux") { + default_triple.contains("linux") + } else if cfg!(target_os = "macos") { + default_triple.contains("macos") + } else if cfg!(target_os = "windows") { + default_triple.contains("windows") + } else { + false + }; + assert!(has_known_os, "Target triple '{default_triple}' has unknown OS"); // TODO: CFG for other supported major OSes From 5b64e21a94315b7aeec0098f8de22e5dd3fb0175 Mon Sep 17 00:00:00 2001 From: Nam Se Hyun <3580430+namse@users.noreply.github.com> Date: Fri, 31 Oct 2025 13:21:32 +0900 Subject: [PATCH 24/26] Support LLVMGetIndices (#615) * Support LLVMGetIndices * Pass doc test --- src/values/instruction_value.rs | 95 +++++++++++++++++++++++-- tests/all/test_instruction_values.rs | 102 +++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 6 deletions(-) diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 043007c9c49..006d93bf573 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -5,12 +5,13 @@ use either::{ #[llvm_versions(14..)] use llvm_sys::core::LLVMGetGEPSourceElementType; use llvm_sys::core::{ - LLVMGetAlignment, LLVMGetAllocatedType, LLVMGetFCmpPredicate, LLVMGetICmpPredicate, LLVMGetInstructionOpcode, - LLVMGetInstructionParent, LLVMGetMetadata, LLVMGetNextInstruction, LLVMGetNumOperands, LLVMGetOperand, - LLVMGetOperandUse, LLVMGetPreviousInstruction, LLVMGetVolatile, LLVMHasMetadata, LLVMInstructionClone, - LLVMInstructionEraseFromParent, LLVMInstructionRemoveFromParent, LLVMIsAAllocaInst, LLVMIsABasicBlock, - LLVMIsAGetElementPtrInst, LLVMIsALoadInst, LLVMIsAStoreInst, LLVMIsATerminatorInst, LLVMIsConditional, - LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand, LLVMSetVolatile, LLVMValueAsBasicBlock, + LLVMGetAlignment, LLVMGetAllocatedType, LLVMGetFCmpPredicate, LLVMGetICmpPredicate, LLVMGetIndices, + LLVMGetInstructionOpcode, LLVMGetInstructionParent, LLVMGetMetadata, LLVMGetNextInstruction, LLVMGetNumIndices, + LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMGetPreviousInstruction, LLVMGetVolatile, + LLVMHasMetadata, LLVMInstructionClone, LLVMInstructionEraseFromParent, LLVMInstructionRemoveFromParent, + LLVMIsAAllocaInst, LLVMIsABasicBlock, LLVMIsAGetElementPtrInst, LLVMIsALoadInst, LLVMIsAStoreInst, + LLVMIsATerminatorInst, LLVMIsConditional, LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand, + LLVMSetVolatile, LLVMValueAsBasicBlock, }; use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering}; #[llvm_versions(10..)] @@ -813,6 +814,88 @@ impl<'ctx> InstructionValue<'ctx> { } } + /// Obtains the number of indices an `InstructionValue` has. + /// An index is used in `ExtractValue` and `InsertValue` instructions to specify + /// which field or element to access in an aggregate type (struct or array). + /// + /// Returns 0 for instructions that are not `ExtractValue` or `InsertValue`. + /// + /// The following example, + /// + /// ```no_run + /// use inkwell::context::Context; + /// use inkwell::values::BasicValue; + /// + /// let context = Context::create(); + /// let module = context.create_module("ivs"); + /// let builder = context.create_builder(); + /// let void_type = context.void_type(); + /// let i32_type = context.i32_type(); + /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false); + /// let fn_type = void_type.fn_type(&[], false); + /// + /// let function = module.add_function("test", fn_type, None); + /// let basic_block = context.append_basic_block(function, "entry"); + /// + /// builder.position_at_end(basic_block); + /// + /// let struct_val = struct_type.get_undef(); + /// let extract_instruction = builder.build_extract_value(struct_val, 0, "extract").unwrap() + /// .as_instruction_value().unwrap(); + /// + /// assert_eq!(extract_instruction.get_num_indices(), 1); + /// ``` + pub fn get_num_indices(self) -> u32 { + let opcode = self.get_opcode(); + if opcode != InstructionOpcode::ExtractValue && opcode != InstructionOpcode::InsertValue { + return 0; + } + unsafe { LLVMGetNumIndices(self.as_value_ref()) } + } + + /// Obtains the indices an `InstructionValue` has as a vector. + /// An index is used in `ExtractValue` and `InsertValue` instructions to specify + /// which field or element to access in an aggregate type (struct or array). + /// + /// Returns an empty vector for instructions that are not `ExtractValue` or `InsertValue`. + /// + /// The following example, + /// + /// ```no_run + /// use inkwell::context::Context; + /// use inkwell::values::BasicValue; + /// + /// let context = Context::create(); + /// let module = context.create_module("ivs"); + /// let builder = context.create_builder(); + /// let void_type = context.void_type(); + /// let i32_type = context.i32_type(); + /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false); + /// let fn_type = void_type.fn_type(&[], false); + /// + /// let function = module.add_function("test", fn_type, None); + /// let basic_block = context.append_basic_block(function, "entry"); + /// + /// builder.position_at_end(basic_block); + /// + /// let struct_val = struct_type.get_undef(); + /// let extract_instruction = builder.build_extract_value(struct_val, 0, "extract").unwrap() + /// .as_instruction_value().unwrap(); + /// + /// assert_eq!(extract_instruction.get_indices(), vec![0]); + /// ``` + pub fn get_indices(self) -> Vec { + let num_indices = self.get_num_indices(); + if num_indices == 0 { + return Vec::new(); + } + + unsafe { + let indices_ptr = LLVMGetIndices(self.as_value_ref()); + std::slice::from_raw_parts(indices_ptr, num_indices as usize).to_vec() + } + } + /// Gets the first use of an `InstructionValue` if any. /// /// The following example, diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 6eaed48b414..a790ee38197 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -804,3 +804,105 @@ fn test_or_disjoint_flag() { assert_eq!(i32_and.get_disjoint_flag(), None); } + +#[test] +fn test_instruction_indices() { + let context = Context::create(); + let module = context.create_module("testing"); + let builder = context.create_builder(); + + let void_type = context.void_type(); + let i32_type = context.i32_type(); + let f32_type = context.f32_type(); + let struct_type = context.struct_type(&[i32_type.into(), f32_type.into(), i32_type.into()], false); + let array_type = i32_type.array_type(3); + let fn_type = void_type.fn_type(&[], false); + + let function = module.add_function("test_indices", fn_type, None); + let basic_block = context.append_basic_block(function, "entry"); + + builder.position_at_end(basic_block); + + // Create actual instruction values by using alloca and load + let struct_alloca = builder.build_alloca(struct_type, "struct_alloca").unwrap(); + #[cfg(feature = "typed-pointers")] + let struct_val = builder.build_load(struct_alloca, "struct_load").unwrap(); + #[cfg(not(feature = "typed-pointers"))] + let struct_val = builder.build_load(struct_type, struct_alloca, "struct_load").unwrap(); + + // Test with struct ExtractValue - now these will be instructions + let extract_struct_0 = builder + .build_extract_value(struct_val.into_struct_value(), 0, "extract_0") + .unwrap() + .as_instruction_value() + .unwrap(); + let extract_struct_1 = builder + .build_extract_value(struct_val.into_struct_value(), 1, "extract_1") + .unwrap() + .as_instruction_value() + .unwrap(); + let extract_struct_2 = builder + .build_extract_value(struct_val.into_struct_value(), 2, "extract_2") + .unwrap() + .as_instruction_value() + .unwrap(); + + assert_eq!(extract_struct_0.get_num_indices(), 1); + assert_eq!(extract_struct_0.get_indices(), vec![0]); + assert_eq!(extract_struct_1.get_num_indices(), 1); + assert_eq!(extract_struct_1.get_indices(), vec![1]); + assert_eq!(extract_struct_2.get_num_indices(), 1); + assert_eq!(extract_struct_2.get_indices(), vec![2]); + + // Test with array ExtractValue + let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); + #[cfg(feature = "typed-pointers")] + let array_val = builder.build_load(array_alloca, "array_load").unwrap(); + #[cfg(not(feature = "typed-pointers"))] + let array_val = builder.build_load(array_type, array_alloca, "array_load").unwrap(); + + let extract_array_0 = builder + .build_extract_value(array_val.into_array_value(), 0, "extract_arr_0") + .unwrap() + .as_instruction_value() + .unwrap(); + let extract_array_1 = builder + .build_extract_value(array_val.into_array_value(), 1, "extract_arr_1") + .unwrap() + .as_instruction_value() + .unwrap(); + + assert_eq!(extract_array_0.get_num_indices(), 1); + assert_eq!(extract_array_0.get_indices(), vec![0]); + assert_eq!(extract_array_1.get_num_indices(), 1); + assert_eq!(extract_array_1.get_indices(), vec![1]); + + // Test with InsertValue + let i32_val = i32_type.const_int(42, false); + let insert_struct_0 = builder + .build_insert_value(struct_val.into_struct_value(), i32_val, 0, "insert_0") + .unwrap() + .as_instruction_value() + .unwrap(); + let insert_struct_2 = builder + .build_insert_value(struct_val.into_struct_value(), i32_val, 2, "insert_2") + .unwrap() + .as_instruction_value() + .unwrap(); + + assert_eq!(insert_struct_0.get_num_indices(), 1); + assert_eq!(insert_struct_0.get_indices(), vec![0]); + assert_eq!(insert_struct_2.get_num_indices(), 1); + assert_eq!(insert_struct_2.get_indices(), vec![2]); + + // Test with non-extractvalue/insertvalue instruction (should return 0/empty) + let i32_alloca = builder.build_alloca(i32_type, "i32_alloca").unwrap(); + let store_inst = builder.build_store(i32_alloca, i32_val).unwrap(); + + assert_eq!(store_inst.get_num_indices(), 0); + assert_eq!(store_inst.get_indices(), vec![]); + + builder.build_return(None).unwrap(); + + assert!(module.verify().is_ok()); +} From f88ccb2b42158486c6823faad1411c3becaa0031 Mon Sep 17 00:00:00 2001 From: Nam Se Hyun <3580430+namse@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:36:07 +0900 Subject: [PATCH 25/26] Get AtomicRMWBinOp (#616) * Get AtomicRMWBinOp * Linting --- src/values/instruction_value.rs | 22 ++++++++++++++++++++-- tests/all/test_instruction_values.rs | 4 ++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 006d93bf573..c100ccfa49f 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -13,9 +13,9 @@ use llvm_sys::core::{ LLVMIsATerminatorInst, LLVMIsConditional, LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand, LLVMSetVolatile, LLVMValueAsBasicBlock, }; -use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering}; #[llvm_versions(10..)] -use llvm_sys::core::{LLVMIsAAtomicCmpXchgInst, LLVMIsAAtomicRMWInst}; +use llvm_sys::core::{LLVMGetAtomicRMWBinOp, LLVMIsAAtomicCmpXchgInst, LLVMIsAAtomicRMWInst}; +use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering}; use llvm_sys::prelude::LLVMValueRef; use llvm_sys::LLVMOpcode; @@ -23,6 +23,8 @@ use std::{ffi::CStr, fmt, fmt::Display}; use crate::error::AlignmentError; use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, MetadataValue, Value}; +#[llvm_versions(10..)] +use crate::AtomicRMWBinOp; use crate::{basic_block::BasicBlock, types::AnyTypeEnum}; use crate::{types::BasicTypeEnum, values::traits::AsValueRef}; use crate::{AtomicOrdering, FloatPredicate, IntPredicate}; @@ -969,6 +971,22 @@ impl<'ctx> InstructionValue<'ctx> { } } + /// Gets the binary operation of an `AtomicRMW` `InstructionValue`. + /// For instance, in the LLVM instruction + /// `%3 = atomicrmw add i32* %ptr, i32 %val monotonic` + /// this gives the `add`. + /// + /// If the instruction is not an `AtomicRMW`, this returns None. + #[llvm_versions(10..)] + pub fn get_atomic_rmw_bin_op(self) -> Option { + if self.get_opcode() == InstructionOpcode::AtomicRMW { + let bin_op = unsafe { LLVMGetAtomicRMWBinOp(self.as_value_ref()) }; + Some(AtomicRMWBinOp::new(bin_op)) + } else { + None + } + } + /// Determines whether or not this `Instruction` has any associated metadata. pub fn has_metadata(self) -> bool { unsafe { LLVMHasMetadata(self.instruction_value.value) == 1 } diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index a790ee38197..3b120742e96 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -394,6 +394,10 @@ fn test_volatile_atomicrmw_cmpxchg() { .as_instruction_value() .unwrap(); + // Test get_atomic_rmw_bin_op + assert_eq!(atomicrmw.get_atomic_rmw_bin_op(), Some(AtomicRMWBinOp::Add)); + assert_eq!(cmpxchg.get_atomic_rmw_bin_op(), None); + assert!(!atomicrmw.get_volatile().unwrap()); assert!(!cmpxchg.get_volatile().unwrap()); atomicrmw.set_volatile(true).unwrap(); From c7a803900029684d63511602c786898dff6821ed Mon Sep 17 00:00:00 2001 From: Alexander Fedotov Date: Sat, 2 Sep 2023 21:52:39 -0400 Subject: [PATCH 26/26] Make creation of values from `LLVMValueRef` public --- src/values/generic_value.rs | 2 +- src/values/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/values/generic_value.rs b/src/values/generic_value.rs index f203e2ca128..6e60c259493 100644 --- a/src/values/generic_value.rs +++ b/src/values/generic_value.rs @@ -16,7 +16,7 @@ pub struct GenericValue<'ctx> { } impl<'ctx> GenericValue<'ctx> { - pub(crate) unsafe fn new(generic_value: LLVMGenericValueRef) -> Self { + pub unsafe fn new(generic_value: LLVMGenericValueRef) -> Self { assert!(!generic_value.is_null()); GenericValue { diff --git a/src/values/mod.rs b/src/values/mod.rs index 9edca9206a2..69574b60c2e 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -96,7 +96,7 @@ struct Value<'ctx> { } impl<'ctx> Value<'ctx> { - pub(crate) unsafe fn new(value: LLVMValueRef) -> Self { + pub unsafe fn new(value: LLVMValueRef) -> Self { debug_assert!( !value.is_null(), "This should never happen since containing struct should check null ptrs"