Skip to content

Commit

Permalink
Make 'inkwell' compile with LLVM 15
Browse files Browse the repository at this point in the history
1. Remove the `LLVMConst*` function family
2. Remove some optimization passes, including those for coroutines
3. Update the `AtomicRMWBinOp` enum

(cherry picked from commit 2a5b193)
  • Loading branch information
Alex Z committed Nov 17, 2022
1 parent fffe576 commit 47bd6a0
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 190 deletions.
14 changes: 14 additions & 0 deletions .idea/inkwell.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@ pub enum AtomicRMWBinOp {
#[llvm_versions(10.0..=latest)]
#[llvm_variant(LLVMAtomicRMWBinOpFSub)]
FSub,

/// Sets memory to the float-typed-greater of the value provided and the value in memory. Returns the value that was in memory.
#[llvm_versions(15.0..=latest)]
#[llvm_variant(LLVMAtomicRMWBinOpFMax)]
FMax,

/// Sets memory to the float-typed-lesser of the value provided and the value in memory. Returns the value that was in memory.
#[llvm_versions(15.0..=latest)]
#[llvm_variant(LLVMAtomicRMWBinOpFMin)]
FMin,
}

/// Defines the optimization level used to compile a `Module`.
Expand Down
71 changes: 70 additions & 1 deletion src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,76 @@ impl<'ctx> Module<'ctx> {
unsafe { Some(GlobalValue::new(value)) }
}

/// Creates a new `Module` from a `MemoryBuffer`.
/// Creates a new `Module` from a `MemoryBuffer` with IR.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::module::Module;
/// use inkwell::memory_buffer::MemoryBuffer;
/// use std::path::Path;
///
/// let path = Path::new("foo/bar.ll");
/// let context = Context::create();
/// let buffer = MemoryBuffer::create_from_file(&path).unwrap();
/// let module = Module::parse_ir_from_buffer(&buffer, &context);
///
/// assert_eq!(*module.unwrap().get_context(), context);
///
/// ```
pub fn parse_ir_from_buffer(
buffer: &MemoryBuffer,
context: &'ctx Context,
) -> Result<Self, LLVMString> {
let mut module = MaybeUninit::uninit();
let mut err_string = MaybeUninit::uninit();

let success = unsafe {
LLVMParseIRInContext(
context.context.0,
buffer.memory_buffer,
module.as_mut_ptr(),
err_string.as_mut_ptr(),
)
};

if success != 0 {
let err_string = unsafe { err_string.assume_init() };
return Err(unsafe { LLVMString::new(err_string) });
}

let module = unsafe { module.assume_init() };

Ok(unsafe { Module::new(module) })
}

/// A convenience function for creating a `Module` from an IR file for a given context.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::module::Module;
/// use std::path::Path;
///
/// let path = Path::new("foo/bar.ll");
/// let context = Context::create();
/// let module = Module::parse_ir_from_path(&path, &context);
///
/// assert_eq!(*module.unwrap().get_context(), context);
///
/// ```
pub fn parse_ir_from_path<P: AsRef<Path>>(
path: P,
context: &'ctx Context,
) -> Result<Self, LLVMString> {
let buffer = MemoryBuffer::create_from_file(path.as_ref())?;

Self::parse_ir_from_buffer(&buffer, &context)
}

