Skip to content

Commit

Permalink
Add opaque pointers (TheDan64#468)
Browse files Browse the repository at this point in the history
* Add opaque pointers

- Add a `ptr_type` method to `Context` for LLVM >= 15.0 to get an opaque
  pointer type.
- Deprecate the use of `ptr_type` on `*Type`.
- Add a `is_opaque` method to `PointerType` to check whether the pointer
  is opaque (which is always true unless opaque-by-default is disabled).
- Change the tests to use the new `ptr_type` method on `Context`.

* Add `get_value_type` to `GlobalValue`

* Fix `LLVMGlobalGetValueType` not available in LLVM <= 7

* Add support for LLVM 18

---------

Co-authored-by: Xavier Lambein <[email protected]>
  • Loading branch information
xlambein and Xavier Lambein authored Apr 13, 2024
1 parent d916c66 commit 5d5a531
Show file tree
Hide file tree
Showing 23 changed files with 879 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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("ret", fn_type, None);
Expand Down
53 changes: 49 additions & 4 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,10 @@ 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")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -574,11 +577,11 @@ impl<'ctx> Builder<'ctx> {
/// };
///
/// // type of an exception in C++
/// let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default());
/// let 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);
/// let exception_type = context.struct_type(&[ptr_type.into(), i32_type.into()], false);
///
/// let null = i8_ptr_type.const_zero();
/// let null = ptr_type.const_zero();
/// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
///
/// // we handle the exception by returning a default value
Expand Down Expand Up @@ -705,7 +708,10 @@ 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")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -734,7 +740,10 @@ 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")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -766,7 +775,10 @@ 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")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -801,7 +813,10 @@ 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")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -920,7 +935,10 @@ impl<'ctx> Builder<'ctx> {
/// };
///
/// // type of an exception in C++
/// let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default());
/// #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
/// 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"))]
/// 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);
///
Expand Down Expand Up @@ -1069,7 +1087,10 @@ 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")))]
/// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
Expand Down Expand Up @@ -1132,7 +1153,10 @@ 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")))]
/// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
Expand Down Expand Up @@ -1203,7 +1227,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let entry = context.append_basic_block(fn_value, "entry");
Expand Down Expand Up @@ -1251,7 +1278,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let entry = context.append_basic_block(fn_value, "entry");
Expand Down Expand Up @@ -1317,7 +1347,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let fn_value = module.add_function("ret", fn_type, None);
Expand Down Expand Up @@ -1354,7 +1387,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let entry = context.append_basic_block(fn_value, "entry");
Expand Down Expand Up @@ -1391,7 +1427,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let entry = context.append_basic_block(fn_value, "entry");
Expand Down Expand Up @@ -3226,7 +3265,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let entry = context.append_basic_block(fn_value, "entry");
Expand Down Expand Up @@ -3302,7 +3344,10 @@ 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")))]
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
/// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
/// 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);
/// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
Expand Down
49 changes: 48 additions & 1 deletion src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use llvm_sys::core::LLVMGetInlineAsm;
use llvm_sys::core::LLVMGetTypeByName2;
#[llvm_versions(6.0..=latest)]
use llvm_sys::core::LLVMMetadataTypeInContext;
#[llvm_versions(15.0..=latest)]
use llvm_sys::core::LLVMPointerTypeInContext;
use llvm_sys::core::{
LLVMAppendBasicBlockInContext, LLVMConstStringInContext, LLVMConstStructInContext, LLVMContextCreate,
LLVMContextDispose, LLVMContextSetDiagnosticHandler, LLVMCreateBuilderInContext, LLVMCreateEnumAttribute,
Expand Down Expand Up @@ -40,7 +42,7 @@ use crate::targets::TargetData;
use crate::types::AnyTypeEnum;
#[llvm_versions(6.0..=latest)]
use crate::types::MetadataType;
use crate::types::{AsTypeRef, BasicTypeEnum, FloatType, FunctionType, IntType, StructType, VoidType};
use crate::types::{AsTypeRef, BasicTypeEnum, FloatType, FunctionType, IntType, PointerType, StructType, VoidType};
use crate::values::{
ArrayValue, AsValueRef, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, MetadataValue, PointerValue,
StructValue,
Expand Down Expand Up @@ -242,6 +244,11 @@ impl ContextImpl {
unsafe { FloatType::new(LLVMPPCFP128TypeInContext(self.0)) }
}

#[llvm_versions(15.0..=latest)]
fn ptr_type<'ctx>(&self, address_space: AddressSpace) -> PointerType<'ctx> {
unsafe { PointerType::new(LLVMPointerTypeInContext(self.0, address_space.0)) }
}

fn struct_type<'ctx>(&self, field_types: &[BasicTypeEnum], packed: bool) -> StructType<'ctx> {
let mut field_types: Vec<LLVMTypeRef> = field_types.iter().map(|val| val.as_type_ref()).collect();
unsafe {
Expand Down Expand Up @@ -917,6 +924,26 @@ impl Context {
self.context.ppc_f128_type()
}

/// Gets the `PointerType`. It will be assigned the current context.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let ptr_type = context.ptr_type(AddressSpace::default());
///
/// assert_eq!(ptr_type.get_address_space(), AddressSpace::default());
/// assert_eq!(ptr_type.get_context(), context);
/// ```
#[llvm_versions(15.0..=latest)]
#[inline]
pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType {
self.context.ptr_type(address_space)
}

/// Creates a `StructType` definition from heterogeneous types in the current `Context`.
///
/// # Example
Expand Down Expand Up @@ -1765,6 +1792,26 @@ impl<'ctx> ContextRef<'ctx> {
self.context.ppc_f128_type()
}

/// Gets the `PointerType`. It will be assigned the current context.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let ptr_type = context.ptr_type(AddressSpace::default());
///
/// assert_eq!(ptr_type.get_address_space(), AddressSpace::default());
/// assert_eq!(ptr_type.get_context(), context);
/// ```
#[llvm_versions(15.0..=latest)]
#[inline]
pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType<'ctx> {
self.context.ptr_type(address_space)
}

/// Creates a `StructType` definition from heterogeneous types in the current `Context`.
///
/// # Example
Expand Down
3 changes: 2 additions & 1 deletion src/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,8 @@ impl Target {
/// # Example
///
/// ```no_run
/// use inkwell::targets::{Target, TargetTriple, TargetMachineOptions};
/// use inkwell::targets::{InitializationConfig, Target, TargetTriple, TargetMachineOptions};
/// use inkwell::OptimizationLevel;
///
/// Target::initialize_x86(&InitializationConfig::default());
///
Expand Down
11 changes: 11 additions & 0 deletions src/types/array_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ impl<'ctx> ArrayType<'ctx> {
/// ))]
/// assert_eq!(i8_array_ptr_type.get_element_type().into_array_type(), i8_array_type);
/// ```
#[cfg_attr(
any(
feature = "llvm15-0",
feature = "llvm16-0",
feature = "llvm17-0",
feature = "llvm18-0"
),
deprecated(
note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
)
)]
pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
self.array_type.ptr_type(address_space)
}
Expand Down
11 changes: 11 additions & 0 deletions src/types/float_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,17 @@ impl<'ctx> FloatType<'ctx> {
/// ))]
/// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type);
/// ```
#[cfg_attr(
any(
feature = "llvm15-0",
feature = "llvm16-0",
feature = "llvm17-0",
feature = "llvm18-0"
),
deprecated(
note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
)
)]
pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
self.float_type.ptr_type(address_space)
}
Expand Down
11 changes: 11 additions & 0 deletions src/types/fn_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ impl<'ctx> FunctionType<'ctx> {
/// ))]
/// assert_eq!(fn_ptr_type.get_element_type().into_function_type(), fn_type);
/// ```
#[cfg_attr(
any(
feature = "llvm15-0",
feature = "llvm16-0",
feature = "llvm17-0",
feature = "llvm18-0"
),
deprecated(
note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
)
)]
pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
self.fn_type.ptr_type(address_space)
}
Expand Down
11 changes: 11 additions & 0 deletions src/types/int_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,17 @@ impl<'ctx> IntType<'ctx> {
/// ))]
/// assert_eq!(i8_ptr_type.get_element_type().into_int_type(), i8_type);
/// ```
#[cfg_attr(
any(
feature = "llvm15-0",
feature = "llvm16-0",
feature = "llvm17-0",
feature = "llvm18-0"
),
deprecated(
note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
)
)]
pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
self.int_type.ptr_type(address_space)
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pub use crate::types::fn_type::FunctionType;
pub use crate::types::int_type::{IntType, StringRadix};
pub use crate::types::metadata_type::MetadataType;
pub use crate::types::ptr_type::PointerType;
pub use crate::types::struct_type::StructType;
pub use crate::types::struct_type::FieldTypesIter;
pub use crate::types::struct_type::StructType;
pub use crate::types::traits::{AnyType, AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType};
pub use crate::types::vec_type::VectorType;
pub use crate::types::void_type::VoidType;
Expand Down
Loading

0 comments on commit 5d5a531

Please sign in to comment.