1use crate::name::Name;
2#[cfg(feature = "llvm-18-or-lower")]
3use crate::predicates::*;
4use crate::types::{FPType, NamedStructDef, Type, TypeRef, Typed, Types};
5use std::convert::TryFrom;
6use std::fmt::{self, Display};
7use std::ops::Deref;
8use std::sync::Arc;
9
10#[derive(PartialEq, Clone, Debug, Hash)]
13pub enum Constant {
14 Int {
15 bits: u32,
17 value: u64,
33 },
34 Float(Float),
35 Null(TypeRef),
37 AggregateZero(TypeRef),
39 Struct {
40 name: Option<String>, values: Vec<ConstantRef>,
42 is_packed: bool,
43 },
44 Array {
45 element_type: TypeRef,
46 elements: Vec<ConstantRef>,
47 },
48 Vector(Vec<ConstantRef>),
49 Undef(TypeRef),
51 #[cfg(feature = "llvm-12-or-greater")]
53 Poison(TypeRef),
54 BlockAddress, GlobalReference {
59 name: Name,
60 ty: TypeRef,
61 },
62 TokenNone,
63 #[cfg(feature = "llvm-19-or-greater")]
65 PtrAuth {
66 ptr : ConstantRef,
67 key : ConstantRef,
68 disc : ConstantRef,
69 addr_disc : ConstantRef
70 },
71
72 Add(Add),
76 Sub(Sub),
77 Mul(Mul),
78 #[cfg(feature = "llvm-14-or-lower")]
79 UDiv(UDiv),
80 #[cfg(feature = "llvm-14-or-lower")]
81 SDiv(SDiv),
82 #[cfg(feature = "llvm-14-or-lower")]
83 URem(URem),
84 #[cfg(feature = "llvm-14-or-lower")]
85 SRem(SRem),
86
87 #[cfg(feature = "llvm-17-or-lower")]
89 And(And),
90 #[cfg(feature = "llvm-17-or-lower")]
91 Or(Or),
92 Xor(Xor),
93 #[cfg(feature = "llvm-18-or-lower")]
94 Shl(Shl),
95 #[cfg(feature = "llvm-17-or-lower")]
96 LShr(LShr),
97 #[cfg(feature = "llvm-17-or-lower")]
98 AShr(AShr),
99
100 #[cfg(feature = "llvm-14-or-lower")]
102 FAdd(FAdd),
103 #[cfg(feature = "llvm-14-or-lower")]
104 FSub(FSub),
105 #[cfg(feature = "llvm-14-or-lower")]
106 FMul(FMul),
107 #[cfg(feature = "llvm-14-or-lower")]
108 FDiv(FDiv),
109 #[cfg(feature = "llvm-14-or-lower")]
110 FRem(FRem),
111
112 ExtractElement(ExtractElement),
114 InsertElement(InsertElement),
115 ShuffleVector(ShuffleVector),
116
117 #[cfg(feature = "llvm-14-or-lower")]
119 ExtractValue(ExtractValue),
120 #[cfg(feature = "llvm-14-or-lower")]
121 InsertValue(InsertValue),
122
123 GetElementPtr(GetElementPtr),
125
126 Trunc(Trunc),
128 #[cfg(feature = "llvm-17-or-lower")]
129 ZExt(ZExt),
130 #[cfg(feature = "llvm-17-or-lower")]
131 SExt(SExt),
132 #[cfg(feature = "llvm-17-or-lower")]
133 FPTrunc(FPTrunc),
134 #[cfg(feature = "llvm-17-or-lower")]
135 FPExt(FPExt),
136 #[cfg(feature = "llvm-17-or-lower")]
137 FPToUI(FPToUI),
138 #[cfg(feature = "llvm-17-or-lower")]
139 FPToSI(FPToSI),
140 #[cfg(feature = "llvm-17-or-lower")]
141 UIToFP(UIToFP),
142 #[cfg(feature = "llvm-17-or-lower")]
143 SIToFP(SIToFP),
144 PtrToInt(PtrToInt),
145 IntToPtr(IntToPtr),
146 BitCast(BitCast),
147 AddrSpaceCast(AddrSpaceCast),
148
149 #[cfg(feature = "llvm-18-or-lower")]
151 ICmp(ICmp),
152 #[cfg(feature = "llvm-18-or-lower")]
153 FCmp(FCmp),
154 #[cfg(feature = "llvm-16-or-lower")]
155 Select(Select),
156}
157
158#[derive(PartialEq, Clone, Debug)]
163#[allow(non_camel_case_types)]
164pub enum Float {
165 Half, #[cfg(feature = "llvm-11-or-greater")]
167 BFloat, Single(f32),
169 Double(f64),
170 Quadruple, X86_FP80, PPC_FP128, }
174
175impl std::hash::Hash for Float {
176 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
177 core::mem::discriminant(self).hash(state);
178 match self {
179 Float::Single(f) => ordered_float::OrderedFloat(*f).hash(state),
180 Float::Double(f) => ordered_float::OrderedFloat(*f).hash(state),
181 _ => {},
182 }
183 }
184}
185
186impl Typed for Float {
187 fn get_type(&self, types: &Types) -> TypeRef {
188 types.fp(match self {
189 Float::Half => FPType::Half,
190 #[cfg(feature = "llvm-11-or-greater")]
191 Float::BFloat => FPType::BFloat,
192 Float::Single(_) => FPType::Single,
193 Float::Double(_) => FPType::Double,
194 Float::Quadruple => FPType::FP128,
195 Float::X86_FP80 => FPType::X86_FP80,
196 Float::PPC_FP128 => FPType::PPC_FP128,
197 })
198 }
199}
200
201impl Display for Float {
202 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203 match self {
204 Float::Half => write!(f, "half"),
205 #[cfg(feature = "llvm-11-or-greater")]
206 Float::BFloat => write!(f, "bfloat"),
207 Float::Single(s) => write!(f, "float {}", s),
208 Float::Double(d) => write!(f, "double {}", d),
209 Float::Quadruple => write!(f, "quadruple"),
210 Float::X86_FP80 => write!(f, "x86_fp80"),
211 Float::PPC_FP128 => write!(f, "ppc_fp128"),
212 }
213 }
214}
215
216impl Typed for Constant {
217 #[rustfmt::skip] fn get_type(&self, types: &Types) -> TypeRef {
219 match self {
220 Constant::Int { bits, .. } => types.int(*bits),
221 Constant::Float(f) => types.type_of(f),
222 Constant::Null(t) => t.clone(),
223 Constant::AggregateZero(t) => t.clone(),
224 Constant::Struct { values, is_packed, .. } => types.struct_of(
225 values.iter().map(|v| types.type_of(v)).collect(),
226 *is_packed,
227 ),
228 Constant::Array { element_type, elements } => types.array_of(
229 element_type.clone(),
230 elements.len(),
231 ),
232 #[cfg(feature="llvm-11-or-greater")]
233 Constant::Vector(v) => types.vector_of(
234 types.type_of(&v[0]),
235 v.len(),
236 false, ),
238 #[cfg(feature="llvm-10-or-lower")]
239 Constant::Vector(v) => types.vector_of(
240 types.type_of(&v[0]),
241 v.len(),
242 ),
243 Constant::Undef(t) => t.clone(),
244 #[cfg(feature="llvm-12-or-greater")]
245 Constant::Poison(t) => t.clone(),
246 Constant::BlockAddress { .. } => types.label_type(),
247 #[cfg(feature="llvm-14-or-lower")]
248 Constant::GlobalReference { ty, .. } => types.pointer_to(ty.clone()),
249 #[cfg(feature="llvm-15-or-greater")]
250 Constant::GlobalReference { .. } => types.pointer(),
251 Constant::TokenNone => types.token_type(),
252 Constant::Add(a) => types.type_of(a),
253 Constant::Sub(s) => types.type_of(s),
254 Constant::Mul(m) => types.type_of(m),
255 #[cfg(feature = "llvm-14-or-lower")]
256 Constant::UDiv(d) => types.type_of(d),
257 #[cfg(feature = "llvm-14-or-lower")]
258 Constant::SDiv(d) => types.type_of(d),
259 #[cfg(feature = "llvm-14-or-lower")]
260 Constant::URem(r) => types.type_of(r),
261 #[cfg(feature = "llvm-14-or-lower")]
262 Constant::SRem(r) => types.type_of(r),
263 #[cfg(feature = "llvm-17-or-lower")]
264 Constant::And(a) => types.type_of(a),
265 #[cfg(feature = "llvm-17-or-lower")]
266 Constant::Or(o) => types.type_of(o),
267 Constant::Xor(x) => types.type_of(x),
268 #[cfg(feature = "llvm-18-or-lower")]
269 Constant::Shl(s) => types.type_of(s),
270 #[cfg(feature = "llvm-17-or-lower")]
271 Constant::LShr(l) => types.type_of(l),
272 #[cfg(feature = "llvm-17-or-lower")]
273 Constant::AShr(a) => types.type_of(a),
274 #[cfg(feature = "llvm-14-or-lower")]
275 Constant::FAdd(f) => types.type_of(f),
276 #[cfg(feature = "llvm-14-or-lower")]
277 Constant::FSub(f) => types.type_of(f),
278 #[cfg(feature = "llvm-14-or-lower")]
279 Constant::FMul(f) => types.type_of(f),
280 #[cfg(feature = "llvm-14-or-lower")]
281 Constant::FDiv(f) => types.type_of(f),
282 #[cfg(feature = "llvm-14-or-lower")]
283 Constant::FRem(f) => types.type_of(f),
284 Constant::ExtractElement(e) => types.type_of(e),
285 Constant::InsertElement(i) => types.type_of(i),
286 Constant::ShuffleVector(s) => types.type_of(s),
287 #[cfg(feature = "llvm-14-or-lower")]
288 Constant::ExtractValue(e) => types.type_of(e),
289 #[cfg(feature = "llvm-14-or-lower")]
290 Constant::InsertValue(i) => types.type_of(i),
291 Constant::GetElementPtr(g) => types.type_of(g),
292 Constant::Trunc(t) => types.type_of(t),
293 #[cfg(feature = "llvm-17-or-lower")]
294 Constant::ZExt(z) => types.type_of(z),
295 #[cfg(feature = "llvm-17-or-lower")]
296 Constant::SExt(s) => types.type_of(s),
297 #[cfg(feature = "llvm-17-or-lower")]
298 Constant::FPTrunc(f) => types.type_of(f),
299 #[cfg(feature = "llvm-17-or-lower")]
300 Constant::FPExt(f) => types.type_of(f),
301 #[cfg(feature = "llvm-17-or-lower")]
302 Constant::FPToUI(f) => types.type_of(f),
303 #[cfg(feature = "llvm-17-or-lower")]
304 Constant::FPToSI(f) => types.type_of(f),
305 #[cfg(feature = "llvm-17-or-lower")]
306 Constant::UIToFP(u) => types.type_of(u),
307 #[cfg(feature = "llvm-17-or-lower")]
308 Constant::SIToFP(s) => types.type_of(s),
309 Constant::PtrToInt(p) => types.type_of(p),
310 Constant::IntToPtr(i) => types.type_of(i),
311 Constant::BitCast(b) => types.type_of(b),
312 Constant::AddrSpaceCast(a) => types.type_of(a),
313 #[cfg(feature = "llvm-18-or-lower")]
314 Constant::ICmp(i) => types.type_of(i),
315 #[cfg(feature = "llvm-18-or-lower")]
316 Constant::FCmp(f) => types.type_of(f),
317 #[cfg(feature="llvm-16-or-lower")]
318 Constant::Select(s) => types.type_of(s),
319 #[cfg(feature="llvm-19-or-greater")]
320 Constant::PtrAuth { .. } => types.pointer(),
321 }
322 }
323}
324
325impl Display for Constant {
326 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
327 match self {
328 Constant::Int { bits, value } => {
329 if *bits == 1 {
330 if *value == 0 {
331 write!(f, "i1 false")
332 } else {
333 write!(f, "i1 true")
334 }
335 } else {
336 match *bits {
338 16 => {
339 let signed_val = (*value & 0xFFFF) as i16;
340 if signed_val > -1000 {
341 write!(f, "i{} {}", bits, signed_val)
342 } else {
343 write!(f, "i{} {}", bits, *value)
344 }
345 },
346 32 => {
347 let signed_val = (*value & 0xFFFF_FFFF) as i32;
348 if signed_val > -1000 {
349 write!(f, "i{} {}", bits, signed_val)
350 } else {
351 write!(f, "i{} {}", bits, *value)
352 }
353 },
354 64 => {
355 let signed_val = *value as i64;
356 if signed_val > -1000 {
357 write!(f, "i{} {}", bits, signed_val)
358 } else {
359 write!(f, "i{} {}", bits, *value)
360 }
361 },
362 _ => write!(f, "i{} {}", bits, value),
363 }
364 }
365 },
366 Constant::Float(float) => write!(f, "{}", float),
367 Constant::Null(ty) => write!(f, "{} null", ty),
368 Constant::AggregateZero(ty) => write!(f, "{} zeroinitializer", ty),
369 Constant::Struct {
370 values, is_packed, ..
371 } => {
372 if *is_packed {
373 write!(f, "<")?;
374 }
375 write!(f, "{{ ")?;
376 for (i, val) in values.iter().enumerate() {
377 if i == values.len() - 1 {
378 write!(f, "{}", val)?;
379 } else {
380 write!(f, "{}, ", val)?;
381 }
382 }
383 write!(f, " }}")?;
384 if *is_packed {
385 write!(f, ">")?;
386 }
387 Ok(())
388 },
389 Constant::Array { elements, .. } => {
390 write!(f, "[ ")?;
391 for (i, elt) in elements.iter().enumerate() {
392 if i == elements.len() - 1 {
393 write!(f, "{}", elt)?;
394 } else {
395 write!(f, "{}, ", elt)?;
396 }
397 }
398 write!(f, " ]")?;
399 Ok(())
400 },
401 Constant::Vector(v) => {
402 write!(f, "< ")?;
403 for (i, elt) in v.iter().enumerate() {
404 if i == v.len() - 1 {
405 write!(f, "{}", elt)?;
406 } else {
407 write!(f, "{}, ", elt)?;
408 }
409 }
410 write!(f, " >")?;
411 Ok(())
412 },
413 Constant::Undef(ty) => write!(f, "{} undef", ty),
414 #[cfg(feature = "llvm-12-or-greater")]
415 Constant::Poison(ty) => write!(f, "{} poison", ty),
416 Constant::BlockAddress => write!(f, "blockaddr"),
417 Constant::GlobalReference { name, ty } => {
418 let name = match name {
419 Name::Name(n) => String::clone(n),
420 Name::Number(n) => n.to_string(),
421 };
422 match ty.as_ref() {
423 Type::FuncType { .. } => {
424 write!(f, "@{}", name)
426 },
427 _ if cfg!(feature = "llvm-14-or-lower") => {
428 write!(f, "{}* @{}", ty, name)
430 },
431 _ => {
432 write!(f, "ptr @{}", name)
434 },
435 }
436 },
437 Constant::TokenNone => write!(f, "none"),
438 Constant::Add(a) => write!(f, "{}", a),
439 Constant::Sub(s) => write!(f, "{}", s),
440 Constant::Mul(m) => write!(f, "{}", m),
441 #[cfg(feature = "llvm-14-or-lower")]
442 Constant::UDiv(d) => write!(f, "{}", d),
443 #[cfg(feature = "llvm-14-or-lower")]
444 Constant::SDiv(d) => write!(f, "{}", d),
445 #[cfg(feature = "llvm-14-or-lower")]
446 Constant::URem(r) => write!(f, "{}", r),
447 #[cfg(feature = "llvm-14-or-lower")]
448 Constant::SRem(r) => write!(f, "{}", r),
449 #[cfg(feature = "llvm-17-or-lower")]
450 Constant::And(a) => write!(f, "{}", a),
451 #[cfg(feature = "llvm-17-or-lower")]
452 Constant::Or(o) => write!(f, "{}", o),
453 Constant::Xor(x) => write!(f, "{}", x),
454 #[cfg(feature = "llvm-18-or-lower")]
455 Constant::Shl(s) => write!(f, "{}", s),
456 #[cfg(feature = "llvm-17-or-lower")]
457 Constant::LShr(l) => write!(f, "{}", l),
458 #[cfg(feature = "llvm-17-or-lower")]
459 Constant::AShr(a) => write!(f, "{}", a),
460 #[cfg(feature = "llvm-14-or-lower")]
461 Constant::FAdd(a) => write!(f, "{}", a),
462 #[cfg(feature = "llvm-14-or-lower")]
463 Constant::FSub(s) => write!(f, "{}", s),
464 #[cfg(feature = "llvm-14-or-lower")]
465 Constant::FMul(m) => write!(f, "{}", m),
466 #[cfg(feature = "llvm-14-or-lower")]
467 Constant::FDiv(d) => write!(f, "{}", d),
468 #[cfg(feature = "llvm-14-or-lower")]
469 Constant::FRem(r) => write!(f, "{}", r),
470 Constant::ExtractElement(e) => write!(f, "{}", e),
471 Constant::InsertElement(i) => write!(f, "{}", i),
472 Constant::ShuffleVector(s) => write!(f, "{}", s),
473 #[cfg(feature = "llvm-14-or-lower")]
474 Constant::ExtractValue(e) => write!(f, "{}", e),
475 #[cfg(feature = "llvm-14-or-lower")]
476 Constant::InsertValue(i) => write!(f, "{}", i),
477 Constant::GetElementPtr(g) => write!(f, "{}", g),
478 Constant::Trunc(t) => write!(f, "{}", t),
479 #[cfg(feature = "llvm-17-or-lower")]
480 Constant::ZExt(z) => write!(f, "{}", z),
481 #[cfg(feature = "llvm-17-or-lower")]
482 Constant::SExt(s) => write!(f, "{}", s),
483 #[cfg(feature = "llvm-17-or-lower")]
484 Constant::FPTrunc(t) => write!(f, "{}", t),
485 #[cfg(feature = "llvm-17-or-lower")]
486 Constant::FPExt(e) => write!(f, "{}", e),
487 #[cfg(feature = "llvm-17-or-lower")]
488 Constant::FPToUI(t) => write!(f, "{}", t),
489 #[cfg(feature = "llvm-17-or-lower")]
490 Constant::FPToSI(t) => write!(f, "{}", t),
491 #[cfg(feature = "llvm-17-or-lower")]
492 Constant::UIToFP(t) => write!(f, "{}", t),
493 #[cfg(feature = "llvm-17-or-lower")]
494 Constant::SIToFP(t) => write!(f, "{}", t),
495 Constant::PtrToInt(p) => write!(f, "{}", p),
496 Constant::IntToPtr(i) => write!(f, "{}", i),
497 Constant::BitCast(b) => write!(f, "{}", b),
498 Constant::AddrSpaceCast(a) => write!(f, "{}", a),
499 #[cfg(feature = "llvm-18-or-lower")]
500 Constant::ICmp(i) => write!(f, "{}", i),
501 #[cfg(feature = "llvm-18-or-lower")]
502 Constant::FCmp(c) => write!(f, "{}", c),
503 #[cfg(feature="llvm-16-or-lower")]
504 Constant::Select(s) => write!(f, "{}", s),
505 #[cfg(feature="llvm-19-or-greater")]
506 Constant::PtrAuth { ptr, key, disc, addr_disc } => {
507 write!(f, "ptrauth({}, {}, {}, {})", ptr, key, disc, addr_disc)
508 }
509 }
510 }
511}
512
513#[derive(PartialEq, Clone, Debug, Hash)]
522pub struct ConstantRef(Arc<Constant>);
523
524impl AsRef<Constant> for ConstantRef {
525 fn as_ref(&self) -> &Constant {
526 self.0.as_ref()
527 }
528}
529
530impl Deref for ConstantRef {
531 type Target = Constant;
532
533 fn deref(&self) -> &Constant {
534 self.0.deref()
535 }
536}
537
538impl Typed for ConstantRef {
539 fn get_type(&self, types: &Types) -> TypeRef {
540 self.as_ref().get_type(types)
541 }
542}
543
544impl Display for ConstantRef {
545 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
546 write!(f, "{}", &self.0)
547 }
548}
549
550impl ConstantRef {
551 pub fn new(c: Constant) -> Self {
557 Self(Arc::new(c))
558 }
559}
560
561pub trait ConstUnaryOp {
562 fn get_operand(&self) -> ConstantRef;
563}
564
565pub trait ConstBinaryOp {
566 fn get_operand0(&self) -> ConstantRef;
567 fn get_operand1(&self) -> ConstantRef;
568}
569
570macro_rules! impl_constexpr {
571 ($expr:ty, $id:ident) => {
572 impl From<$expr> for Constant {
573 fn from(expr: $expr) -> Constant {
574 Constant::$id(expr)
575 }
576 }
577
578 impl TryFrom<Constant> for $expr {
579 type Error = &'static str;
580 fn try_from(constant: Constant) -> Result<Self, Self::Error> {
581 match constant {
582 Constant::$id(expr) => Ok(expr),
583 _ => Err("Constant is not of requested kind"),
584 }
585 }
586 }
587 };
588}
589
590macro_rules! impl_unop {
593 ($expr:ty) => {
594 impl ConstUnaryOp for $expr {
595 fn get_operand(&self) -> ConstantRef {
596 self.operand.clone()
597 }
598 }
599 };
600}
601
602macro_rules! impl_binop {
606 ($expr:ty, $dispname:expr) => {
607 impl ConstBinaryOp for $expr {
608 fn get_operand0(&self) -> ConstantRef {
609 self.operand0.clone()
610 }
611 fn get_operand1(&self) -> ConstantRef {
612 self.operand1.clone()
613 }
614 }
615 };
616}
617
618macro_rules! binop_same_type {
621 ($expr:ty, $dispname:expr) => {
622 impl_binop!($expr, $dispname);
623
624 impl Typed for $expr {
625 fn get_type(&self, types: &Types) -> TypeRef {
626 let t = types.type_of(&self.get_operand0());
627 debug_assert_eq!(t, types.type_of(&self.get_operand1()));
628 t
629 }
630 }
631
632 impl Display for $expr {
633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
634 write!(f, "{} ({}, {})", $dispname, &self.operand0, &self.operand1)
635 }
636 }
637 };
638}
639
640#[cfg(feature = "llvm-18-or-lower")]
643macro_rules! binop_left_type {
644 ($expr:ty, $dispname:expr) => {
645 impl_binop!($expr, $dispname);
646
647 impl Typed for $expr {
648 fn get_type(&self, types: &Types) -> TypeRef {
649 types.type_of(&self.get_operand0())
650 }
651 }
652
653 impl Display for $expr {
654 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
655 write!(f, "{} ({}, {})", $dispname, &self.operand0, &self.operand1)
656 }
657 }
658 };
659}
660
661macro_rules! unop_explicitly_typed {
663 ($expr:ty, $dispname:expr) => {
664 impl_unop!($expr);
665
666 impl Typed for $expr {
667 fn get_type(&self, _types: &Types) -> TypeRef {
668 self.to_type.clone()
669 }
670 }
671
672 impl Display for $expr {
673 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
674 write!(
675 f,
676 "{} ({} to {})",
677 $dispname,
678 &self.get_operand(),
679 &self.to_type,
680 )
681 }
682 }
683 };
684}
685
686#[derive(PartialEq, Clone, Debug, Hash)]
687pub struct Add {
688 pub operand0: ConstantRef,
689 pub operand1: ConstantRef,
690 }
693
694impl_constexpr!(Add, Add);
695binop_same_type!(Add, "add");
696
697#[derive(PartialEq, Clone, Debug, Hash)]
698pub struct Sub {
699 pub operand0: ConstantRef,
700 pub operand1: ConstantRef,
701 }
704
705impl_constexpr!(Sub, Sub);
706binop_same_type!(Sub, "sub");
707
708#[derive(PartialEq, Clone, Debug, Hash)]
709pub struct Mul {
710 pub operand0: ConstantRef,
711 pub operand1: ConstantRef,
712 }
715
716impl_constexpr!(Mul, Mul);
717binop_same_type!(Mul, "mul");
718
719#[cfg(feature = "llvm-14-or-lower")]
720#[derive(PartialEq, Clone, Debug, Hash)]
721pub struct UDiv {
722 pub operand0: ConstantRef,
723 pub operand1: ConstantRef,
724 }
726
727#[cfg(feature = "llvm-14-or-lower")]
728impl_constexpr!(UDiv, UDiv);
729#[cfg(feature = "llvm-14-or-lower")]
730binop_same_type!(UDiv, "udiv");
731
732#[cfg(feature = "llvm-14-or-lower")]
733#[derive(PartialEq, Clone, Debug, Hash)]
734pub struct SDiv {
735 pub operand0: ConstantRef,
736 pub operand1: ConstantRef,
737 }
739
740#[cfg(feature = "llvm-14-or-lower")]
741impl_constexpr!(SDiv, SDiv);
742#[cfg(feature = "llvm-14-or-lower")]
743binop_same_type!(SDiv, "sdiv");
744
745#[cfg(feature = "llvm-14-or-lower")]
746#[derive(PartialEq, Clone, Debug, Hash)]
747pub struct URem {
748 pub operand0: ConstantRef,
749 pub operand1: ConstantRef,
750}
751
752#[cfg(feature = "llvm-14-or-lower")]
753impl_constexpr!(URem, URem);
754#[cfg(feature = "llvm-14-or-lower")]
755binop_same_type!(URem, "urem");
756
757#[cfg(feature = "llvm-14-or-lower")]
758#[derive(PartialEq, Clone, Debug, Hash)]
759pub struct SRem {
760 pub operand0: ConstantRef,
761 pub operand1: ConstantRef,
762}
763
764#[cfg(feature = "llvm-14-or-lower")]
765impl_constexpr!(SRem, SRem);
766#[cfg(feature = "llvm-14-or-lower")]
767binop_same_type!(SRem, "srem");
768
769#[cfg(feature = "llvm-17-or-lower")]
770#[derive(PartialEq, Clone, Debug, Hash)]
771pub struct And {
772 pub operand0: ConstantRef,
773 pub operand1: ConstantRef,
774}
775
776#[cfg(feature = "llvm-17-or-lower")]
777impl_constexpr!(And, And);
778#[cfg(feature = "llvm-17-or-lower")]
779binop_same_type!(And, "and");
780
781#[cfg(feature = "llvm-17-or-lower")]
782#[derive(PartialEq, Clone, Debug, Hash)]
783pub struct Or {
784 pub operand0: ConstantRef,
785 pub operand1: ConstantRef,
786}
787
788#[cfg(feature = "llvm-17-or-lower")]
789impl_constexpr!(Or, Or);
790#[cfg(feature = "llvm-17-or-lower")]
791binop_same_type!(Or, "or");
792
793#[derive(PartialEq, Clone, Debug, Hash)]
794pub struct Xor {
795 pub operand0: ConstantRef,
796 pub operand1: ConstantRef,
797}
798
799impl_constexpr!(Xor, Xor);
800binop_same_type!(Xor, "xor");
801
802#[cfg(feature = "llvm-18-or-lower")]
803#[derive(PartialEq, Clone, Debug, Hash)]
804pub struct Shl {
805 pub operand0: ConstantRef,
806 pub operand1: ConstantRef,
807 }
810
811#[cfg(feature = "llvm-18-or-lower")]
812impl_constexpr!(Shl, Shl);
813#[cfg(feature = "llvm-18-or-lower")]
814binop_left_type!(Shl, "shl");
815
816#[cfg(feature = "llvm-17-or-lower")]
817#[derive(PartialEq, Clone, Debug, Hash)]
818pub struct LShr {
819 pub operand0: ConstantRef,
820 pub operand1: ConstantRef,
821 }
823
824#[cfg(feature = "llvm-17-or-lower")]
825impl_constexpr!(LShr, LShr);
826#[cfg(feature = "llvm-17-or-lower")]
827binop_left_type!(LShr, "lshr");
828
829#[cfg(feature = "llvm-17-or-lower")]
830#[derive(PartialEq, Clone, Debug, Hash)]
831pub struct AShr {
832 pub operand0: ConstantRef,
833 pub operand1: ConstantRef,
834 }
836
837#[cfg(feature = "llvm-17-or-lower")]
838impl_constexpr!(AShr, AShr);
839#[cfg(feature = "llvm-17-or-lower")]
840binop_left_type!(AShr, "ashr");
841
842#[cfg(feature = "llvm-14-or-lower")]
843#[derive(PartialEq, Clone, Debug, Hash)]
844pub struct FAdd {
845 pub operand0: ConstantRef,
846 pub operand1: ConstantRef,
847}
848
849#[cfg(feature = "llvm-14-or-lower")]
850impl_constexpr!(FAdd, FAdd);
851#[cfg(feature = "llvm-14-or-lower")]
852binop_same_type!(FAdd, "fadd");
853
854#[cfg(feature = "llvm-14-or-lower")]
855#[derive(PartialEq, Clone, Debug, Hash)]
856pub struct FSub {
857 pub operand0: ConstantRef,
858 pub operand1: ConstantRef,
859}
860
861#[cfg(feature = "llvm-14-or-lower")]
862impl_constexpr!(FSub, FSub);
863#[cfg(feature = "llvm-14-or-lower")]
864binop_same_type!(FSub, "fsub");
865
866#[cfg(feature = "llvm-14-or-lower")]
867#[derive(PartialEq, Clone, Debug, Hash)]
868pub struct FMul {
869 pub operand0: ConstantRef,
870 pub operand1: ConstantRef,
871}
872
873#[cfg(feature = "llvm-14-or-lower")]
874impl_constexpr!(FMul, FMul);
875#[cfg(feature = "llvm-14-or-lower")]
876binop_same_type!(FMul, "fmul");
877
878#[cfg(feature = "llvm-14-or-lower")]
879#[derive(PartialEq, Clone, Debug, Hash)]
880pub struct FDiv {
881 pub operand0: ConstantRef,
882 pub operand1: ConstantRef,
883}
884
885#[cfg(feature = "llvm-14-or-lower")]
886impl_constexpr!(FDiv, FDiv);
887#[cfg(feature = "llvm-14-or-lower")]
888binop_same_type!(FDiv, "fdiv");
889
890#[cfg(feature = "llvm-14-or-lower")]
891#[derive(PartialEq, Clone, Debug, Hash)]
892pub struct FRem {
893 pub operand0: ConstantRef,
894 pub operand1: ConstantRef,
895}
896
897#[cfg(feature = "llvm-14-or-lower")]
898impl_constexpr!(FRem, FRem);
899#[cfg(feature = "llvm-14-or-lower")]
900binop_same_type!(FRem, "frem");
901
902#[derive(PartialEq, Clone, Debug, Hash)]
903pub struct ExtractElement {
904 pub vector: ConstantRef,
905 pub index: ConstantRef,
906}
907
908impl_constexpr!(ExtractElement, ExtractElement);
909
910impl Typed for ExtractElement {
911 fn get_type(&self, types: &Types) -> TypeRef {
912 match types.type_of(&self.vector).as_ref() {
913 Type::VectorType { element_type, .. } => element_type.clone(),
914 ty => panic!(
915 "Expected an ExtractElement vector to be VectorType, got {:?}",
916 ty
917 ),
918 }
919 }
920}
921
922impl Display for ExtractElement {
923 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
924 write!(f, "extractelement ({}, {})", &self.vector, &self.index)
925 }
926}
927
928#[derive(PartialEq, Clone, Debug, Hash)]
929pub struct InsertElement {
930 pub vector: ConstantRef,
931 pub element: ConstantRef,
932 pub index: ConstantRef,
933}
934
935impl_constexpr!(InsertElement, InsertElement);
936
937impl Typed for InsertElement {
938 fn get_type(&self, types: &Types) -> TypeRef {
939 types.type_of(&self.vector)
940 }
941}
942
943impl Display for InsertElement {
944 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
945 write!(
946 f,
947 "insertelement ({}, {}, {})",
948 &self.vector, &self.element, &self.index,
949 )
950 }
951}
952
953#[derive(PartialEq, Clone, Debug, Hash)]
954pub struct ShuffleVector {
955 pub operand0: ConstantRef,
956 pub operand1: ConstantRef,
957 pub mask: ConstantRef,
958}
959
960impl_constexpr!(ShuffleVector, ShuffleVector);
961impl_binop!(ShuffleVector, "shufflevector");
962
963impl Typed for ShuffleVector {
964 fn get_type(&self, types: &Types) -> TypeRef {
965 let ty = types.type_of(&self.operand0);
966 debug_assert_eq!(ty, types.type_of(&self.operand1));
967 match ty.as_ref() {
968 Type::VectorType { element_type, .. } => match types.type_of(&self.mask).as_ref() {
969 #[cfg(feature = "llvm-11-or-greater")]
970 Type::VectorType {
971 num_elements,
972 scalable,
973 ..
974 } => types.vector_of(element_type.clone(), *num_elements, *scalable),
975 #[cfg(feature = "llvm-10-or-lower")]
976 Type::VectorType { num_elements, .. } => {
977 types.vector_of(element_type.clone(), *num_elements)
978 },
979 ty => panic!(
980 "Expected a ShuffleVector mask to be VectorType, got {:?}",
981 ty
982 ),
983 },
984 _ => panic!(
985 "Expected a ShuffleVector operand to be VectorType, got {:?}",
986 ty
987 ),
988 }
989 }
990}
991
992impl Display for ShuffleVector {
993 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
994 write!(
995 f,
996 "shufflevector ({}, {}, {})",
997 &self.operand0, &self.operand1, &self.mask,
998 )
999 }
1000}
1001
1002#[cfg(feature = "llvm-14-or-lower")]
1003#[derive(PartialEq, Clone, Debug, Hash)]
1004pub struct ExtractValue {
1005 pub aggregate: ConstantRef,
1006 pub indices: Vec<u32>,
1007}
1008
1009#[cfg(feature = "llvm-14-or-lower")]
1010impl_constexpr!(ExtractValue, ExtractValue);
1011
1012#[cfg(feature = "llvm-14-or-lower")]
1013impl Typed for ExtractValue {
1014 fn get_type(&self, types: &Types) -> TypeRef {
1015 ev_type(types.type_of(&self.aggregate), self.indices.iter().copied())
1016 }
1017}
1018
1019#[cfg(feature = "llvm-14-or-lower")]
1020fn ev_type(cur_type: TypeRef, mut indices: impl Iterator<Item = u32>) -> TypeRef {
1021 match indices.next() {
1022 None => cur_type,
1023 Some(index) => match cur_type.as_ref() {
1024 Type::ArrayType { element_type, .. } => ev_type(element_type.clone(), indices),
1025 Type::StructType { element_types, .. } => ev_type(
1026 element_types
1027 .get(index as usize)
1028 .expect("ExtractValue index out of range")
1029 .clone(),
1030 indices,
1031 ),
1032 _ => panic!(
1033 "ExtractValue from something that's not ArrayType or StructType; its type is {:?}",
1034 cur_type
1035 ),
1036 },
1037 }
1038}
1039
1040#[cfg(feature = "llvm-14-or-lower")]
1041impl Display for ExtractValue {
1042 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1043 write!(f, "extractvalue ({}", &self.aggregate)?;
1044 for idx in &self.indices {
1045 write!(f, ", {}", idx)?;
1046 }
1047 write!(f, ")")?;
1048 Ok(())
1049 }
1050}
1051
1052#[cfg(feature = "llvm-14-or-lower")]
1053#[derive(PartialEq, Clone, Debug, Hash)]
1054pub struct InsertValue {
1055 pub aggregate: ConstantRef,
1056 pub element: ConstantRef,
1057 pub indices: Vec<u32>,
1058}
1059
1060#[cfg(feature = "llvm-14-or-lower")]
1061impl_constexpr!(InsertValue, InsertValue);
1062
1063#[cfg(feature = "llvm-14-or-lower")]
1064impl Typed for InsertValue {
1065 fn get_type(&self, types: &Types) -> TypeRef {
1066 types.type_of(&self.aggregate)
1067 }
1068}
1069
1070#[cfg(feature = "llvm-14-or-lower")]
1071impl Display for InsertValue {
1072 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1073 write!(f, "insertvalue ({}, {}", &self.aggregate, &self.element)?;
1074 for idx in &self.indices {
1075 write!(f, ", {}", idx)?;
1076 }
1077 write!(f, ")")?;
1078 Ok(())
1079 }
1080}
1081
1082#[derive(PartialEq, Clone, Debug, Hash)]
1083pub struct GetElementPtr {
1084 pub address: ConstantRef,
1085 pub indices: Vec<ConstantRef>,
1086 pub in_bounds: bool,
1087}
1088
1089impl_constexpr!(GetElementPtr, GetElementPtr);
1090
1091#[cfg(feature = "llvm-14-or-lower")]
1092impl Typed for GetElementPtr {
1093 fn get_type(&self, types: &Types) -> TypeRef {
1094 gep_type(types.type_of(&self.address), self.indices.iter(), types)
1095 }
1096}
1097#[cfg(feature = "llvm-15-or-greater")]
1098impl Typed for GetElementPtr {
1099 fn get_type(&self, types: &Types) -> TypeRef {
1100 types.pointer()
1101 }
1102}
1103
1104#[cfg(feature = "llvm-14-or-lower")]
1105fn gep_type<'c>(
1106 cur_type: TypeRef,
1107 mut indices: impl Iterator<Item = &'c ConstantRef>,
1108 types: &Types,
1109) -> TypeRef {
1110 match indices.next() {
1111 None => types.pointer_to(cur_type), Some(index) => match cur_type.as_ref() {
1113 Type::PointerType { pointee_type, .. } => gep_type(pointee_type.clone(), indices, types),
1114 Type::VectorType { element_type, .. } => gep_type(element_type.clone(), indices, types),
1115 Type::ArrayType { element_type, .. } => gep_type(element_type.clone(), indices, types),
1116 Type::StructType { element_types, .. } => {
1117 if let Constant::Int { value, .. } = index.as_ref() {
1118 gep_type(
1119 element_types.get(*value as usize).cloned().expect("GEP index out of range"),
1120 indices,
1121 types,
1122 )
1123 } else {
1124 panic!("Expected GEP index on a constant struct to be a Constant::Int; got {:?}", index)
1125 }
1126 },
1127 Type::NamedStructType { name } => match types.named_struct_def(name) {
1128 None => panic!("Named struct with no definition (struct name {:?})", name),
1129 Some(NamedStructDef::Opaque) => panic!("GEP on an opaque struct type"),
1130 Some(NamedStructDef::Defined(ty)) => match ty.as_ref() {
1131 Type::StructType { element_types, .. } => {
1132 if let Constant::Int { value, .. } = index.as_ref() {
1133 gep_type(element_types.get(*value as usize).cloned().expect("GEP index out of range"), indices, types)
1134 } else {
1135 panic!("Expected GEP index on a struct to be a Constant::Int; got {:?}", index)
1136 }
1137 },
1138 ty => panic!("Expected NamedStructDef inner type to be a StructType; got {:?}", ty),
1139 },
1140 }
1141 _ => panic!("Expected GEP base type to be a PointerType, VectorType, ArrayType, StructType, or NamedStructType; got {:?}", cur_type),
1142 },
1143 }
1144}
1145
1146impl Display for GetElementPtr {
1147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1148 write!(
1149 f,
1150 "getelementptr{} ({}",
1151 if self.in_bounds { " inbounds" } else { "" },
1152 &self.address
1153 )?;
1154 for idx in &self.indices {
1155 write!(f, ", {}", idx)?;
1156 }
1157 write!(f, ")")?;
1158 Ok(())
1159 }
1160}
1161
1162#[derive(PartialEq, Clone, Debug, Hash)]
1163pub struct Trunc {
1164 pub operand: ConstantRef,
1165 pub to_type: TypeRef,
1166}
1167
1168impl_constexpr!(Trunc, Trunc);
1169unop_explicitly_typed!(Trunc, "trunc");
1170
1171#[cfg(feature = "llvm-17-or-lower")]
1172#[derive(PartialEq, Clone, Debug, Hash)]
1173pub struct ZExt {
1174 pub operand: ConstantRef,
1175 pub to_type: TypeRef,
1176}
1177
1178#[cfg(feature = "llvm-17-or-lower")]
1179impl_constexpr!(ZExt, ZExt);
1180#[cfg(feature = "llvm-17-or-lower")]
1181unop_explicitly_typed!(ZExt, "zext");
1182
1183#[cfg(feature = "llvm-17-or-lower")]
1184#[derive(PartialEq, Clone, Debug, Hash)]
1185pub struct SExt {
1186 pub operand: ConstantRef,
1187 pub to_type: TypeRef,
1188}
1189
1190#[cfg(feature = "llvm-17-or-lower")]
1191impl_constexpr!(SExt, SExt);
1192#[cfg(feature = "llvm-17-or-lower")]
1193unop_explicitly_typed!(SExt, "sext");
1194
1195#[cfg(feature = "llvm-17-or-lower")]
1196#[derive(PartialEq, Clone, Debug, Hash)]
1197pub struct FPTrunc {
1198 pub operand: ConstantRef,
1199 pub to_type: TypeRef,
1200}
1201#[cfg(feature = "llvm-17-or-lower")]
1202impl_constexpr!(FPTrunc, FPTrunc);
1203#[cfg(feature = "llvm-17-or-lower")]
1204unop_explicitly_typed!(FPTrunc, "fptrunc");
1205
1206#[cfg(feature = "llvm-17-or-lower")]
1207#[derive(PartialEq, Clone, Debug, Hash)]
1208pub struct FPExt {
1209 pub operand: ConstantRef,
1210 pub to_type: TypeRef,
1211}
1212
1213#[cfg(feature = "llvm-17-or-lower")]
1214impl_constexpr!(FPExt, FPExt);
1215#[cfg(feature = "llvm-17-or-lower")]
1216unop_explicitly_typed!(FPExt, "fpext");
1217
1218#[cfg(feature = "llvm-17-or-lower")]
1219#[derive(PartialEq, Clone, Debug, Hash)]
1220pub struct FPToUI {
1221 pub operand: ConstantRef,
1222 pub to_type: TypeRef,
1223}
1224
1225#[cfg(feature = "llvm-17-or-lower")]
1226impl_constexpr!(FPToUI, FPToUI);
1227#[cfg(feature = "llvm-17-or-lower")]
1228unop_explicitly_typed!(FPToUI, "fptoui");
1229
1230#[cfg(feature = "llvm-17-or-lower")]
1231#[derive(PartialEq, Clone, Debug, Hash)]
1232pub struct FPToSI {
1233 pub operand: ConstantRef,
1234 pub to_type: TypeRef,
1235}
1236
1237#[cfg(feature = "llvm-17-or-lower")]
1238impl_constexpr!(FPToSI, FPToSI);
1239#[cfg(feature = "llvm-17-or-lower")]
1240unop_explicitly_typed!(FPToSI, "fptosi");
1241
1242#[cfg(feature = "llvm-17-or-lower")]
1243#[derive(PartialEq, Clone, Debug, Hash)]
1244pub struct UIToFP {
1245 pub operand: ConstantRef,
1246 pub to_type: TypeRef,
1247}
1248
1249#[cfg(feature = "llvm-17-or-lower")]
1250impl_constexpr!(UIToFP, UIToFP);
1251#[cfg(feature = "llvm-17-or-lower")]
1252unop_explicitly_typed!(UIToFP, "uitofp");
1253
1254#[cfg(feature = "llvm-17-or-lower")]
1255#[derive(PartialEq, Clone, Debug, Hash)]
1256pub struct SIToFP {
1257 pub operand: ConstantRef,
1258 pub to_type: TypeRef,
1259}
1260
1261#[cfg(feature = "llvm-17-or-lower")]
1262impl_constexpr!(SIToFP, SIToFP);
1263#[cfg(feature = "llvm-17-or-lower")]
1264unop_explicitly_typed!(SIToFP, "sitofp");
1265
1266#[derive(PartialEq, Clone, Debug, Hash)]
1267pub struct PtrToInt {
1268 pub operand: ConstantRef,
1269 pub to_type: TypeRef,
1270}
1271
1272impl_constexpr!(PtrToInt, PtrToInt);
1273unop_explicitly_typed!(PtrToInt, "ptrtoint");
1274
1275#[derive(PartialEq, Clone, Debug, Hash)]
1276pub struct IntToPtr {
1277 pub operand: ConstantRef,
1278 pub to_type: TypeRef,
1279}
1280
1281impl_constexpr!(IntToPtr, IntToPtr);
1282unop_explicitly_typed!(IntToPtr, "inttoptr");
1283
1284#[derive(PartialEq, Clone, Debug, Hash)]
1285pub struct BitCast {
1286 pub operand: ConstantRef,
1287 pub to_type: TypeRef,
1288}
1289
1290impl_constexpr!(BitCast, BitCast);
1291unop_explicitly_typed!(BitCast, "bitcast");
1292
1293#[derive(PartialEq, Clone, Debug, Hash)]
1294pub struct AddrSpaceCast {
1295 pub operand: ConstantRef,
1296 pub to_type: TypeRef,
1297}
1298
1299impl_constexpr!(AddrSpaceCast, AddrSpaceCast);
1300unop_explicitly_typed!(AddrSpaceCast, "addrspacecast");
1301
1302#[cfg(feature = "llvm-18-or-lower")]
1303#[derive(PartialEq, Clone, Debug, Hash)]
1304pub struct ICmp {
1305 pub predicate: IntPredicate,
1306 pub operand0: ConstantRef,
1307 pub operand1: ConstantRef,
1308}
1309
1310#[cfg(feature = "llvm-18-or-lower")]
1311impl_constexpr!(ICmp, ICmp);
1312#[cfg(feature = "llvm-18-or-lower")]
1313impl_binop!(ICmp, "icmp");
1314
1315#[cfg(feature = "llvm-18-or-lower")]
1316impl Typed for ICmp {
1317 fn get_type(&self, types: &Types) -> TypeRef {
1318 let ty = types.type_of(&self.operand0);
1319 debug_assert_eq!(ty, types.type_of(&self.operand1));
1320 match ty.as_ref() {
1321 #[cfg(feature = "llvm-11-or-greater")]
1322 Type::VectorType {
1323 num_elements,
1324 scalable,
1325 ..
1326 } => types.vector_of(types.bool(), *num_elements, *scalable),
1327 #[cfg(feature = "llvm-10-or-lower")]
1328 Type::VectorType { num_elements, .. } => types.vector_of(types.bool(), *num_elements),
1329 _ => types.bool(),
1330 }
1331 }
1332}
1333
1334#[cfg(feature = "llvm-18-or-lower")]
1335impl Display for ICmp {
1336 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1337 write!(
1338 f,
1339 "icmp {} ({}, {})",
1340 &self.predicate, &self.operand0, &self.operand1,
1341 )
1342 }
1343}
1344
1345#[cfg(feature = "llvm-18-or-lower")]
1346#[derive(PartialEq, Clone, Debug, Hash)]
1347pub struct FCmp {
1348 pub predicate: FPPredicate,
1349 pub operand0: ConstantRef,
1350 pub operand1: ConstantRef,
1351}
1352
1353#[cfg(feature = "llvm-18-or-lower")]
1354impl_constexpr!(FCmp, FCmp);
1355#[cfg(feature = "llvm-18-or-lower")]
1356impl_binop!(FCmp, "fcmp");
1357
1358#[cfg(feature = "llvm-18-or-lower")]
1359impl Typed for FCmp {
1360 fn get_type(&self, types: &Types) -> TypeRef {
1361 let ty = types.type_of(&self.operand0);
1362 debug_assert_eq!(ty, types.type_of(&self.operand1));
1363 match ty.as_ref() {
1364 #[cfg(feature = "llvm-11-or-greater")]
1365 Type::VectorType {
1366 num_elements,
1367 scalable,
1368 ..
1369 } => types.vector_of(types.bool(), *num_elements, *scalable),
1370 #[cfg(feature = "llvm-10-or-lower")]
1371 Type::VectorType { num_elements, .. } => types.vector_of(types.bool(), *num_elements),
1372 _ => types.bool(),
1373 }
1374 }
1375}
1376
1377#[cfg(feature = "llvm-18-or-lower")]
1378impl Display for FCmp {
1379 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1380 write!(
1381 f,
1382 "fcmp {} ({}, {})",
1383 &self.predicate, &self.operand0, &self.operand1,
1384 )
1385 }
1386}
1387
1388#[cfg(feature="llvm-16-or-lower")]
1389#[derive(PartialEq, Clone, Debug, Hash)]
1390pub struct Select {
1391 pub condition: ConstantRef,
1392 pub true_value: ConstantRef,
1393 pub false_value: ConstantRef,
1394}
1395
1396#[cfg(feature="llvm-16-or-lower")]
1397impl_constexpr!(Select, Select);
1398
1399#[cfg(feature="llvm-16-or-lower")]
1400impl Typed for Select {
1401 fn get_type(&self, types: &Types) -> TypeRef {
1402 let t = types.type_of(&self.true_value);
1403 debug_assert_eq!(t, types.type_of(&self.false_value));
1404 t
1405 }
1406}
1407
1408#[cfg(feature="llvm-16-or-lower")]
1409impl Display for Select {
1410 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1411 write!(
1412 f,
1413 "select ({}, {}, {})",
1414 &self.condition, &self.true_value, &self.false_value,
1415 )
1416 }
1417}
1418
1419use crate::llvm_sys::*;
1424use crate::module::ModuleContext;
1425use std::collections::hash_map::Entry;
1426
1427impl Constant {
1428 pub(crate) fn from_llvm_ref(constant: LLVMValueRef, ctx: &mut ModuleContext) -> ConstantRef {
1429 if let Some(constantref) = ctx.constants.get(&constant) {
1430 return constantref.clone();
1431 }
1432 let parsed = Self::parse_from_llvm_ref(constant, ctx);
1433 match ctx.constants.entry(constant) {
1434 Entry::Occupied(_) => panic!("This case should have been handled above"),
1435 Entry::Vacant(ventry) => ventry.insert(ConstantRef::new(parsed)).clone(),
1436 }
1437 }
1438
1439 fn parse_from_llvm_ref(constant: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1440 use llvm_sys::LLVMValueKind;
1441 if unsafe { LLVMIsAConstant(constant).is_null() } {
1442 panic!(
1443 "Constant::from_llvm_ref: argument wasn't a constant; ValueKind {:?}",
1444 unsafe { LLVMGetValueKind(constant) }
1445 )
1446 }
1447 match unsafe { LLVMGetValueKind(constant) } {
1448 LLVMValueKind::LLVMConstantIntValueKind => {
1449 match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1450 Type::IntegerType { bits } => Constant::Int {
1451 bits: *bits,
1452 value: unsafe { LLVMConstIntGetZExtValue(constant) } as u64,
1453 },
1454 ty => panic!("Expected Constant::Int to have type Type::IntegerType; got {:?}", ty),
1455 }
1456 },
1457 LLVMValueKind::LLVMConstantFPValueKind => {
1458 match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1459 Type::FPType(fptype) => Constant::Float(match fptype {
1460 FPType::Half => Float::Half,
1461 #[cfg(feature="llvm-11-or-greater")]
1462 FPType::BFloat => Float::BFloat,
1463 FPType::Single => Float::Single( unsafe {
1464 let mut b = 0;
1465 let b_ptr: *mut std::os::raw::c_int = &mut b;
1466 LLVMConstRealGetDouble(constant, b_ptr)
1467 } as f32),
1468 FPType::Double => Float::Double( unsafe {
1469 let mut b = 0;
1470 let b_ptr: *mut std::os::raw::c_int = &mut b;
1471 LLVMConstRealGetDouble(constant, b_ptr)
1472 } ),
1473 FPType::FP128 => Float::Quadruple,
1474 FPType::X86_FP80 => Float::X86_FP80,
1475 FPType::PPC_FP128 => Float::PPC_FP128,
1476 }),
1477 ty => panic!("Expected Constant::Float to have type Type::FPType; got {:?}", ty),
1478 }
1479 },
1480 LLVMValueKind::LLVMConstantStructValueKind => {
1481 let (num_elements, is_packed) = match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1482 Type::StructType { element_types, is_packed } => (element_types.len(), *is_packed),
1483 Type::NamedStructType { name } => match ctx.types.named_struct_def(name) {
1484 NamedStructDef::Opaque => panic!("Constant of opaque struct type (struct name {:?})", name),
1485 NamedStructDef::Defined(ty) => match ty.as_ref() {
1486 Type::StructType { element_types, is_packed } => {
1487 (element_types.len(), *is_packed)
1488 },
1489 ty => panic!("Expected NamedStructDef inner type to be a StructType, but it actually is a {:?}", ty),
1490 },
1491 },
1492 ty => panic!("Expected Constant::Struct to have type StructType or NamedStructType; got {:?}", ty),
1493 };
1494 Constant::Struct {
1495 name: None, values: {
1497 (0 .. num_elements).map(|i| {
1498 Constant::from_llvm_ref( unsafe { LLVMGetOperand(constant, i as u32) }, ctx)
1499 }).collect()
1500 },
1501 is_packed,
1502 }
1503 },
1504 LLVMValueKind::LLVMConstantArrayValueKind => {
1505 match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1506 Type::ArrayType { element_type, num_elements } => Constant::Array {
1507 element_type: element_type.clone(),
1508 elements: {
1509 (0 .. *num_elements).map(|i| Constant::from_llvm_ref( unsafe { LLVMGetOperand(constant, i as u32) }, ctx)).collect()
1510 },
1511 },
1512 ty => panic!("Expected Constant::Array to have type Type::ArrayType; got {:?}", ty),
1513 }
1514 },
1515 LLVMValueKind::LLVMConstantVectorValueKind => {
1516 let num_elements = unsafe { LLVMGetNumOperands(constant) };
1517 Constant::Vector(
1518 (0 .. num_elements).map(|i| Constant::from_llvm_ref( unsafe { LLVMGetOperand(constant, i as u32) }, ctx)).collect()
1519 )
1520 },
1521 LLVMValueKind::LLVMConstantDataArrayValueKind => {
1522 match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1523 Type::ArrayType { element_type, num_elements } => Constant::Array {
1524 element_type: element_type.clone(),
1525 elements: {
1526 #[cfg(feature = "llvm-14-or-lower")]
1527 { (0 .. *num_elements).map(|i| Constant::from_llvm_ref( unsafe { LLVMGetElementAsConstant(constant, i as u32) }, ctx)).collect() }
1528 #[cfg(feature = "llvm-15-or-greater")]
1529 { (0 .. *num_elements).map(|i| Constant::from_llvm_ref( unsafe { LLVMGetAggregateElement(constant, i as u32) }, ctx)).collect() }
1530 },
1531 },
1532 ty => panic!("Expected ConstantDataArray to have type Type::ArrayType; got {:?}", ty),
1533 }
1534 },
1535 LLVMValueKind::LLVMConstantDataVectorValueKind => {
1536 match ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ).as_ref() {
1537 Type::VectorType { num_elements, .. } => Constant::Vector(
1538 (0 .. *num_elements).map(
1539 |i| Constant::from_llvm_ref(
1540 unsafe {
1541 #[cfg(feature = "llvm-14-or-lower")]
1542 { LLVMGetElementAsConstant(constant, i as u32) }
1543 #[cfg(feature = "llvm-15-or-greater")]
1544 { LLVMGetAggregateElement(constant, i as u32) }
1545 },
1546 ctx)).collect()
1547 ),
1548 ty => panic!("Expected ConstantDataVector to have type Type::VectorType; got {:?}", ty),
1549 }
1550 },
1551 LLVMValueKind::LLVMConstantPointerNullValueKind => {
1552 Constant::Null(ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ))
1553 },
1554 LLVMValueKind::LLVMConstantAggregateZeroValueKind => {
1555 Constant::AggregateZero(ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ))
1556 },
1557 LLVMValueKind::LLVMUndefValueValueKind => {
1558 Constant::Undef(ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ))
1559 },
1560 #[cfg(feature = "llvm-12-or-greater")]
1561 LLVMValueKind::LLVMPoisonValueKind => {
1562 Constant::Poison(ctx.types.type_from_llvm_ref( unsafe { LLVMTypeOf(constant) } ))
1563 },
1564 LLVMValueKind::LLVMConstantTokenNoneValueKind => {
1565 Constant::TokenNone
1566 },
1567 LLVMValueKind::LLVMBlockAddressValueKind => {
1568 Constant::BlockAddress
1569 },
1570 LLVMValueKind::LLVMConstantExprValueKind => {
1571 use llvm_sys::LLVMOpcode;
1572 match unsafe { LLVMGetConstOpcode(constant) } {
1573 LLVMOpcode::LLVMAdd => Constant::Add(Add::from_llvm_ref(constant, ctx)),
1574 LLVMOpcode::LLVMSub => Constant::Sub(Sub::from_llvm_ref(constant, ctx)),
1575 LLVMOpcode::LLVMMul => Constant::Mul(Mul::from_llvm_ref(constant, ctx)),
1576 #[cfg(feature = "llvm-14-or-lower")]
1577 LLVMOpcode::LLVMUDiv => Constant::UDiv(UDiv::from_llvm_ref(constant, ctx)),
1578 #[cfg(feature = "llvm-14-or-lower")]
1579 LLVMOpcode::LLVMSDiv => Constant::SDiv(SDiv::from_llvm_ref(constant, ctx)),
1580 #[cfg(feature = "llvm-14-or-lower")]
1581 LLVMOpcode::LLVMURem => Constant::URem(URem::from_llvm_ref(constant, ctx)),
1582 #[cfg(feature = "llvm-14-or-lower")]
1583 LLVMOpcode::LLVMSRem => Constant::SRem(SRem::from_llvm_ref(constant, ctx)),
1584 #[cfg(feature = "llvm-17-or-lower")]
1585 LLVMOpcode::LLVMAnd => Constant::And(And::from_llvm_ref(constant, ctx)),
1586 #[cfg(feature = "llvm-17-or-lower")]
1587 LLVMOpcode::LLVMOr => Constant::Or(Or::from_llvm_ref(constant, ctx)),
1588 LLVMOpcode::LLVMXor => Constant::Xor(Xor::from_llvm_ref(constant, ctx)),
1589 #[cfg(feature = "llvm-18-or-lower")]
1590 LLVMOpcode::LLVMShl => Constant::Shl(Shl::from_llvm_ref(constant, ctx)),
1591 #[cfg(feature = "llvm-17-or-lower")]
1592 LLVMOpcode::LLVMLShr => Constant::LShr(LShr::from_llvm_ref(constant, ctx)),
1593 #[cfg(feature = "llvm-17-or-lower")]
1594 LLVMOpcode::LLVMAShr => Constant::AShr(AShr::from_llvm_ref(constant, ctx)),
1595 #[cfg(feature = "llvm-14-or-lower")]
1596 LLVMOpcode::LLVMFAdd => Constant::FAdd(FAdd::from_llvm_ref(constant, ctx)),
1597 #[cfg(feature = "llvm-14-or-lower")]
1598 LLVMOpcode::LLVMFSub => Constant::FSub(FSub::from_llvm_ref(constant, ctx)),
1599 #[cfg(feature = "llvm-14-or-lower")]
1600 LLVMOpcode::LLVMFMul => Constant::FMul(FMul::from_llvm_ref(constant, ctx)),
1601 #[cfg(feature = "llvm-14-or-lower")]
1602 LLVMOpcode::LLVMFDiv => Constant::FDiv(FDiv::from_llvm_ref(constant, ctx)),
1603 #[cfg(feature = "llvm-14-or-lower")]
1604 LLVMOpcode::LLVMFRem => Constant::FRem(FRem::from_llvm_ref(constant, ctx)),
1605 LLVMOpcode::LLVMExtractElement => Constant::ExtractElement(ExtractElement::from_llvm_ref(constant, ctx)),
1606 LLVMOpcode::LLVMInsertElement => Constant::InsertElement(InsertElement::from_llvm_ref(constant, ctx)),
1607 LLVMOpcode::LLVMShuffleVector => Constant::ShuffleVector(ShuffleVector::from_llvm_ref(constant, ctx)),
1608 #[cfg(feature = "llvm-14-or-lower")]
1609 LLVMOpcode::LLVMExtractValue => Constant::ExtractValue(ExtractValue::from_llvm_ref(constant, ctx)),
1610 #[cfg(feature = "llvm-14-or-lower")]
1611 LLVMOpcode::LLVMInsertValue => Constant::InsertValue(InsertValue::from_llvm_ref(constant, ctx)),
1612 LLVMOpcode::LLVMGetElementPtr => Constant::GetElementPtr(GetElementPtr::from_llvm_ref(constant, ctx)),
1613 LLVMOpcode::LLVMTrunc => Constant::Trunc(Trunc::from_llvm_ref(constant, ctx)),
1614 #[cfg(feature = "llvm-17-or-lower")]
1615 LLVMOpcode::LLVMZExt => Constant::ZExt(ZExt::from_llvm_ref(constant, ctx)),
1616 #[cfg(feature = "llvm-17-or-lower")]
1617 LLVMOpcode::LLVMSExt => Constant::SExt(SExt::from_llvm_ref(constant, ctx)),
1618 #[cfg(feature = "llvm-17-or-lower")]
1619 LLVMOpcode::LLVMFPTrunc => Constant::FPTrunc(FPTrunc::from_llvm_ref(constant, ctx)),
1620 #[cfg(feature = "llvm-17-or-lower")]
1621 LLVMOpcode::LLVMFPExt => Constant::FPExt(FPExt::from_llvm_ref(constant, ctx)),
1622 #[cfg(feature = "llvm-17-or-lower")]
1623 LLVMOpcode::LLVMFPToUI => Constant::FPToUI(FPToUI::from_llvm_ref(constant, ctx)),
1624 #[cfg(feature = "llvm-17-or-lower")]
1625 LLVMOpcode::LLVMFPToSI => Constant::FPToSI(FPToSI::from_llvm_ref(constant, ctx)),
1626 #[cfg(feature = "llvm-17-or-lower")]
1627 LLVMOpcode::LLVMUIToFP => Constant::UIToFP(UIToFP::from_llvm_ref(constant, ctx)),
1628 #[cfg(feature = "llvm-17-or-lower")]
1629 LLVMOpcode::LLVMSIToFP => Constant::SIToFP(SIToFP::from_llvm_ref(constant, ctx)),
1630 LLVMOpcode::LLVMPtrToInt => Constant::PtrToInt(PtrToInt::from_llvm_ref(constant, ctx)),
1631 LLVMOpcode::LLVMIntToPtr => Constant::IntToPtr(IntToPtr::from_llvm_ref(constant, ctx)),
1632 LLVMOpcode::LLVMBitCast => Constant::BitCast(BitCast::from_llvm_ref(constant, ctx)),
1633 LLVMOpcode::LLVMAddrSpaceCast => Constant::AddrSpaceCast(AddrSpaceCast::from_llvm_ref(constant, ctx)),
1634 #[cfg(feature = "llvm-18-or-lower")]
1635 LLVMOpcode::LLVMICmp => Constant::ICmp(ICmp::from_llvm_ref(constant, ctx)),
1636 #[cfg(feature = "llvm-18-or-lower")]
1637 LLVMOpcode::LLVMFCmp => Constant::FCmp(FCmp::from_llvm_ref(constant, ctx)),
1638 #[cfg(feature="llvm-16-or-lower")]
1639 LLVMOpcode::LLVMSelect => Constant::Select(Select::from_llvm_ref(constant, ctx)),
1640 opcode => panic!("ConstantExpr has unexpected opcode {:?}", opcode),
1641 }
1642 },
1643 #[cfg(feature = "llvm-19-or-greater")]
1644 LLVMValueKind::LLVMConstantPtrAuthValueKind => {
1645 Constant::PtrAuth {
1646 ptr : Constant::from_llvm_ref( unsafe { LLVMGetConstantPtrAuthPointer(constant) }, ctx),
1647 key : Constant::from_llvm_ref( unsafe { LLVMGetConstantPtrAuthKey(constant) }, ctx),
1648 disc : Constant::from_llvm_ref( unsafe { LLVMGetConstantPtrAuthDiscriminator(constant) }, ctx),
1649 addr_disc : Constant::from_llvm_ref( unsafe { LLVMGetConstantPtrAuthAddrDiscriminator(constant) }, ctx)
1650 }
1651 }
1652 _ if unsafe { !LLVMIsAGlobalValue(constant).is_null() } => {
1653 Constant::GlobalReference {
1654 name: ctx.global_names.get(&constant)
1655 .unwrap_or_else(|| { let names: Vec<_> = ctx.global_names.values().collect(); panic!("Global not found in ctx.global_names; have names {:?}", names) })
1656 .clone(),
1657 ty: ctx.types.type_from_llvm_ref( unsafe { LLVMGlobalGetValueType(constant) } ),
1658 }
1659 },
1660 k => panic!("Constant::from_llvm_ref: don't know how to handle this Constant with ValueKind {:?}", k),
1661 }
1662 }
1663}
1664
1665macro_rules! binop_from_llvm {
1666 ($expr:ident) => {
1667 impl $expr {
1668 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1669 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1670 Self {
1671 operand0: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1672 operand1: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1673 }
1674 }
1675 }
1676 };
1677}
1678
1679binop_from_llvm!(Add);
1680binop_from_llvm!(Sub);
1681binop_from_llvm!(Mul);
1682#[cfg(feature = "llvm-14-or-lower")]
1683binop_from_llvm!(UDiv);
1684#[cfg(feature = "llvm-14-or-lower")]
1685binop_from_llvm!(SDiv);
1686#[cfg(feature = "llvm-14-or-lower")]
1687binop_from_llvm!(URem);
1688#[cfg(feature = "llvm-14-or-lower")]
1689binop_from_llvm!(SRem);
1690#[cfg(feature = "llvm-17-or-lower")]
1691binop_from_llvm!(And);
1692#[cfg(feature = "llvm-17-or-lower")]
1693binop_from_llvm!(Or);
1694binop_from_llvm!(Xor);
1695#[cfg(feature = "llvm-18-or-lower")]
1696binop_from_llvm!(Shl);
1697#[cfg(feature = "llvm-17-or-lower")]
1698binop_from_llvm!(LShr);
1699#[cfg(feature = "llvm-17-or-lower")]
1700binop_from_llvm!(AShr);
1701#[cfg(feature = "llvm-14-or-lower")]
1702binop_from_llvm!(FAdd);
1703#[cfg(feature = "llvm-14-or-lower")]
1704binop_from_llvm!(FSub);
1705#[cfg(feature = "llvm-14-or-lower")]
1706binop_from_llvm!(FMul);
1707#[cfg(feature = "llvm-14-or-lower")]
1708binop_from_llvm!(FDiv);
1709#[cfg(feature = "llvm-14-or-lower")]
1710binop_from_llvm!(FRem);
1711
1712impl ExtractElement {
1713 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1714 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1715 Self {
1716 vector: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1717 index: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1718 }
1719 }
1720}
1721
1722impl InsertElement {
1723 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1724 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 3);
1725 Self {
1726 vector: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1727 element: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1728 index: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 2) }, ctx),
1729 }
1730 }
1731}
1732
1733impl ShuffleVector {
1734 #[cfg(feature = "llvm-10-or-lower")]
1735 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1736 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 3);
1737 Self {
1738 operand0: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1739 operand1: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1740 mask: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 2) }, ctx),
1741 }
1742 }
1743 #[cfg(feature = "llvm-11-or-greater")]
1744 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, _ctx: &mut ModuleContext) -> Self {
1745 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1746 panic!("Encountered a Constant::ShuffleVector, which is not supported for LLVM 11+")
1750 }
1751}
1752
1753#[cfg(feature = "llvm-14-or-lower")]
1754impl ExtractValue {
1755 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1756 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1757 Self {
1758 aggregate: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1759 indices: unsafe {
1760 let num_indices = LLVMGetNumIndices(expr);
1761 let ptr = LLVMGetIndices(expr);
1762 std::slice::from_raw_parts(ptr, num_indices as usize).to_vec()
1763 },
1764 }
1765 }
1766}
1767
1768#[cfg(feature = "llvm-14-or-lower")]
1769impl InsertValue {
1770 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1771 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 3);
1772 Self {
1773 aggregate: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1774 element: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1775 indices: unsafe {
1776 let num_indices = LLVMGetNumIndices(expr);
1777 let ptr = LLVMGetIndices(expr);
1778 std::slice::from_raw_parts(ptr, num_indices as usize).to_vec()
1779 },
1780 }
1781 }
1782}
1783
1784impl GetElementPtr {
1785 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1786 Self {
1787 address: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1788 indices: {
1789 let num_indices = unsafe { LLVMGetNumOperands(expr) as u32 } - 1; (1 ..= num_indices)
1791 .map(|i| Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, i) }, ctx))
1792 .collect()
1793 },
1794 in_bounds: unsafe { LLVMIsInBounds(expr) } != 0,
1795 }
1796 }
1797}
1798
1799macro_rules! typed_unop_from_llvm {
1802 ($expr:ident) => {
1803 impl $expr {
1804 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1805 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 1);
1806 Self {
1807 operand: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1808 to_type: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(expr) }),
1809 }
1810 }
1811 }
1812 };
1813}
1814
1815typed_unop_from_llvm!(Trunc);
1816#[cfg(feature = "llvm-17-or-lower")]
1817typed_unop_from_llvm!(ZExt);
1818#[cfg(feature = "llvm-17-or-lower")]
1819typed_unop_from_llvm!(SExt);
1820#[cfg(feature = "llvm-17-or-lower")]
1821typed_unop_from_llvm!(FPTrunc);
1822#[cfg(feature = "llvm-17-or-lower")]
1823typed_unop_from_llvm!(FPExt);
1824#[cfg(feature = "llvm-17-or-lower")]
1825typed_unop_from_llvm!(FPToUI);
1826#[cfg(feature = "llvm-17-or-lower")]
1827typed_unop_from_llvm!(FPToSI);
1828#[cfg(feature = "llvm-17-or-lower")]
1829typed_unop_from_llvm!(UIToFP);
1830#[cfg(feature = "llvm-17-or-lower")]
1831typed_unop_from_llvm!(SIToFP);
1832typed_unop_from_llvm!(PtrToInt);
1833typed_unop_from_llvm!(IntToPtr);
1834typed_unop_from_llvm!(BitCast);
1835typed_unop_from_llvm!(AddrSpaceCast);
1836
1837#[cfg(feature = "llvm-18-or-lower")]
1838impl ICmp {
1839 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1840 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1841 Self {
1842 predicate: IntPredicate::from_llvm(unsafe { LLVMGetICmpPredicate(expr) }),
1843 operand0: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1844 operand1: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1845 }
1846 }
1847}
1848
1849#[cfg(feature = "llvm-18-or-lower")]
1850impl FCmp {
1851 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1852 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 2);
1853 Self {
1854 predicate: FPPredicate::from_llvm(unsafe { LLVMGetFCmpPredicate(expr) }),
1855 operand0: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1856 operand1: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1857 }
1858 }
1859}
1860
1861#[cfg(feature="llvm-16-or-lower")]
1862impl Select {
1863 pub(crate) fn from_llvm_ref(expr: LLVMValueRef, ctx: &mut ModuleContext) -> Self {
1864 assert_eq!(unsafe { LLVMGetNumOperands(expr) }, 3);
1865 Self {
1866 condition: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 0) }, ctx),
1867 true_value: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 1) }, ctx),
1868 false_value: Constant::from_llvm_ref(unsafe { LLVMGetOperand(expr, 2) }, ctx),
1869 }
1870 }
1871}