/// Creates a new `Module` from a `MemoryBuffer` with bitcode.
///
/// # Example
///
Expand Down
113 changes: 3 additions & 110 deletions src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ use llvm_sys::prelude::{LLVMPassManagerRef, LLVMPassRegistryRef};
#[llvm_versions(10.0..=latest)]
use llvm_sys::transforms::ipo::LLVMAddMergeFunctionsPass;
use llvm_sys::transforms::ipo::{
LLVMAddAlwaysInlinerPass, LLVMAddArgumentPromotionPass, LLVMAddConstantMergePass, LLVMAddDeadArgEliminationPass,
LLVMAddAlwaysInlinerPass, LLVMAddConstantMergePass, LLVMAddDeadArgEliminationPass,
LLVMAddFunctionAttrsPass, LLVMAddFunctionInliningPass, LLVMAddGlobalDCEPass, LLVMAddGlobalOptimizerPass,
LLVMAddIPSCCPPass, LLVMAddInternalizePass, LLVMAddPruneEHPass, LLVMAddStripDeadPrototypesPass,
LLVMAddStripSymbolsPass,
};
use llvm_sys::transforms::pass_manager_builder::{
LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderPopulateFunctionPassManager,
LLVMPassManagerBuilderPopulateLTOPassManager, LLVMPassManagerBuilderPopulateModulePassManager,
LLVMPassManagerBuilderPopulateModulePassManager,
LLVMPassManagerBuilderRef, LLVMPassManagerBuilderSetDisableSimplifyLibCalls,
LLVMPassManagerBuilderSetDisableUnitAtATime, LLVMPassManagerBuilderSetDisableUnrollLoops,
LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderSetSizeLevel,
Expand All @@ -31,7 +31,7 @@ use llvm_sys::transforms::scalar::{
LLVMAddDeadStoreEliminationPass, LLVMAddDemoteMemoryToRegisterPass, LLVMAddEarlyCSEPass, LLVMAddGVNPass,
LLVMAddIndVarSimplifyPass, LLVMAddInstructionCombiningPass, LLVMAddJumpThreadingPass, LLVMAddLICMPass,
LLVMAddLoopDeletionPass, LLVMAddLoopIdiomPass, LLVMAddLoopRerollPass, LLVMAddLoopRotatePass, LLVMAddLoopUnrollPass,
LLVMAddLoopUnswitchPass, LLVMAddLowerExpectIntrinsicPass, LLVMAddMemCpyOptPass, LLVMAddMergedLoadStoreMotionPass,
LLVMAddLowerExpectIntrinsicPass, LLVMAddMemCpyOptPass, LLVMAddMergedLoadStoreMotionPass,
LLVMAddPartiallyInlineLibCallsPass, LLVMAddReassociatePass, LLVMAddSCCPPass, LLVMAddScalarReplAggregatesPass,
LLVMAddScalarReplAggregatesPassSSA, LLVMAddScalarReplAggregatesPassWithThreshold, LLVMAddScalarizerPass,
LLVMAddScopedNoAliasAAPass, LLVMAddSimplifyLibCallsPass, LLVMAddTailCallEliminationPass,
Expand Down Expand Up @@ -162,37 +162,6 @@ impl PassManagerBuilder {
pub fn populate_module_pass_manager(&self, pass_manager: &PassManager<Module>) {
unsafe { LLVMPassManagerBuilderPopulateModulePassManager(self.pass_manager_builder, pass_manager.pass_manager) }
}

/// Populates a PassManager<Module> with the expectation of link time
/// optimization transformations.
///
/// # Example
///
/// ```no_run
/// use inkwell::OptimizationLevel::Aggressive;
/// use inkwell::passes::{PassManager, PassManagerBuilder};
/// use inkwell::targets::{InitializationConfig, Target};
///
/// let config = InitializationConfig::default();
/// Target::initialize_native(&config).unwrap();
/// let pass_manager_builder = PassManagerBuilder::create();
///
/// pass_manager_builder.set_optimization_level(Aggressive);
///
/// let lpm = PassManager::create(());
///
/// pass_manager_builder.populate_lto_pass_manager(&lpm, false, false);
/// ```
pub fn populate_lto_pass_manager(&self, pass_manager: &PassManager<Module>, internalize: bool, run_inliner: bool) {
unsafe {
LLVMPassManagerBuilderPopulateLTOPassManager(
self.pass_manager_builder,
pass_manager.pass_manager,
internalize as i32,
run_inliner as i32,
)
}
}
}

impl Drop for PassManagerBuilder {
Expand Down Expand Up @@ -282,28 +251,6 @@ impl<T: PassManagerSubType> PassManager<T> {
unsafe { input.run_in_pass_manager(self) }
}

/// This pass promotes "by reference" arguments to be "by value" arguments.
/// In practice, this means looking for internal functions that have pointer
/// arguments. If it can prove, through the use of alias analysis, that an
/// argument is only loaded, then it can pass the value into the function
/// instead of the address of the value. This can cause recursive simplification
/// of code and lead to the elimination of allocas (especially in C++ template
/// code like the STL).
///
/// This pass also handles aggregate arguments that are passed into a function,
/// scalarizing them if the elements of the aggregate are only loaded. Note that
/// it refuses to scalarize aggregates which would require passing in more than
/// three operands to the function, because passing thousands of operands for a
/// large array or structure is unprofitable!
///
/// Note that this transformation could also be done for arguments that are
/// only stored to (returning the value instead), but does not currently.
/// This case would be best handled when and if LLVM starts supporting multiple
/// return values from functions.
pub fn add_argument_promotion_pass(&self) {
unsafe { LLVMAddArgumentPromotionPass(self.pass_manager) }
}

/// Merges duplicate global constants together into a single constant that is
/// shared. This is useful because some passes (i.e., TraceValues) insert a lot
/// of string constants into the program, regardless of whether or not an existing
Expand Down Expand Up @@ -699,32 +646,6 @@ impl<T: PassManagerSubType> PassManager<T> {
unsafe { LLVMAddLoopUnrollPass(self.pass_manager) }
}

/// This pass transforms loops that contain branches on
/// loop-invariant conditions to have multiple loops.
/// For example, it turns the left into the right code:
///
/// ```c
/// for (...) if (lic)
/// A for (...)
/// if (lic) A; B; C
/// B else
/// C for (...)
/// A; C
/// ```
///
/// This can increase the size of the code exponentially
/// (doubling it every time a loop is unswitched) so we
/// only unswitch if the resultant code will be smaller
/// than a threshold.
///
/// This pass expects [LICM](https://llvm.org/docs/Passes.html#passes-licm)
/// to be run before it to hoist invariant conditions
/// out of the loop, to make the unswitching opportunity
/// obvious.
pub fn add_loop_unswitch_pass(&self) {
unsafe { LLVMAddLoopUnswitchPass(self.pass_manager) }
}

/// This pass performs various transformations related
/// to eliminating memcpy calls, or transforming sets
/// of stores into memsets.
Expand Down Expand Up @@ -1007,34 +928,6 @@ impl<T: PassManagerSubType> PassManager<T> {

unsafe { LLVMAddLoopUnrollAndJamPass(self.pass_manager) }
}

#[llvm_versions(8.0..=latest)]
pub fn add_coroutine_early_pass(&self) {
use llvm_sys::transforms::coroutines::LLVMAddCoroEarlyPass;

unsafe { LLVMAddCoroEarlyPass(self.pass_manager) }
}

#[llvm_versions(8.0..=latest)]
pub fn add_coroutine_split_pass(&self) {
use llvm_sys::transforms::coroutines::LLVMAddCoroSplitPass;

unsafe { LLVMAddCoroSplitPass(self.pass_manager) }
}

#[llvm_versions(8.0..=latest)]
pub fn add_coroutine_elide_pass(&self) {
use llvm_sys::transforms::coroutines::LLVMAddCoroElidePass;

unsafe { LLVMAddCoroElidePass(self.pass_manager) }
}

#[llvm_versions(8.0..=latest)]
pub fn add_coroutine_cleanup_pass(&self) {
use llvm_sys::transforms::coroutines::LLVMAddCoroCleanupPass;

unsafe { LLVMAddCoroCleanupPass(self.pass_manager) }
}
}

impl<T> Drop for PassManager<T> {
Expand Down
24 changes: 2 additions & 22 deletions src/values/float_value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use llvm_sys::core::{
LLVMConstFAdd, LLVMConstFCmp, LLVMConstFDiv, LLVMConstFMul, LLVMConstFNeg, LLVMConstFPCast, LLVMConstFPExt,
LLVMConstFPToSI, LLVMConstFPToUI, LLVMConstFPTrunc, LLVMConstFRem, LLVMConstFSub, LLVMConstRealGetDouble,
LLVMConstFCmp, LLVMConstFNeg, LLVMConstFPCast, LLVMConstFPExt,
LLVMConstFPToSI, LLVMConstFPToUI, LLVMConstFPTrunc, LLVMConstRealGetDouble,
};
use llvm_sys::prelude::LLVMValueRef;

Expand Down Expand Up @@ -64,26 +64,6 @@ impl<'ctx> FloatValue<'ctx> {
unsafe { FloatValue::new(LLVMConstFNeg(self.as_value_ref())) }
}

pub fn const_add(self, rhs: FloatValue<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFAdd(self.as_value_ref(), rhs.as_value_ref())) }
}

pub fn const_sub(self, rhs: FloatValue<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFSub(self.as_value_ref(), rhs.as_value_ref())) }
}

pub fn const_mul(self, rhs: FloatValue<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFMul(self.as_value_ref(), rhs.as_value_ref())) }
}

pub fn const_div(self, rhs: FloatValue<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFDiv(self.as_value_ref(), rhs.as_value_ref())) }
}

pub fn const_remainder(self, rhs: FloatValue<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFRem(self.as_value_ref(), rhs.as_value_ref())) }
}

pub fn const_cast(self, float_type: FloatType<'ctx>) -> Self {
unsafe { FloatValue::new(LLVMConstFPCast(self.as_value_ref(), float_type.as_type_ref())) }
}
Expand Down
Loading

0 comments on commit 47bd6a0

Please sign in to comment.