Skip to content

Commit 9a84825

Browse files
Removes Either dependency. (#610)
* Replaced Either with UsedValue enum. * More replacement of Either. * All instances of Either removed. * Removed `either` dependency. * Formatting. * Added documentation. * Changed `value().unwrap()` into `unwrap_value()`. --------- Co-authored-by: Dan Kolsoi <ThaDan64@gmail.com>
1 parent f88ccb2 commit 9a84825

14 files changed

Lines changed: 308 additions & 80 deletions

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ llvm-sys-181 = { package = "llvm-sys", version = "181.2.0", optional = true }
156156
llvm-sys-191 = { package = "llvm-sys", version = "191.0.0", optional = true }
157157
llvm-sys-201 = { package = "llvm-sys", version = "201.0.0", optional = true }
158158

159-
either = "1.5"
160159
libc = "0.2"
161160
once_cell = "1.16"
162161
thiserror = "2.0.11"

examples/kaleidoscope/implementation_typed_pointers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> {
971971
.build_call(fun, &[lhs.into(), rhs.into()], "tmpbin")
972972
.unwrap()
973973
.try_as_basic_value()
974-
.left()
974+
.basic()
975975
{
976976
Some(value) => Ok(value.into_float_value()),
977977
None => Err("Invalid call produced."),
@@ -1001,7 +1001,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> {
10011001
.build_call(fun, argsv.as_slice(), "tmp")
10021002
.unwrap()
10031003
.try_as_basic_value()
1004-
.left()
1004+
.basic()
10051005
{
10061006
Some(value) => Ok(value.into_float_value()),
10071007
None => Err("Invalid call produced."),

src/basic_block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ impl<'ctx> BasicBlock<'ctx> {
506506
///
507507
/// bb1.replace_all_uses_with(&bb2);
508508
///
509-
/// assert_eq!(branch_inst.get_operand(0).unwrap().right().unwrap(), bb2);
509+
/// assert_eq!(branch_inst.get_operand(0).unwrap().unwrap_block(), bb2);
510510
/// ```
511511
pub fn replace_all_uses_with(self, other: &BasicBlock<'ctx>) {
512512
let value = unsafe { LLVMBasicBlockAsValue(self.basic_block) };

src/builder.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ impl<'ctx> Builder<'ctx> {
242242
///
243243
/// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
244244
/// .try_as_basic_value()
245-
/// .left()
246-
/// .unwrap();
245+
/// .unwrap_basic();
247246
///
248247
/// builder.build_return(Some(&ret_val)).unwrap();
249248
/// ```
@@ -320,8 +319,7 @@ impl<'ctx> Builder<'ctx> {
320319
///
321320
/// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
322321
/// .try_as_basic_value()
323-
/// .left()
324-
/// .unwrap();
322+
/// .unwrap_basic();
325323
///
326324
/// builder.build_return(Some(&ret_val)).unwrap();
327325
/// ```
@@ -367,7 +365,7 @@ impl<'ctx> Builder<'ctx> {
367365
/// )
368366
/// .unwrap()
369367
/// .try_as_basic_value()
370-
/// .unwrap_left();
368+
/// .unwrap_basic();
371369
/// builder.build_return(Some(&ret_val)).unwrap();
372370
///
373371
/// # module.verify().unwrap();
@@ -413,8 +411,7 @@ impl<'ctx> Builder<'ctx> {
413411
/// let function_pointer = fn_value.as_global_value().as_pointer_value();
414412
/// let ret_val = builder.build_indirect_call(fn_value.get_type(), function_pointer, &[i32_arg.into(), md_string.into()], "call").unwrap()
415413
/// .try_as_basic_value()
416-
/// .left()
417-
/// .unwrap();
414+
/// .unwrap_basic();
418415
///
419416
/// builder.build_return(Some(&ret_val)).unwrap();
420417
/// ```
@@ -585,7 +582,7 @@ impl<'ctx> Builder<'ctx> {
585582
/// builder.position_at_end(then_block);
586583
///
587584
/// // in the then_block, the `call_site` value is defined and can be used
588-
/// let result = call_site.try_as_basic_value().left().unwrap();
585+
/// let result = call_site.try_as_basic_value().unwrap_basic();
589586
///
590587
/// builder.build_return(Some(&result)).unwrap();
591588
/// }
@@ -707,7 +704,7 @@ impl<'ctx> Builder<'ctx> {
707704
/// builder.position_at_end(then_block);
708705
///
709706
/// // in the then_block, the `call_site` value is defined and can be used
710-
/// let result = call_site.try_as_basic_value().left().unwrap();
707+
/// let result = call_site.try_as_basic_value().unwrap_basic();
711708
///
712709
/// builder.build_return(Some(&result)).unwrap();
713710
/// }
@@ -1068,7 +1065,7 @@ impl<'ctx> Builder<'ctx> {
10681065
/// builder.position_at_end(then_block);
10691066
///
10701067
/// // in the then_block, the `call_site` value is defined and can be used
1071-
/// let result = call_site.try_as_basic_value().left().unwrap();
1068+
/// let result = call_site.try_as_basic_value().unwrap_basic();
10721069
///
10731070
/// builder.build_return(Some(&result)).unwrap();
10741071
/// }

src/execution_engine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<'ctx> ExecutionEngine<'ctx> {
166166
///
167167
/// let argf = ft.const_float(64.);
168168
/// let call_site_value = builder.build_call(extf, &[argf.into(), argf.into()], "retv").unwrap();
169-
/// let retv = call_site_value.try_as_basic_value().left().unwrap().into_float_value();
169+
/// let retv = call_site_value.try_as_basic_value().unwrap_basic().into_float_value();
170170
///
171171
/// builder.build_return(Some(&retv)).unwrap();
172172
///

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ use llvm_sys::{
7878

7979
use llvm_sys::LLVMInlineAsmDialect;
8080

81-
pub use either::Either;
8281
pub use error::Error;
8382
#[cfg(feature = "serde")]
8483
use serde::{Deserialize, Serialize};

src/values/basic_value_use.rs

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use either::{
2-
Either,
3-
Either::{Left, Right},
4-
};
51
use llvm_sys::core::{LLVMGetNextUse, LLVMGetUsedValue, LLVMGetUser, LLVMIsABasicBlock, LLVMValueAsBasicBlock};
62
use llvm_sys::prelude::LLVMUseRef;
73

@@ -10,6 +6,87 @@ use std::marker::PhantomData;
106
use crate::basic_block::BasicBlock;
117
use crate::values::{AnyValueEnum, BasicValueEnum};
128

9+
/// Either [BasicValueEnum] or [BasicBlock].
10+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11+
pub enum Operand<'ctx> {
12+
Value(BasicValueEnum<'ctx>),
13+
Block(BasicBlock<'ctx>),
14+
}
15+
16+
impl<'ctx> Operand<'ctx> {
17+
/// Determines if the [Operand] is a [BasicValueEnum].
18+
#[inline]
19+
#[must_use]
20+
pub fn is_value(self) -> bool {
21+
matches!(self, Self::Value(_))
22+
}
23+
24+
/// Determines if the [Operand] is a [BasicBlock].
25+
#[inline]
26+
#[must_use]
27+
pub fn is_block(self) -> bool {
28+
matches!(self, Self::Block(_))
29+
}
30+
31+
/// If the [Operand] is a [BasicValueEnum], map it into [Option::Some].
32+
#[inline]
33+
#[must_use]
34+
pub fn value(self) -> Option<BasicValueEnum<'ctx>> {
35+
match self {
36+
Self::Value(value) => Some(value),
37+
_ => None,
38+
}
39+
}
40+
41+
/// If the [Operand] is a [BasicBlock], map it into [Option::Some].
42+
#[inline]
43+
#[must_use]
44+
pub fn block(self) -> Option<BasicBlock<'ctx>> {
45+
match self {
46+
Self::Block(block) => Some(block),
47+
_ => None,
48+
}
49+
}
50+
51+
/// Expect [BasicValueEnum], panic with the message if it is not.
52+
#[inline]
53+
#[must_use]
54+
#[track_caller]
55+
pub fn expect_value(self, msg: &str) -> BasicValueEnum<'ctx> {
56+
match self {
57+
Self::Value(value) => value,
58+
_ => panic!("{msg}"),
59+
}
60+
}
61+
62+
/// Expect [BasicBlock], panic with the message if it is not.
63+
#[inline]
64+
#[must_use]
65+
#[track_caller]
66+
pub fn expect_block(self, msg: &str) -> BasicBlock<'ctx> {
67+
match self {
68+
Self::Block(block) => block,
69+
_ => panic!("{msg}"),
70+
}
71+
}
72+
73+
/// Unwrap [BasicValueEnum]. Will panic if it is not.
74+
#[inline]
75+
#[must_use]
76+
#[track_caller]
77+
pub fn unwrap_value(self) -> BasicValueEnum<'ctx> {
78+
self.expect_value("Called unwrap_value() on UsedValue::Block.")
79+
}
80+
81+
/// Unwrap [BasicBlock]. Will panic if it is not.
82+
#[inline]
83+
#[must_use]
84+
#[track_caller]
85+
pub fn unwrap_block(self) -> BasicBlock<'ctx> {
86+
self.expect_block("Called unwrap_block() on UsedValue::Value.")
87+
}
88+
}
89+
1390
/// A usage of a `BasicValue` in another value.
1491
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1592
pub struct BasicValueUse<'ctx>(LLVMUseRef, PhantomData<&'ctx ()>);
@@ -160,28 +237,28 @@ impl<'ctx> BasicValueUse<'ctx> {
160237
/// let free_instruction = builder.build_free(arg1).unwrap();
161238
/// let return_instruction = builder.build_return(None).unwrap();
162239
///
163-
/// let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap();
240+
/// let free_operand0 = free_instruction.get_operand(0).unwrap().unwrap_value();
164241
/// let free_operand0_instruction = free_operand0.as_instruction_value().unwrap();
165242
/// let bitcast_use_value = free_operand0_instruction
166243
/// .get_first_use()
167244
/// .unwrap()
168245
/// .get_used_value()
169-
/// .left()
246+
/// .value()
170247
/// .unwrap();
171248
///
172249
/// assert_eq!(bitcast_use_value, free_operand0);
173250
/// ```
174-
pub fn get_used_value(self) -> Either<BasicValueEnum<'ctx>, BasicBlock<'ctx>> {
251+
pub fn get_used_value(self) -> Operand<'ctx> {
175252
let used_value = unsafe { LLVMGetUsedValue(self.0) };
176253

177254
let is_basic_block = unsafe { !LLVMIsABasicBlock(used_value).is_null() };
178255

179256
if is_basic_block {
180257
let bb = unsafe { BasicBlock::new(LLVMValueAsBasicBlock(used_value)) };
181258

182-
Right(bb.expect("BasicBlock should always be valid"))
259+
Operand::Block(bb.expect("BasicBlock should always be valid"))
183260
} else {
184-
unsafe { Left(BasicValueEnum::new(used_value)) }
261+
unsafe { Operand::Value(BasicValueEnum::new(used_value)) }
185262
}
186263
}
187264
}

src/values/call_site_value.rs

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::fmt::{self, Display};
22

3-
use either::Either;
4-
53
use llvm_sys::core::LLVMGetCalledFunctionType;
64
use llvm_sys::core::{
75
LLVMGetCalledValue, LLVMGetInstructionCallConv, LLVMGetTypeKind, LLVMIsTailCall, LLVMSetInstrParamAlignment,
@@ -20,6 +18,87 @@ use crate::values::{AsValueRef, BasicValueEnum, FunctionValue, InstructionValue,
2018

2119
use super::{AnyValue, InstructionOpcode};
2220

21+
/// Either [BasicValueEnum] or [InstructionValue].
22+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23+
pub enum ValueKind<'ctx> {
24+
Basic(BasicValueEnum<'ctx>),
25+
Instruction(InstructionValue<'ctx>),
26+
}
27+
28+
impl<'ctx> ValueKind<'ctx> {
29+
/// Determines if the [ValueKind] is a [BasicValueEnum].
30+
#[inline]
31+
#[must_use]
32+
pub fn is_basic(self) -> bool {
33+
matches!(self, Self::Basic(_))
34+
}
35+
36+
/// Determines if the [ValueKind] is an [InstructionValue].
37+
#[inline]
38+
#[must_use]
39+
pub fn is_instruction(self) -> bool {
40+
matches!(self, Self::Instruction(_))
41+
}
42+
43+
/// If the [ValueKind] is a [BasicValueEnum], map it into [Option::Some].
44+
#[inline]
45+
#[must_use]
46+
pub fn basic(self) -> Option<BasicValueEnum<'ctx>> {
47+
match self {
48+
Self::Basic(value) => Some(value),
49+
_ => None,
50+
}
51+
}
52+
53+
/// If the [ValueKind] is an [InstructionValue], map it into [Option::Some].
54+
#[inline]
55+
#[must_use]
56+
pub fn instruction(self) -> Option<InstructionValue<'ctx>> {
57+
match self {
58+
Self::Instruction(inst) => Some(inst),
59+
_ => None,
60+
}
61+
}
62+
63+
/// Expect [BasicValueEnum], panic with the message if it is not.
64+
#[inline]
65+
#[must_use]
66+
#[track_caller]
67+
pub fn expect_basic(self, msg: &str) -> BasicValueEnum<'ctx> {
68+
match self {
69+
Self::Basic(value) => value,
70+
_ => panic!("{msg}"),
71+
}
72+
}
73+
74+
/// Expect [InstructionValue], panic with the message if it is not.
75+
#[inline]
76+
#[must_use]
77+
#[track_caller]
78+
pub fn expect_instruction(self, msg: &str) -> InstructionValue<'ctx> {
79+
match self {
80+
Self::Instruction(inst) => inst,
81+
_ => panic!("{msg}"),
82+
}
83+
}
84+
85+
/// Unwrap [BasicValueEnum]. Will panic if it is not.
86+
#[inline]
87+
#[must_use]
88+
#[track_caller]
89+
pub fn unwrap_basic(self) -> BasicValueEnum<'ctx> {
90+
self.expect_basic("Called unwrap_basic() on ValueKind::Instruction.")
91+
}
92+
93+
/// Unwrap [InstructionValue]. Will panic if it is not.
94+
#[inline]
95+
#[must_use]
96+
#[track_caller]
97+
pub fn unwrap_instruction(self) -> InstructionValue<'ctx> {
98+
self.expect_instruction("Called unwrap_instruction() on ValueKind::Basic.")
99+
}
100+
}
101+
23102
/// A value resulting from a function call. It may have function attributes applied to it.
24103
///
25104
/// This struct may be removed in the future in favor of an `InstructionValue<CallSite>` type.
@@ -160,13 +239,13 @@ impl<'ctx> CallSiteValue<'ctx> {
160239
///
161240
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
162241
///
163-
/// assert!(call_site_value.try_as_basic_value().is_right());
242+
/// assert!(call_site_value.try_as_basic_value().is_instruction());
164243
/// ```
165-
pub fn try_as_basic_value(self) -> Either<BasicValueEnum<'ctx>, InstructionValue<'ctx>> {
244+
pub fn try_as_basic_value(self) -> ValueKind<'ctx> {
166245
unsafe {
167246
match LLVMGetTypeKind(LLVMTypeOf(self.as_value_ref())) {
168-
LLVMTypeKind::LLVMVoidTypeKind => Either::Right(InstructionValue::new(self.as_value_ref())),
169-
_ => Either::Left(BasicValueEnum::new(self.as_value_ref())),
247+
LLVMTypeKind::LLVMVoidTypeKind => ValueKind::Instruction(InstructionValue::new(self.as_value_ref())),
248+
_ => ValueKind::Basic(BasicValueEnum::new(self.as_value_ref())),
170249
}
171250
}
172251
}

0 commit comments

Comments
 (0)