1use crate::constant::ConstantRef;
2use crate::debugloc::{DebugLoc, HasDebugLoc};
3use crate::function::{CallingConvention, FunctionAttribute, ParameterAttribute};
4use crate::name::Name;
5use crate::operand::Operand;
6use crate::predicates::*;
7#[cfg(feature = "llvm-14-or-lower")]
8use crate::types::NamedStructDef;
9use crate::types::{Type, TypeRef, Typed, Types};
10use either::Either;
11use std::convert::TryFrom;
12use std::fmt::{self, Debug, Display};
13
14#[derive(PartialEq, Clone, Debug, Hash)]
16pub enum Instruction {
17 Add(Add),
19 Sub(Sub),
20 Mul(Mul),
21 UDiv(UDiv),
22 SDiv(SDiv),
23 URem(URem),
24 SRem(SRem),
25
26 And(And),
28 Or(Or),
29 Xor(Xor),
30 Shl(Shl),
31 LShr(LShr),
32 AShr(AShr),
33
34 FAdd(FAdd),
36 FSub(FSub),
37 FMul(FMul),
38 FDiv(FDiv),
39 FRem(FRem),
40 FNeg(FNeg),
41
42 ExtractElement(ExtractElement),
44 InsertElement(InsertElement),
45 ShuffleVector(ShuffleVector),
46
47 ExtractValue(ExtractValue),
49 InsertValue(InsertValue),
50
51 Alloca(Alloca),
53 Load(Load),
54 Store(Store),
55 Fence(Fence),
56 CmpXchg(CmpXchg),
57 AtomicRMW(AtomicRMW),
58 GetElementPtr(GetElementPtr),
59
60 Trunc(Trunc),
62 ZExt(ZExt),
63 SExt(SExt),
64 FPTrunc(FPTrunc),
65 FPExt(FPExt),
66 FPToUI(FPToUI),
67 FPToSI(FPToSI),
68 UIToFP(UIToFP),
69 SIToFP(SIToFP),
70 PtrToInt(PtrToInt),
71 IntToPtr(IntToPtr),
72 BitCast(BitCast),
73 AddrSpaceCast(AddrSpaceCast),
74
75 ICmp(ICmp),
77 FCmp(FCmp),
78 Phi(Phi),
79 Select(Select),
80 #[cfg(feature = "llvm-10-or-greater")]
81 Freeze(Freeze),
82 Call(Call),
83 VAArg(VAArg),
84 LandingPad(LandingPad),
85 CatchPad(CatchPad),
86 CleanupPad(CleanupPad),
87}
88
89impl Typed for Instruction {
91 fn get_type(&self, types: &Types) -> TypeRef {
92 match self {
93 Instruction::Add(i) => types.type_of(i),
94 Instruction::Sub(i) => types.type_of(i),
95 Instruction::Mul(i) => types.type_of(i),
96 Instruction::UDiv(i) => types.type_of(i),
97 Instruction::SDiv(i) => types.type_of(i),
98 Instruction::URem(i) => types.type_of(i),
99 Instruction::SRem(i) => types.type_of(i),
100 Instruction::And(i) => types.type_of(i),
101 Instruction::Or(i) => types.type_of(i),
102 Instruction::Xor(i) => types.type_of(i),
103 Instruction::Shl(i) => types.type_of(i),
104 Instruction::LShr(i) => types.type_of(i),
105 Instruction::AShr(i) => types.type_of(i),
106 Instruction::FAdd(i) => types.type_of(i),
107 Instruction::FSub(i) => types.type_of(i),
108 Instruction::FMul(i) => types.type_of(i),
109 Instruction::FDiv(i) => types.type_of(i),
110 Instruction::FRem(i) => types.type_of(i),
111 Instruction::FNeg(i) => types.type_of(i),
112 Instruction::ExtractElement(i) => types.type_of(i),
113 Instruction::InsertElement(i) => types.type_of(i),
114 Instruction::ShuffleVector(i) => types.type_of(i),
115 Instruction::ExtractValue(i) => types.type_of(i),
116 Instruction::InsertValue(i) => types.type_of(i),
117 Instruction::Alloca(i) => types.type_of(i),
118 Instruction::Load(i) => types.type_of(i),
119 Instruction::Store(i) => types.type_of(i),
120 Instruction::Fence(i) => types.type_of(i),
121 Instruction::CmpXchg(i) => types.type_of(i),
122 Instruction::AtomicRMW(i) => types.type_of(i),
123 Instruction::GetElementPtr(i) => types.type_of(i),
124 Instruction::Trunc(i) => types.type_of(i),
125 Instruction::ZExt(i) => types.type_of(i),
126 Instruction::SExt(i) => types.type_of(i),
127 Instruction::FPTrunc(i) => types.type_of(i),
128 Instruction::FPExt(i) => types.type_of(i),
129 Instruction::FPToUI(i) => types.type_of(i),
130 Instruction::FPToSI(i) => types.type_of(i),
131 Instruction::UIToFP(i) => types.type_of(i),
132 Instruction::SIToFP(i) => types.type_of(i),
133 Instruction::PtrToInt(i) => types.type_of(i),
134 Instruction::IntToPtr(i) => types.type_of(i),
135 Instruction::BitCast(i) => types.type_of(i),
136 Instruction::AddrSpaceCast(i) => types.type_of(i),
137 Instruction::ICmp(i) => types.type_of(i),
138 Instruction::FCmp(i) => types.type_of(i),
139 Instruction::Phi(i) => types.type_of(i),
140 Instruction::Select(i) => types.type_of(i),
141 #[cfg(feature = "llvm-10-or-greater")]
142 Instruction::Freeze(i) => types.type_of(i),
143 Instruction::Call(i) => types.type_of(i),
144 Instruction::VAArg(i) => types.type_of(i),
145 Instruction::LandingPad(i) => types.type_of(i),
146 Instruction::CatchPad(i) => types.type_of(i),
147 Instruction::CleanupPad(i) => types.type_of(i),
148 }
149 }
150}
151
152impl HasDebugLoc for Instruction {
153 fn get_debug_loc(&self) -> &Option<DebugLoc> {
154 match self {
155 Instruction::Add(i) => i.get_debug_loc(),
156 Instruction::Sub(i) => i.get_debug_loc(),
157 Instruction::Mul(i) => i.get_debug_loc(),
158 Instruction::UDiv(i) => i.get_debug_loc(),
159 Instruction::SDiv(i) => i.get_debug_loc(),
160 Instruction::URem(i) => i.get_debug_loc(),
161 Instruction::SRem(i) => i.get_debug_loc(),
162 Instruction::And(i) => i.get_debug_loc(),
163 Instruction::Or(i) => i.get_debug_loc(),
164 Instruction::Xor(i) => i.get_debug_loc(),
165 Instruction::Shl(i) => i.get_debug_loc(),
166 Instruction::LShr(i) => i.get_debug_loc(),
167 Instruction::AShr(i) => i.get_debug_loc(),
168 Instruction::FAdd(i) => i.get_debug_loc(),
169 Instruction::FSub(i) => i.get_debug_loc(),
170 Instruction::FMul(i) => i.get_debug_loc(),
171 Instruction::FDiv(i) => i.get_debug_loc(),
172 Instruction::FRem(i) => i.get_debug_loc(),
173 Instruction::FNeg(i) => i.get_debug_loc(),
174 Instruction::ExtractElement(i) => i.get_debug_loc(),
175 Instruction::InsertElement(i) => i.get_debug_loc(),
176 Instruction::ShuffleVector(i) => i.get_debug_loc(),
177 Instruction::ExtractValue(i) => i.get_debug_loc(),
178 Instruction::InsertValue(i) => i.get_debug_loc(),
179 Instruction::Alloca(i) => i.get_debug_loc(),
180 Instruction::Load(i) => i.get_debug_loc(),
181 Instruction::Store(i) => i.get_debug_loc(),
182 Instruction::Fence(i) => i.get_debug_loc(),
183 Instruction::CmpXchg(i) => i.get_debug_loc(),
184 Instruction::AtomicRMW(i) => i.get_debug_loc(),
185 Instruction::GetElementPtr(i) => i.get_debug_loc(),
186 Instruction::Trunc(i) => i.get_debug_loc(),
187 Instruction::ZExt(i) => i.get_debug_loc(),
188 Instruction::SExt(i) => i.get_debug_loc(),
189 Instruction::FPTrunc(i) => i.get_debug_loc(),
190 Instruction::FPExt(i) => i.get_debug_loc(),
191 Instruction::FPToUI(i) => i.get_debug_loc(),
192 Instruction::FPToSI(i) => i.get_debug_loc(),
193 Instruction::UIToFP(i) => i.get_debug_loc(),
194 Instruction::SIToFP(i) => i.get_debug_loc(),
195 Instruction::PtrToInt(i) => i.get_debug_loc(),
196 Instruction::IntToPtr(i) => i.get_debug_loc(),
197 Instruction::BitCast(i) => i.get_debug_loc(),
198 Instruction::AddrSpaceCast(i) => i.get_debug_loc(),
199 Instruction::ICmp(i) => i.get_debug_loc(),
200 Instruction::FCmp(i) => i.get_debug_loc(),
201 Instruction::Phi(i) => i.get_debug_loc(),
202 Instruction::Select(i) => i.get_debug_loc(),
203 #[cfg(feature = "llvm-10-or-greater")]
204 Instruction::Freeze(i) => i.get_debug_loc(),
205 Instruction::Call(i) => i.get_debug_loc(),
206 Instruction::VAArg(i) => i.get_debug_loc(),
207 Instruction::LandingPad(i) => i.get_debug_loc(),
208 Instruction::CatchPad(i) => i.get_debug_loc(),
209 Instruction::CleanupPad(i) => i.get_debug_loc(),
210 }
211 }
212}
213
214impl Instruction {
215 pub fn try_get_result(&self) -> Option<&Name> {
218 match self {
219 Instruction::Add(i) => Some(&i.dest),
220 Instruction::Sub(i) => Some(&i.dest),
221 Instruction::Mul(i) => Some(&i.dest),
222 Instruction::UDiv(i) => Some(&i.dest),
223 Instruction::SDiv(i) => Some(&i.dest),
224 Instruction::URem(i) => Some(&i.dest),
225 Instruction::SRem(i) => Some(&i.dest),
226 Instruction::And(i) => Some(&i.dest),
227 Instruction::Or(i) => Some(&i.dest),
228 Instruction::Xor(i) => Some(&i.dest),
229 Instruction::Shl(i) => Some(&i.dest),
230 Instruction::LShr(i) => Some(&i.dest),
231 Instruction::AShr(i) => Some(&i.dest),
232 Instruction::FAdd(i) => Some(&i.dest),
233 Instruction::FSub(i) => Some(&i.dest),
234 Instruction::FMul(i) => Some(&i.dest),
235 Instruction::FDiv(i) => Some(&i.dest),
236 Instruction::FRem(i) => Some(&i.dest),
237 Instruction::FNeg(i) => Some(&i.dest),
238 Instruction::ExtractElement(i) => Some(&i.dest),
239 Instruction::InsertElement(i) => Some(&i.dest),
240 Instruction::ShuffleVector(i) => Some(&i.dest),
241 Instruction::ExtractValue(i) => Some(&i.dest),
242 Instruction::InsertValue(i) => Some(&i.dest),
243 Instruction::Alloca(i) => Some(&i.dest),
244 Instruction::Load(i) => Some(&i.dest),
245 Instruction::Store(_) => None,
246 Instruction::Fence(_) => None,
247 Instruction::CmpXchg(i) => Some(&i.dest),
248 Instruction::AtomicRMW(i) => Some(&i.dest),
249 Instruction::GetElementPtr(i) => Some(&i.dest),
250 Instruction::Trunc(i) => Some(&i.dest),
251 Instruction::ZExt(i) => Some(&i.dest),
252 Instruction::SExt(i) => Some(&i.dest),
253 Instruction::FPTrunc(i) => Some(&i.dest),
254 Instruction::FPExt(i) => Some(&i.dest),
255 Instruction::FPToUI(i) => Some(&i.dest),
256 Instruction::FPToSI(i) => Some(&i.dest),
257 Instruction::UIToFP(i) => Some(&i.dest),
258 Instruction::SIToFP(i) => Some(&i.dest),
259 Instruction::PtrToInt(i) => Some(&i.dest),
260 Instruction::IntToPtr(i) => Some(&i.dest),
261 Instruction::BitCast(i) => Some(&i.dest),
262 Instruction::AddrSpaceCast(i) => Some(&i.dest),
263 Instruction::ICmp(i) => Some(&i.dest),
264 Instruction::FCmp(i) => Some(&i.dest),
265 Instruction::Phi(i) => Some(&i.dest),
266 Instruction::Select(i) => Some(&i.dest),
267 #[cfg(feature = "llvm-10-or-greater")]
268 Instruction::Freeze(i) => Some(&i.dest),
269 Instruction::Call(i) => i.dest.as_ref(),
270 Instruction::VAArg(i) => Some(&i.dest),
271 Instruction::LandingPad(i) => Some(&i.dest),
272 Instruction::CatchPad(i) => Some(&i.dest),
273 Instruction::CleanupPad(i) => Some(&i.dest),
274 }
275 }
276
277 pub fn is_atomic(&self) -> bool {
279 match self {
280 Instruction::Add(_) => false,
281 Instruction::Sub(_) => false,
282 Instruction::Mul(_) => false,
283 Instruction::UDiv(_) => false,
284 Instruction::SDiv(_) => false,
285 Instruction::URem(_) => false,
286 Instruction::SRem(_) => false,
287 Instruction::And(_) => false,
288 Instruction::Or(_) => false,
289 Instruction::Xor(_) => false,
290 Instruction::Shl(_) => false,
291 Instruction::LShr(_) => false,
292 Instruction::AShr(_) => false,
293 Instruction::FAdd(_) => false,
294 Instruction::FSub(_) => false,
295 Instruction::FMul(_) => false,
296 Instruction::FDiv(_) => false,
297 Instruction::FRem(_) => false,
298 Instruction::FNeg(_) => false,
299 Instruction::ExtractElement(_) => false,
300 Instruction::InsertElement(_) => false,
301 Instruction::ShuffleVector(_) => false,
302 Instruction::ExtractValue(_) => false,
303 Instruction::InsertValue(_) => false,
304 Instruction::Alloca(_) => false,
305 Instruction::Load(i) => i.atomicity.is_some(),
306 Instruction::Store(i) => i.atomicity.is_some(),
307 Instruction::Fence(_) => true,
308 Instruction::CmpXchg(_) => true,
309 Instruction::AtomicRMW(_) => true,
310 Instruction::GetElementPtr(_) => false,
311 Instruction::Trunc(_) => false,
312 Instruction::ZExt(_) => false,
313 Instruction::SExt(_) => false,
314 Instruction::FPTrunc(_) => false,
315 Instruction::FPExt(_) => false,
316 Instruction::FPToUI(_) => false,
317 Instruction::FPToSI(_) => false,
318 Instruction::UIToFP(_) => false,
319 Instruction::SIToFP(_) => false,
320 Instruction::PtrToInt(_) => false,
321 Instruction::IntToPtr(_) => false,
322 Instruction::BitCast(_) => false,
323 Instruction::AddrSpaceCast(_) => false,
324 Instruction::ICmp(_) => false,
325 Instruction::FCmp(_) => false,
326 Instruction::Phi(_) => false,
327 Instruction::Select(_) => false,
328 #[cfg(feature = "llvm-10-or-greater")]
329 Instruction::Freeze(_) => false,
330 Instruction::Call(_) => false,
331 Instruction::VAArg(_) => false,
332 Instruction::LandingPad(_) => false,
333 Instruction::CatchPad(_) => false,
334 Instruction::CleanupPad(_) => false,
335 }
336 }
337}
338
339pub trait HasResult: Debug + Typed {
408 fn get_result(&self) -> &Name;
409}
410
411pub trait UnaryOp: HasResult {
412 fn get_operand(&self) -> &Operand;
413}
414
415pub trait BinaryOp: HasResult {
416 fn get_operand0(&self) -> &Operand;
417 fn get_operand1(&self) -> &Operand;
418}
419
420pub mod groups;
421
422impl Instruction {
423 pub fn is_binary_op(&self) -> bool {
427 match self {
428 Instruction::Add(_) => true,
429 Instruction::Sub(_) => true,
430 Instruction::Mul(_) => true,
431 Instruction::UDiv(_) => true,
432 Instruction::SDiv(_) => true,
433 Instruction::URem(_) => true,
434 Instruction::SRem(_) => true,
435 Instruction::And(_) => true,
436 Instruction::Or(_) => true,
437 Instruction::Xor(_) => true,
438 Instruction::Shl(_) => true,
439 Instruction::LShr(_) => true,
440 Instruction::AShr(_) => true,
441 Instruction::FAdd(_) => true,
442 Instruction::FSub(_) => true,
443 Instruction::FMul(_) => true,
444 Instruction::FDiv(_) => true,
445 Instruction::FRem(_) => true,
446 _ => false,
447 }
448 }
449
450 pub fn is_unary_op(&self) -> bool {
454 match self {
455 Instruction::AddrSpaceCast(_) => true,
456 Instruction::BitCast(_) => true,
457 Instruction::FNeg(_) => true,
458 Instruction::FPExt(_) => true,
459 Instruction::FPToSI(_) => true,
460 Instruction::FPToUI(_) => true,
461 Instruction::FPTrunc(_) => true,
462 #[cfg(feature = "llvm-10-or-greater")]
463 Instruction::Freeze(_) => true,
464 Instruction::IntToPtr(_) => true,
465 Instruction::PtrToInt(_) => true,
466 Instruction::SExt(_) => true,
467 Instruction::SIToFP(_) => true,
468 Instruction::Trunc(_) => true,
469 Instruction::UIToFP(_) => true,
470 Instruction::ZExt(_) => true,
471 _ => false,
472 }
473 }
474}
475
476impl Display for Instruction {
477 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
478 match self {
479 Instruction::Add(i) => write!(f, "{}", i),
480 Instruction::Sub(i) => write!(f, "{}", i),
481 Instruction::Mul(i) => write!(f, "{}", i),
482 Instruction::UDiv(i) => write!(f, "{}", i),
483 Instruction::SDiv(i) => write!(f, "{}", i),
484 Instruction::URem(i) => write!(f, "{}", i),
485 Instruction::SRem(i) => write!(f, "{}", i),
486 Instruction::And(i) => write!(f, "{}", i),
487 Instruction::Or(i) => write!(f, "{}", i),
488 Instruction::Xor(i) => write!(f, "{}", i),
489 Instruction::Shl(i) => write!(f, "{}", i),
490 Instruction::LShr(i) => write!(f, "{}", i),
491 Instruction::AShr(i) => write!(f, "{}", i),
492 Instruction::FAdd(i) => write!(f, "{}", i),
493 Instruction::FSub(i) => write!(f, "{}", i),
494 Instruction::FMul(i) => write!(f, "{}", i),
495 Instruction::FDiv(i) => write!(f, "{}", i),
496 Instruction::FRem(i) => write!(f, "{}", i),
497 Instruction::FNeg(i) => write!(f, "{}", i),
498 Instruction::ExtractElement(i) => write!(f, "{}", i),
499 Instruction::InsertElement(i) => write!(f, "{}", i),
500 Instruction::ShuffleVector(i) => write!(f, "{}", i),
501 Instruction::ExtractValue(i) => write!(f, "{}", i),
502 Instruction::InsertValue(i) => write!(f, "{}", i),
503 Instruction::Alloca(i) => write!(f, "{}", i),
504 Instruction::Load(i) => write!(f, "{}", i),
505 Instruction::Store(i) => write!(f, "{}", i),
506 Instruction::Fence(i) => write!(f, "{}", i),
507 Instruction::CmpXchg(i) => write!(f, "{}", i),
508 Instruction::AtomicRMW(i) => write!(f, "{}", i),
509 Instruction::GetElementPtr(i) => write!(f, "{}", i),
510 Instruction::Trunc(i) => write!(f, "{}", i),
511 Instruction::ZExt(i) => write!(f, "{}", i),
512 Instruction::SExt(i) => write!(f, "{}", i),
513 Instruction::FPTrunc(i) => write!(f, "{}", i),
514 Instruction::FPExt(i) => write!(f, "{}", i),
515 Instruction::FPToUI(i) => write!(f, "{}", i),
516 Instruction::FPToSI(i) => write!(f, "{}", i),
517 Instruction::UIToFP(i) => write!(f, "{}", i),
518 Instruction::SIToFP(i) => write!(f, "{}", i),
519 Instruction::PtrToInt(i) => write!(f, "{}", i),
520 Instruction::IntToPtr(i) => write!(f, "{}", i),
521 Instruction::BitCast(i) => write!(f, "{}", i),
522 Instruction::AddrSpaceCast(i) => write!(f, "{}", i),
523 Instruction::ICmp(i) => write!(f, "{}", i),
524 Instruction::FCmp(i) => write!(f, "{}", i),
525 Instruction::Phi(i) => write!(f, "{}", i),
526 Instruction::Select(i) => write!(f, "{}", i),
527 #[cfg(feature = "llvm-10-or-greater")]
528 Instruction::Freeze(i) => write!(f, "{}", i),
529 Instruction::Call(i) => write!(f, "{}", i),
530 Instruction::VAArg(i) => write!(f, "{}", i),
531 Instruction::LandingPad(i) => write!(f, "{}", i),
532 Instruction::CatchPad(i) => write!(f, "{}", i),
533 Instruction::CleanupPad(i) => write!(f, "{}", i),
534 }
535 }
536}
537
538macro_rules! impl_inst {
539 ($inst:ty, $id:ident) => {
540 impl From<$inst> for Instruction {
541 fn from(inst: $inst) -> Instruction {
542 Instruction::$id(inst)
543 }
544 }
545
546 impl TryFrom<Instruction> for $inst {
547 type Error = &'static str;
548 fn try_from(inst: Instruction) -> Result<Self, Self::Error> {
549 match inst {
550 Instruction::$id(inst) => Ok(inst),
551 _ => Err("Instruction is not of requested type"),
552 }
553 }
554 }
555
556 impl HasDebugLoc for $inst {
557 fn get_debug_loc(&self) -> &Option<DebugLoc> {
558 &self.debugloc
559 }
560 }
561
562 };
570}
571
572macro_rules! impl_hasresult {
573 ($inst:ty) => {
574 impl HasResult for $inst {
575 fn get_result(&self) -> &Name {
576 &self.dest
577 }
578 }
579 };
580}
581
582macro_rules! impl_unop {
586 ($inst:ty) => {
587 impl_hasresult!($inst);
588
589 impl UnaryOp for $inst {
590 fn get_operand(&self) -> &Operand {
591 &self.operand
592 }
593 }
594 };
595}
596
597macro_rules! impl_binop {
599 ($inst:ty, $id:ident) => {
600 impl_hasresult!($inst);
601
602 impl BinaryOp for $inst {
603 fn get_operand0(&self) -> &Operand {
604 &self.operand0
605 }
606 fn get_operand1(&self) -> &Operand {
607 &self.operand1
608 }
609 }
610
611 impl From<$inst> for groups::BinaryOp {
612 fn from(inst: $inst) -> Self {
613 groups::BinaryOp::$id(inst)
614 }
615 }
616
617 impl TryFrom<groups::BinaryOp> for $inst {
618 type Error = &'static str;
619 fn try_from(bo: groups::BinaryOp) -> Result<Self, Self::Error> {
620 match bo {
621 groups::BinaryOp::$id(i) => Ok(i),
622 _ => Err("BinaryOp is not of requested type"),
623 }
624 }
625 }
626 };
627}
628
629macro_rules! binop_display {
631 ($inst:ty, $dispname:expr) => {
632 impl Display for $inst {
633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
634 write!(
635 f,
636 "{} = {} {}, {}",
637 &self.dest, $dispname, &self.operand0, &self.operand1,
638 )?;
639 if self.debugloc.is_some() {
640 write!(f, " (with debugloc)")?;
641 }
642 Ok(())
643 }
644 }
645 };
646}
647
648macro_rules! binop_nuw_nsw_display {
650 ($inst:ty, $dispname:expr) => {
651 impl Display for $inst {
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
653 #[cfg(feature = "llvm-16-or-lower")]
654 let nuw = "";
655 #[cfg(feature = "llvm-17-or-greater")]
656 let nuw = if self.nuw { " nuw" } else { "" };
657 #[cfg(feature = "llvm-16-or-lower")]
658 let nsw = "";
659 #[cfg(feature = "llvm-17-or-greater")]
660 let nsw = if self.nsw { " nsw" } else { "" };
661 write!(
662 f,
663 "{} = {}{}{} {}, {}",
664 &self.dest,
665 $dispname,
666 nuw,
667 nsw,
668 &self.operand0,
669 &self.operand1,
670 )?;
671 if self.debugloc.is_some() {
672 write!(f, " (with debugloc)")?;
673 }
674 Ok(())
675 }
676 }
677 };
678}
679
680macro_rules! binop_exact_display {
682 ($inst:ty, $dispname:expr) => {
683 impl Display for $inst {
684 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
685 #[cfg(feature = "llvm-16-or-lower")]
686 let exact = "";
687 #[cfg(feature = "llvm-17-or-greater")]
688 let exact = if self.exact { " exact" } else { "" };
689 write!(
690 f,
691 "{} = {}{} {}, {}",
692 &self.dest,
693 $dispname,
694 exact,
695 &self.operand0,
696 &self.operand1,
697 )?;
698 if self.debugloc.is_some() {
699 write!(f, " (with debugloc)")?;
700 }
701 Ok(())
702 }
703 }
704 };
705}
706
707macro_rules! unop_same_type {
709 ($inst:ty, $dispname:expr) => {
710 impl_unop!($inst);
711
712 impl Typed for $inst {
713 fn get_type(&self, types: &Types) -> TypeRef {
714 types.type_of(self.get_operand())
715 }
716 }
717
718 impl Display for $inst {
719 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
720 write!(f, "{} = {} {}", &self.dest, $dispname, &self.operand)?;
721 if self.debugloc.is_some() {
722 write!(f, " (with debugloc)")?;
723 }
724 Ok(())
725 }
726 }
727 };
728}
729
730macro_rules! unop_explicitly_typed {
732 ($inst:ty, $dispname:expr) => {
733 impl_unop!($inst);
734 explicitly_typed!($inst);
735
736 impl Display for $inst {
737 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
738 write!(
739 f,
740 "{} = {} {} to {}",
741 &self.dest, $dispname, &self.operand, &self.to_type,
742 )?;
743 if self.debugloc.is_some() {
744 write!(f, " (with debugloc)")?;
745 }
746 Ok(())
747 }
748 }
749 };
750}
751
752macro_rules! binop_same_type {
754 ($inst:ty) => {
755 impl Typed for $inst {
756 fn get_type(&self, types: &Types) -> TypeRef {
757 let ty = types.type_of(self.get_operand0());
758 debug_assert_eq!(ty, types.type_of(self.get_operand1()));
759 ty
760 }
761 }
762 };
763}
764
765macro_rules! binop_left_type {
767 ($inst:ty) => {
768 impl Typed for $inst {
769 fn get_type(&self, types: &Types) -> TypeRef {
770 types.type_of(self.get_operand0())
771 }
772 }
773 };
774}
775
776macro_rules! explicitly_typed {
778 ($inst:ty) => {
779 impl Typed for $inst {
780 fn get_type(&self, _types: &Types) -> TypeRef {
781 self.to_type.clone()
782 }
783 }
784 };
785}
786
787macro_rules! void_typed {
788 ($inst:ty) => {
789 impl Typed for $inst {
790 fn get_type(&self, types: &Types) -> TypeRef {
791 types.void()
792 }
793 }
794 };
795}
796
797#[derive(PartialEq, Clone, Debug, Hash)]
800pub struct Add {
801 pub operand0: Operand,
802 pub operand1: Operand,
803 pub dest: Name,
804 #[cfg(feature = "llvm-17-or-greater")]
805 pub nuw: bool, #[cfg(feature = "llvm-17-or-greater")]
807 pub nsw: bool, pub debugloc: Option<DebugLoc>,
809 }
811
812impl_inst!(Add, Add);
813impl_binop!(Add, Add);
814binop_same_type!(Add);
815binop_nuw_nsw_display!(Add, "add");
816
817#[derive(PartialEq, Clone, Debug, Hash)]
820pub struct Sub {
821 pub operand0: Operand,
822 pub operand1: Operand,
823 pub dest: Name,
824 #[cfg(feature = "llvm-17-or-greater")]
825 pub nuw: bool, #[cfg(feature = "llvm-17-or-greater")]
827 pub nsw: bool, pub debugloc: Option<DebugLoc>,
829 }
831
832impl_inst!(Sub, Sub);
833impl_binop!(Sub, Sub);
834binop_same_type!(Sub);
835binop_nuw_nsw_display!(Sub, "sub");
836
837#[derive(PartialEq, Clone, Debug, Hash)]
840pub struct Mul {
841 pub operand0: Operand,
842 pub operand1: Operand,
843 pub dest: Name,
844 #[cfg(feature = "llvm-17-or-greater")]
845 pub nuw: bool, #[cfg(feature = "llvm-17-or-greater")]
847 pub nsw: bool, pub debugloc: Option<DebugLoc>,
849 }
851
852impl_inst!(Mul, Mul);
853impl_binop!(Mul, Mul);
854binop_same_type!(Mul);
855binop_nuw_nsw_display!(Mul, "mul");
856
857#[derive(PartialEq, Clone, Debug, Hash)]
860pub struct UDiv {
861 pub operand0: Operand,
862 pub operand1: Operand,
863 pub dest: Name,
864 #[cfg(feature = "llvm-17-or-greater")]
865 pub exact: bool, pub debugloc: Option<DebugLoc>,
867 }
869
870impl_inst!(UDiv, UDiv);
871impl_binop!(UDiv, UDiv);
872binop_same_type!(UDiv);
873binop_exact_display!(UDiv, "udiv");
874
875#[derive(PartialEq, Clone, Debug, Hash)]
878pub struct SDiv {
879 pub operand0: Operand,
880 pub operand1: Operand,
881 pub dest: Name,
882 #[cfg(feature = "llvm-17-or-greater")]
883 pub exact: bool, pub debugloc: Option<DebugLoc>,
885 }
887
888impl_inst!(SDiv, SDiv);
889impl_binop!(SDiv, SDiv);
890binop_same_type!(SDiv);
891binop_exact_display!(SDiv, "sdiv");
892
893#[derive(PartialEq, Clone, Debug, Hash)]
896pub struct URem {
897 pub operand0: Operand,
898 pub operand1: Operand,
899 pub dest: Name,
900 pub debugloc: Option<DebugLoc>,
901 }
903
904impl_inst!(URem, URem);
905impl_binop!(URem, URem);
906binop_same_type!(URem);
907binop_display!(URem, "urem");
908
909#[derive(PartialEq, Clone, Debug, Hash)]
912pub struct SRem {
913 pub operand0: Operand,
914 pub operand1: Operand,
915 pub dest: Name,
916 pub debugloc: Option<DebugLoc>,
917 }
919
920impl_inst!(SRem, SRem);
921impl_binop!(SRem, SRem);
922binop_same_type!(SRem);
923binop_display!(SRem, "srem");
924
925#[derive(PartialEq, Clone, Debug, Hash)]
928pub struct And {
929 pub operand0: Operand,
930 pub operand1: Operand,
931 pub dest: Name,
932 pub debugloc: Option<DebugLoc>,
933 }
935
936impl_inst!(And, And);
937impl_binop!(And, And);
938binop_same_type!(And);
939binop_display!(And, "and");
940
941#[derive(PartialEq, Clone, Debug, Hash)]
944pub struct Or {
945 pub operand0: Operand,
946 pub operand1: Operand,
947 pub dest: Name,
948 pub debugloc: Option<DebugLoc>,
949 }
951
952impl_inst!(Or, Or);
953impl_binop!(Or, Or);
954binop_same_type!(Or);
955binop_display!(Or, "or");
956
957#[derive(PartialEq, Clone, Debug, Hash)]
960pub struct Xor {
961 pub operand0: Operand,
962 pub operand1: Operand,
963 pub dest: Name,
964 pub debugloc: Option<DebugLoc>,
965 }
967
968impl_inst!(Xor, Xor);
969impl_binop!(Xor, Xor);
970binop_same_type!(Xor);
971binop_display!(Xor, "xor");
972
973#[derive(PartialEq, Clone, Debug, Hash)]
976pub struct Shl {
977 pub operand0: Operand,
978 pub operand1: Operand,
979 pub dest: Name,
980 #[cfg(feature = "llvm-17-or-greater")]
981 pub nuw: bool, #[cfg(feature = "llvm-17-or-greater")]
983 pub nsw: bool, pub debugloc: Option<DebugLoc>,
985 }
987
988impl_inst!(Shl, Shl);
989impl_binop!(Shl, Shl);
990binop_left_type!(Shl);
991binop_nuw_nsw_display!(Shl, "shl");
992
993#[derive(PartialEq, Clone, Debug, Hash)]
996pub struct LShr {
997 pub operand0: Operand,
998 pub operand1: Operand,
999 pub dest: Name,
1000 #[cfg(feature = "llvm-17-or-greater")]
1001 pub exact: bool, pub debugloc: Option<DebugLoc>,
1003 }
1005
1006impl_inst!(LShr, LShr);
1007impl_binop!(LShr, LShr);
1008binop_left_type!(LShr);
1009binop_exact_display!(LShr, "lshr");
1010
1011#[derive(PartialEq, Clone, Debug, Hash)]
1014pub struct AShr {
1015 pub operand0: Operand,
1016 pub operand1: Operand,
1017 pub dest: Name,
1018 #[cfg(feature = "llvm-17-or-greater")]
1019 pub exact: bool, pub debugloc: Option<DebugLoc>,
1021 }
1023
1024impl_inst!(AShr, AShr);
1025impl_binop!(AShr, AShr);
1026binop_left_type!(AShr);
1027binop_exact_display!(AShr, "ashr");
1028
1029#[derive(PartialEq, Clone, Debug, Hash)]
1032pub struct FAdd {
1033 pub operand0: Operand,
1034 pub operand1: Operand,
1035 pub dest: Name,
1036 pub debugloc: Option<DebugLoc>,
1038 }
1040
1041impl_inst!(FAdd, FAdd);
1042impl_binop!(FAdd, FAdd);
1043binop_same_type!(FAdd);
1044binop_display!(FAdd, "fadd");
1045
1046#[derive(PartialEq, Clone, Debug, Hash)]
1049pub struct FSub {
1050 pub operand0: Operand,
1051 pub operand1: Operand,
1052 pub dest: Name,
1053 pub debugloc: Option<DebugLoc>,
1055 }
1057
1058impl_inst!(FSub, FSub);
1059impl_binop!(FSub, FSub);
1060binop_same_type!(FSub);
1061binop_display!(FSub, "fsub");
1062
1063#[derive(PartialEq, Clone, Debug, Hash)]
1066pub struct FMul {
1067 pub operand0: Operand,
1068 pub operand1: Operand,
1069 pub dest: Name,
1070 pub debugloc: Option<DebugLoc>,
1072 }
1074
1075impl_inst!(FMul, FMul);
1076impl_binop!(FMul, FMul);
1077binop_same_type!(FMul);
1078binop_display!(FMul, "fmul");
1079
1080#[derive(PartialEq, Clone, Debug, Hash)]
1083pub struct FDiv {
1084 pub operand0: Operand,
1085 pub operand1: Operand,
1086 pub dest: Name,
1087 pub debugloc: Option<DebugLoc>,
1089 }
1091
1092impl_inst!(FDiv, FDiv);
1093impl_binop!(FDiv, FDiv);
1094binop_same_type!(FDiv);
1095binop_display!(FDiv, "fdiv");
1096
1097#[derive(PartialEq, Clone, Debug, Hash)]
1100pub struct FRem {
1101 pub operand0: Operand,
1102 pub operand1: Operand,
1103 pub dest: Name,
1104 pub debugloc: Option<DebugLoc>,
1106 }
1108
1109impl_inst!(FRem, FRem);
1110impl_binop!(FRem, FRem);
1111binop_same_type!(FRem);
1112binop_display!(FRem, "frem");
1113
1114#[derive(PartialEq, Clone, Debug, Hash)]
1117pub struct FNeg {
1118 pub operand: Operand,
1119 pub dest: Name,
1120 pub debugloc: Option<DebugLoc>,
1122 }
1124
1125impl_inst!(FNeg, FNeg);
1126unop_same_type!(FNeg, "fneg");
1127
1128#[derive(PartialEq, Clone, Debug, Hash)]
1131pub struct ExtractElement {
1132 pub vector: Operand,
1133 pub index: Operand,
1134 pub dest: Name,
1135 pub debugloc: Option<DebugLoc>,
1136 }
1138
1139impl_inst!(ExtractElement, ExtractElement);
1140impl_hasresult!(ExtractElement);
1141
1142impl Typed for ExtractElement {
1143 fn get_type(&self, types: &Types) -> TypeRef {
1144 match types.type_of(&self.vector).as_ref() {
1145 Type::VectorType { element_type, .. } => element_type.clone(),
1146 ty => panic!(
1147 "Expected an ExtractElement vector to be VectorType, got {:?}",
1148 ty
1149 ),
1150 }
1151 }
1152}
1153
1154impl Display for ExtractElement {
1155 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1156 write!(
1157 f,
1158 "{} = extractelement {}, {}",
1159 &self.dest, &self.vector, &self.index,
1160 )?;
1161 if self.debugloc.is_some() {
1162 write!(f, " (with debugloc)")?;
1163 }
1164 Ok(())
1165 }
1166}
1167
1168#[derive(PartialEq, Clone, Debug, Hash)]
1171pub struct InsertElement {
1172 pub vector: Operand,
1173 pub element: Operand,
1174 pub index: Operand,
1175 pub dest: Name,
1176 pub debugloc: Option<DebugLoc>,
1177 }
1179
1180impl_inst!(InsertElement, InsertElement);
1181impl_hasresult!(InsertElement);
1182
1183impl Typed for InsertElement {
1184 fn get_type(&self, types: &Types) -> TypeRef {
1185 types.type_of(&self.vector)
1186 }
1187}
1188
1189impl Display for InsertElement {
1190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1191 write!(
1192 f,
1193 "{} = insertelement {}, {}, {}",
1194 &self.dest, &self.vector, &self.element, &self.index,
1195 )?;
1196 if self.debugloc.is_some() {
1197 write!(f, " (with debugloc)")?;
1198 }
1199 Ok(())
1200 }
1201}
1202
1203#[derive(PartialEq, Clone, Debug, Hash)]
1206pub struct ShuffleVector {
1207 pub operand0: Operand,
1208 pub operand1: Operand,
1209 pub dest: Name,
1210 pub mask: ConstantRef,
1211 pub debugloc: Option<DebugLoc>,
1212 }
1214
1215impl_inst!(ShuffleVector, ShuffleVector);
1216impl_hasresult!(ShuffleVector);
1217
1218impl Typed for ShuffleVector {
1219 fn get_type(&self, types: &Types) -> TypeRef {
1220 let ty = types.type_of(&self.operand0);
1221 debug_assert_eq!(ty, types.type_of(&self.operand1));
1222 match ty.as_ref() {
1223 Type::VectorType { element_type, .. } => match types.type_of(&self.mask).as_ref() {
1224 #[cfg(feature = "llvm-11-or-greater")]
1225 Type::VectorType {
1226 num_elements,
1227 scalable,
1228 ..
1229 } => types.vector_of(element_type.clone(), *num_elements, *scalable),
1230 #[cfg(feature = "llvm-10-or-lower")]
1231 Type::VectorType { num_elements, .. } => {
1232 types.vector_of(element_type.clone(), *num_elements)
1233 },
1234 ty => panic!(
1235 "Expected a ShuffleVector mask to be VectorType, got {:?}",
1236 ty
1237 ),
1238 },
1239 _ => panic!(
1240 "Expected a ShuffleVector operand to be VectorType, got {:?}",
1241 ty
1242 ),
1243 }
1244 }
1245}
1246
1247impl Display for ShuffleVector {
1248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1249 write!(
1250 f,
1251 "{} = shufflevector {}, {}, {}",
1252 &self.dest, &self.operand0, &self.operand1, &self.mask,
1253 )?;
1254 if self.debugloc.is_some() {
1255 write!(f, " (with debugloc)")?;
1256 }
1257 Ok(())
1258 }
1259}
1260
1261#[derive(PartialEq, Clone, Debug, Hash)]
1264pub struct ExtractValue {
1265 pub aggregate: Operand,
1266 pub indices: Vec<u32>,
1267 pub dest: Name,
1268 pub debugloc: Option<DebugLoc>,
1269 }
1271
1272impl_inst!(ExtractValue, ExtractValue);
1273impl_hasresult!(ExtractValue);
1274
1275impl Typed for ExtractValue {
1276 fn get_type(&self, types: &Types) -> TypeRef {
1277 ev_type(types.type_of(&self.aggregate), self.indices.iter().copied())
1278 }
1279}
1280
1281fn ev_type(cur_type: TypeRef, mut indices: impl Iterator<Item = u32>) -> TypeRef {
1282 match indices.next() {
1283 None => cur_type,
1284 Some(index) => match cur_type.as_ref() {
1285 Type::ArrayType { element_type, .. } => ev_type(element_type.clone(), indices),
1286 Type::StructType { element_types, .. } => ev_type(
1287 element_types
1288 .get(index as usize)
1289 .expect("ExtractValue index out of range")
1290 .clone(),
1291 indices,
1292 ),
1293 _ => panic!(
1294 "ExtractValue from something that's not ArrayType or StructType; its type is {:?}",
1295 cur_type
1296 ),
1297 },
1298 }
1299}
1300
1301impl Display for ExtractValue {
1302 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1303 write!(
1304 f,
1305 "{} = extractvalue {}, {}",
1306 &self.dest,
1307 &self.aggregate,
1308 &self.indices.first().expect("ExtractValue with no indices")
1309 )?;
1310 for idx in &self.indices[1 ..] {
1311 write!(f, ", {idx}")?;
1312 }
1313 if self.debugloc.is_some() {
1314 write!(f, " (with debugloc)")?;
1315 }
1316 Ok(())
1317 }
1318}
1319
1320#[derive(PartialEq, Clone, Debug, Hash)]
1323pub struct InsertValue {
1324 pub aggregate: Operand,
1325 pub element: Operand,
1326 pub indices: Vec<u32>,
1327 pub dest: Name,
1328 pub debugloc: Option<DebugLoc>,
1329 }
1331
1332impl_inst!(InsertValue, InsertValue);
1333impl_hasresult!(InsertValue);
1334
1335impl Typed for InsertValue {
1336 fn get_type(&self, types: &Types) -> TypeRef {
1337 types.type_of(&self.aggregate)
1338 }
1339}
1340
1341impl Display for InsertValue {
1342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1343 write!(
1344 f,
1345 "{} = insertvalue {}, {}, {}",
1346 &self.dest,
1347 &self.aggregate,
1348 &self.element,
1349 &self.indices.first().expect("InsertValue with no indices"),
1350 )?;
1351 for idx in &self.indices[1 ..] {
1352 write!(f, ", {idx}")?;
1353 }
1354 if self.debugloc.is_some() {
1355 write!(f, " (with debugloc)")?;
1356 }
1357 Ok(())
1358 }
1359}
1360
1361#[derive(PartialEq, Clone, Debug, Hash)]
1364pub struct Alloca {
1365 pub allocated_type: TypeRef,
1366 pub num_elements: Operand, pub dest: Name,
1368 pub alignment: u32,
1369 pub debugloc: Option<DebugLoc>,
1370 }
1372
1373impl_inst!(Alloca, Alloca);
1374impl_hasresult!(Alloca);
1375
1376#[cfg(feature = "llvm-14-or-lower")]
1377impl Typed for Alloca {
1378 fn get_type(&self, types: &Types) -> TypeRef {
1379 types.pointer_to(self.allocated_type.clone())
1380 }
1381}
1382#[cfg(feature = "llvm-15-or-greater")]
1383impl Typed for Alloca {
1384 fn get_type(&self, types: &Types) -> TypeRef {
1385 types.pointer()
1386 }
1387}
1388
1389impl Display for Alloca {
1390 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1391 write!(f, "{} = alloca {}", &self.dest, &self.allocated_type)?;
1392 if let Some(Constant::Int { value: 1, .. }) = self.num_elements.as_constant() {
1393 } else {
1395 write!(f, ", {}", &self.num_elements)?;
1396 }
1397 write!(f, ", align {}", &self.alignment)?;
1398 if self.debugloc.is_some() {
1399 write!(f, " (with debugloc)")?;
1400 }
1401 Ok(())
1402 }
1403}
1404
1405#[derive(PartialEq, Clone, Debug, Hash)]
1408pub struct Load {
1409 pub address: Operand,
1410 pub dest: Name,
1411 #[cfg(feature = "llvm-15-or-greater")]
1412 pub loaded_ty: TypeRef,
1413 pub volatile: bool,
1414 pub atomicity: Option<Atomicity>,
1415 pub alignment: u32,
1416 pub debugloc: Option<DebugLoc>,
1417 }
1419
1420impl_inst!(Load, Load);
1421impl_hasresult!(Load);
1422
1423#[cfg(feature = "llvm-14-or-lower")]
1424impl Typed for Load {
1425 fn get_type(&self, types: &Types) -> TypeRef {
1426 match types.type_of(&self.address).as_ref() {
1427 Type::PointerType { pointee_type, .. } => pointee_type.clone(),
1428 ty => panic!("Expected a load address to be PointerType, got {:?}", ty),
1429 }
1430 }
1431}
1432#[cfg(feature = "llvm-15-or-greater")]
1433impl Typed for Load {
1434 fn get_type(&self, _types: &Types) -> TypeRef {
1435 self.loaded_ty.clone()
1436 }
1437}
1438
1439impl Display for Load {
1440 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1441 write!(f, "{} = load ", &self.dest)?;
1442 if self.atomicity.is_some() {
1443 write!(f, "atomic ")?;
1444 }
1445 if self.volatile {
1446 write!(f, "volatile ")?;
1447 }
1448 #[cfg(feature = "llvm-14-or-lower")]
1449 {
1450 }
1454 #[cfg(feature = "llvm-15-or-greater")]
1455 {
1456 write!(f, "{}, ", &self.loaded_ty)?;
1457 }
1458 write!(f, "{}", &self.address)?;
1459 if let Some(a) = &self.atomicity {
1460 write!(f, " {}", a)?;
1461 }
1462 write!(f, ", align {}", &self.alignment)?;
1463 if self.debugloc.is_some() {
1464 write!(f, " (with debugloc)")?;
1465 }
1466 Ok(())
1467 }
1468}
1469
1470#[derive(PartialEq, Clone, Debug, Hash)]
1473pub struct Store {
1474 pub address: Operand,
1475 pub value: Operand,
1476 pub volatile: bool,
1477 pub atomicity: Option<Atomicity>,
1478 pub alignment: u32,
1479 pub debugloc: Option<DebugLoc>,
1480 }
1482
1483impl_inst!(Store, Store);
1484void_typed!(Store);
1485
1486impl Display for Store {
1487 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1488 write!(f, "store ")?;
1489 if self.atomicity.is_some() {
1490 write!(f, "atomic ")?;
1491 }
1492 if self.volatile {
1493 write!(f, "volatile ")?;
1494 }
1495 write!(f, "{}, {}", &self.value, &self.address)?;
1496 if let Some(a) = &self.atomicity {
1497 write!(f, " {}", a)?;
1498 }
1499 write!(f, ", align {}", &self.alignment)?;
1500 if self.debugloc.is_some() {
1501 write!(f, " (with debugloc)")?;
1502 }
1503 Ok(())
1504 }
1505}
1506
1507#[derive(PartialEq, Clone, Debug, Hash)]
1510pub struct Fence {
1511 pub atomicity: Atomicity,
1512 pub debugloc: Option<DebugLoc>,
1513 }
1515
1516impl_inst!(Fence, Fence);
1517void_typed!(Fence);
1518
1519impl Display for Fence {
1520 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1521 write!(f, "fence {}", &self.atomicity)?;
1522 if self.debugloc.is_some() {
1523 write!(f, " (with debugloc)")?;
1524 }
1525 Ok(())
1526 }
1527}
1528
1529#[derive(PartialEq, Clone, Debug, Hash)]
1532pub struct CmpXchg {
1533 pub address: Operand,
1534 pub expected: Operand,
1535 pub replacement: Operand,
1536 pub dest: Name,
1537 pub volatile: bool,
1538 pub atomicity: Atomicity,
1540 pub failure_memory_ordering: MemoryOrdering,
1542 #[cfg(feature = "llvm-10-or-greater")]
1543 pub weak: bool,
1544 pub debugloc: Option<DebugLoc>,
1545 }
1547
1548impl_inst!(CmpXchg, CmpXchg);
1549impl_hasresult!(CmpXchg);
1550
1551impl Typed for CmpXchg {
1552 fn get_type(&self, types: &Types) -> TypeRef {
1553 let ty = types.type_of(&self.expected);
1554 debug_assert_eq!(ty, types.type_of(&self.replacement));
1555 types.struct_of(vec![ty, types.bool()], false)
1556 }
1557}
1558
1559impl Display for CmpXchg {
1560 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1561 write!(f, "{} = cmpxchg ", &self.dest)?;
1562 #[cfg(feature = "llvm-10-or-greater")]
1563 if self.weak {
1564 write!(f, "weak ")?;
1565 }
1566 if self.volatile {
1567 write!(f, "volatile ")?;
1568 }
1569 write!(
1570 f,
1571 "{}, {}, {} {} {}",
1572 &self.address,
1573 &self.expected,
1574 &self.replacement,
1575 &self.atomicity,
1576 &self.failure_memory_ordering,
1577 )?;
1578 if self.debugloc.is_some() {
1579 write!(f, " (with debugloc)")?;
1580 }
1581 Ok(())
1582 }
1583}
1584
1585#[derive(PartialEq, Clone, Debug, Hash)]
1588pub struct AtomicRMW {
1589 #[cfg(feature = "llvm-10-or-greater")]
1591 pub operation: RMWBinOp,
1592 pub address: Operand,
1593 pub value: Operand,
1594 pub dest: Name,
1595 pub volatile: bool,
1596 pub atomicity: Atomicity,
1597 pub debugloc: Option<DebugLoc>,
1598 }
1600
1601impl_inst!(AtomicRMW, AtomicRMW);
1602impl_hasresult!(AtomicRMW);
1603
1604#[cfg(feature = "llvm-14-or-lower")]
1605impl Typed for AtomicRMW {
1606 fn get_type(&self, types: &Types) -> TypeRef {
1607 match types.type_of(&self.address).as_ref() {
1608 Type::PointerType { pointee_type, .. } => pointee_type.clone(),
1609 ty => panic!(
1610 "Expected an AtomicRMW address to be PointerType, got {:?}",
1611 ty
1612 ),
1613 }
1614 }
1615}
1616#[cfg(feature = "llvm-15-or-greater")]
1617impl Typed for AtomicRMW {
1618 fn get_type(&self, types: &Types) -> TypeRef {
1619 self.value.get_type(types)
1620 }
1621}
1622
1623impl Display for AtomicRMW {
1624 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1625 write!(f, "{} = atomicrmw ", &self.dest)?;
1626 if self.volatile {
1627 write!(f, "volatile ")?;
1628 }
1629 #[cfg(feature = "llvm-10-or-greater")]
1630 write!(f, "{} ", &self.operation)?;
1631 write!(f, "{}, {} {}", &self.address, &self.value, &self.atomicity)?;
1632 if self.debugloc.is_some() {
1633 write!(f, " (with debugloc)")?;
1634 }
1635 Ok(())
1636 }
1637}
1638
1639#[derive(PartialEq, Clone, Debug, Hash)]
1643pub struct GetElementPtr {
1644 pub address: Operand,
1645 pub indices: Vec<Operand>,
1646 pub dest: Name,
1647 pub in_bounds: bool,
1648 pub debugloc: Option<DebugLoc>,
1649 #[cfg(feature = "llvm-14-or-greater")]
1650 pub source_element_type: TypeRef
1651 }
1653
1654impl_inst!(GetElementPtr, GetElementPtr);
1655impl_hasresult!(GetElementPtr);
1656
1657#[cfg(feature = "llvm-14-or-lower")]
1658impl Typed for GetElementPtr {
1659 fn get_type(&self, types: &Types) -> TypeRef {
1660 gep_type(types.type_of(&self.address), self.indices.iter(), types)
1661 }
1662}
1663#[cfg(feature = "llvm-15-or-greater")]
1664impl Typed for GetElementPtr {
1665 fn get_type(&self, types: &Types) -> TypeRef {
1666 types.pointer()
1667 }
1668}
1669
1670#[cfg(feature = "llvm-14-or-lower")]
1671fn gep_type<'o>(
1672 cur_type: TypeRef,
1673 mut indices: impl Iterator<Item = &'o Operand>,
1674 types: &Types,
1675) -> TypeRef {
1676 if let Type::NamedStructType { name } = cur_type.as_ref() {
1677 match types.named_struct_def(name) {
1678 None => panic!("Named struct without a definition (name {:?})", name),
1679 Some(NamedStructDef::Opaque) => {
1680 panic!("GEP on an opaque struct type (name {:?})", name)
1681 },
1682 Some(NamedStructDef::Defined(ty)) => {
1683 return gep_type(ty.clone(), indices, types);
1684 },
1685 }
1686 }
1687 match indices.next() {
1688 None => types.pointer_to(cur_type), Some(index) => match cur_type.as_ref() {
1690 Type::PointerType { pointee_type, .. } => gep_type(pointee_type.clone(), indices, types),
1691 Type::VectorType { element_type, .. } => gep_type(element_type.clone(), indices, types),
1692 Type::ArrayType { element_type, .. } => gep_type(element_type.clone(), indices, types),
1693 Type::StructType { element_types, .. } => {
1694 if let Operand::ConstantOperand(cref) = index {
1695 if let Constant::Int { value, .. } = cref.as_ref() {
1696 gep_type(element_types.get(*value as usize).cloned().expect("GEP index out of range"), indices, types)
1697 } else {
1698 panic!("Expected GEP index on a struct to be a Constant::Int; got {:?}", cref)
1699 }
1700 } else {
1701 panic!("Expected GEP index on a struct to be a Operand::ConstantOperand(Constant::Int); got {:?}", index)
1702 }
1703 },
1704 Type::NamedStructType { .. } => panic!("This case should have been handled above"),
1705 _ => panic!("Expected GEP base type to be a PointerType, VectorType, ArrayType, StructType, or NamedStructType; got {:?}", cur_type),
1706 }
1707 }
1708}
1709
1710impl Display for GetElementPtr {
1711 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1712 write!(f, "{} = getelementptr ", &self.dest)?;
1717 if self.in_bounds {
1718 write!(f, "inbounds ")?;
1719 }
1720 write!(f, "{}", &self.address)?;
1721 for idx in &self.indices {
1722 write!(f, ", {}", idx)?;
1723 }
1724 if self.debugloc.is_some() {
1725 write!(f, " (with debugloc)")?;
1726 }
1727 Ok(())
1728 }
1729}
1730
1731#[derive(PartialEq, Clone, Debug, Hash)]
1734pub struct Trunc {
1735 pub operand: Operand,
1736 pub to_type: TypeRef,
1737 pub dest: Name,
1738 pub debugloc: Option<DebugLoc>,
1739 }
1741
1742impl_inst!(Trunc, Trunc);
1743unop_explicitly_typed!(Trunc, "trunc");
1744
1745#[derive(PartialEq, Clone, Debug, Hash)]
1748pub struct ZExt {
1749 pub operand: Operand,
1750 pub to_type: TypeRef,
1751 pub dest: Name,
1752 pub debugloc: Option<DebugLoc>,
1753 }
1755
1756impl_inst!(ZExt, ZExt);
1757unop_explicitly_typed!(ZExt, "zext");
1758
1759#[derive(PartialEq, Clone, Debug, Hash)]
1762pub struct SExt {
1763 pub operand: Operand,
1764 pub to_type: TypeRef,
1765 pub dest: Name,
1766 pub debugloc: Option<DebugLoc>,
1767 }
1769
1770impl_inst!(SExt, SExt);
1771unop_explicitly_typed!(SExt, "sext");
1772
1773#[derive(PartialEq, Clone, Debug, Hash)]
1776pub struct FPTrunc {
1777 pub operand: Operand,
1778 pub to_type: TypeRef,
1779 pub dest: Name,
1780 pub debugloc: Option<DebugLoc>,
1781 }
1783
1784impl_inst!(FPTrunc, FPTrunc);
1785unop_explicitly_typed!(FPTrunc, "fptrunc");
1786
1787#[derive(PartialEq, Clone, Debug, Hash)]
1790pub struct FPExt {
1791 pub operand: Operand,
1792 pub to_type: TypeRef,
1793 pub dest: Name,
1794 pub debugloc: Option<DebugLoc>,
1795 }
1797
1798impl_inst!(FPExt, FPExt);
1799unop_explicitly_typed!(FPExt, "fpext");
1800
1801#[derive(PartialEq, Clone, Debug, Hash)]
1804pub struct FPToUI {
1805 pub operand: Operand,
1806 pub to_type: TypeRef,
1807 pub dest: Name,
1808 pub debugloc: Option<DebugLoc>,
1809 }
1811
1812impl_inst!(FPToUI, FPToUI);
1813unop_explicitly_typed!(FPToUI, "fptoui");
1814
1815#[derive(PartialEq, Clone, Debug, Hash)]
1818pub struct FPToSI {
1819 pub operand: Operand,
1820 pub to_type: TypeRef,
1821 pub dest: Name,
1822 pub debugloc: Option<DebugLoc>,
1823 }
1825
1826impl_inst!(FPToSI, FPToSI);
1827unop_explicitly_typed!(FPToSI, "fptosi");
1828
1829#[derive(PartialEq, Clone, Debug, Hash)]
1832pub struct UIToFP {
1833 pub operand: Operand,
1834 pub to_type: TypeRef,
1835 pub dest: Name,
1836 pub debugloc: Option<DebugLoc>,
1837 }
1839
1840impl_inst!(UIToFP, UIToFP);
1841unop_explicitly_typed!(UIToFP, "uitofp");
1842
1843#[derive(PartialEq, Clone, Debug, Hash)]
1846pub struct SIToFP {
1847 pub operand: Operand,
1848 pub to_type: TypeRef,
1849 pub dest: Name,
1850 pub debugloc: Option<DebugLoc>,
1851 }
1853
1854impl_inst!(SIToFP, SIToFP);
1855unop_explicitly_typed!(SIToFP, "sitofp");
1856
1857#[derive(PartialEq, Clone, Debug, Hash)]
1860pub struct PtrToInt {
1861 pub operand: Operand,
1862 pub to_type: TypeRef,
1863 pub dest: Name,
1864 pub debugloc: Option<DebugLoc>,
1865 }
1867
1868impl_inst!(PtrToInt, PtrToInt);
1869unop_explicitly_typed!(PtrToInt, "ptrtoint");
1870
1871#[derive(PartialEq, Clone, Debug, Hash)]
1874pub struct IntToPtr {
1875 pub operand: Operand,
1876 pub to_type: TypeRef,
1877 pub dest: Name,
1878 pub debugloc: Option<DebugLoc>,
1879 }
1881
1882impl_inst!(IntToPtr, IntToPtr);
1883unop_explicitly_typed!(IntToPtr, "inttoptr");
1884
1885#[derive(PartialEq, Clone, Debug, Hash)]
1888pub struct BitCast {
1889 pub operand: Operand,
1890 pub to_type: TypeRef,
1891 pub dest: Name,
1892 pub debugloc: Option<DebugLoc>,
1893 }
1895
1896impl_inst!(BitCast, BitCast);
1897unop_explicitly_typed!(BitCast, "bitcast");
1898
1899#[derive(PartialEq, Clone, Debug, Hash)]
1902pub struct AddrSpaceCast {
1903 pub operand: Operand,
1904 pub to_type: TypeRef,
1905 pub dest: Name,
1906 pub debugloc: Option<DebugLoc>,
1907 }
1909
1910impl_inst!(AddrSpaceCast, AddrSpaceCast);
1911unop_explicitly_typed!(AddrSpaceCast, "addrspacecast");
1912
1913#[derive(PartialEq, Clone, Debug, Hash)]
1916pub struct ICmp {
1917 pub predicate: IntPredicate,
1918 pub operand0: Operand,
1919 pub operand1: Operand,
1920 pub dest: Name,
1921 pub debugloc: Option<DebugLoc>,
1922 }
1924
1925impl_inst!(ICmp, ICmp);
1926impl_hasresult!(ICmp);
1927
1928impl Typed for ICmp {
1929 fn get_type(&self, types: &Types) -> TypeRef {
1930 let ty = types.type_of(&self.operand0);
1931 debug_assert_eq!(ty, types.type_of(&self.operand1));
1932 match ty.as_ref() {
1933 #[cfg(feature = "llvm-11-or-greater")]
1934 Type::VectorType {
1935 num_elements,
1936 scalable,
1937 ..
1938 } => types.vector_of(types.bool(), *num_elements, *scalable),
1939 #[cfg(feature = "llvm-10-or-lower")]
1940 Type::VectorType { num_elements, .. } => types.vector_of(types.bool(), *num_elements),
1941 _ => types.bool(),
1942 }
1943 }
1944}
1945
1946impl Display for ICmp {
1947 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1948 write!(
1949 f,
1950 "{} = icmp {} {}, {}",
1951 &self.dest, &self.predicate, &self.operand0, &self.operand1,
1952 )?;
1953 if self.debugloc.is_some() {
1954 write!(f, " (with debugloc)")?;
1955 }
1956 Ok(())
1957 }
1958}
1959
1960#[derive(PartialEq, Clone, Debug, Hash)]
1963pub struct FCmp {
1964 pub predicate: FPPredicate,
1965 pub operand0: Operand,
1966 pub operand1: Operand,
1967 pub dest: Name,
1968 pub debugloc: Option<DebugLoc>,
1969 }
1971
1972impl_inst!(FCmp, FCmp);
1973impl_hasresult!(FCmp);
1974
1975impl Typed for FCmp {
1976 fn get_type(&self, types: &Types) -> TypeRef {
1977 let ty = types.type_of(&self.operand0);
1978 debug_assert_eq!(ty, types.type_of(&self.operand1));
1979 match ty.as_ref() {
1980 #[cfg(feature = "llvm-11-or-greater")]
1981 Type::VectorType {
1982 num_elements,
1983 scalable,
1984 ..
1985 } => types.vector_of(types.bool(), *num_elements, *scalable),
1986 #[cfg(feature = "llvm-10-or-lower")]
1987 Type::VectorType { num_elements, .. } => types.vector_of(types.bool(), *num_elements),
1988 _ => types.bool(),
1989 }
1990 }
1991}
1992
1993impl Display for FCmp {
1994 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1995 write!(
1996 f,
1997 "{} = fcmp {} {}, {}",
1998 &self.dest, &self.predicate, &self.operand0, &self.operand1,
1999 )?;
2000 if self.debugloc.is_some() {
2001 write!(f, " (with debugloc)")?;
2002 }
2003 Ok(())
2004 }
2005}
2006
2007#[derive(PartialEq, Clone, Debug, Hash)]
2009pub struct Phi {
2010 pub incoming_values: Vec<(Operand, Name)>,
2011 pub dest: Name,
2012 pub to_type: TypeRef,
2013 pub debugloc: Option<DebugLoc>,
2014 }
2016
2017impl_inst!(Phi, Phi);
2018impl_hasresult!(Phi);
2019explicitly_typed!(Phi);
2020
2021impl Display for Phi {
2022 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2023 let (first_val, first_label) = &self
2024 .incoming_values
2025 .get(0)
2026 .expect("Phi with no incoming values");
2027 write!(
2028 f,
2029 "{} = phi {} [ {}, {} ]",
2030 &self.dest, &self.to_type, first_val, first_label,
2031 )?;
2032 for (val, label) in &self.incoming_values[1 ..] {
2033 write!(f, ", [ {}, {} ]", val, label)?;
2034 }
2035 if self.debugloc.is_some() {
2036 write!(f, " (with debugloc)")?;
2037 }
2038 Ok(())
2039 }
2040}
2041
2042#[derive(PartialEq, Clone, Debug, Hash)]
2045pub struct Select {
2046 pub condition: Operand,
2047 pub true_value: Operand,
2048 pub false_value: Operand,
2049 pub dest: Name,
2050 pub debugloc: Option<DebugLoc>,
2051 }
2053
2054impl_inst!(Select, Select);
2055impl_hasresult!(Select);
2056
2057impl Typed for Select {
2058 fn get_type(&self, types: &Types) -> TypeRef {
2059 let t = types.type_of(&self.true_value);
2060 debug_assert_eq!(t, types.type_of(&self.false_value));
2061 t
2062 }
2063}
2064
2065impl Display for Select {
2066 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2067 write!(
2068 f,
2069 "{} = select {}, {}, {}",
2070 &self.dest, &self.condition, &self.true_value, &self.false_value,
2071 )?;
2072 if self.debugloc.is_some() {
2073 write!(f, " (with debugloc)")?;
2074 }
2075 Ok(())
2076 }
2077}
2078
2079#[cfg(feature = "llvm-10-or-greater")]
2082#[derive(PartialEq, Clone, Debug, Hash)]
2083pub struct Freeze {
2084 pub operand: Operand,
2085 pub dest: Name,
2086 pub debugloc: Option<DebugLoc>,
2087 }
2089
2090#[cfg(feature = "llvm-10-or-greater")]
2091impl_inst!(Freeze, Freeze);
2092#[cfg(feature = "llvm-10-or-greater")]
2093unop_same_type!(Freeze, "freeze");
2094
2095#[derive(PartialEq, Clone, Debug, Hash)]
2098pub struct Call {
2099 pub function: Either<InlineAssembly, Operand>,
2100 #[cfg(feature = "llvm-15-or-greater")]
2101 pub function_ty: TypeRef,
2102 pub arguments: Vec<(Operand, Vec<ParameterAttribute>)>,
2103 pub return_attributes: Vec<ParameterAttribute>,
2104 pub dest: Option<Name>, pub function_attributes: Vec<FunctionAttribute>, pub is_tail_call: bool, pub calling_convention: CallingConvention,
2108 pub debugloc: Option<DebugLoc>,
2109 }
2111
2112impl_inst!(Call, Call);
2113
2114#[cfg(feature = "llvm-14-or-lower")]
2115impl Typed for Call {
2116 fn get_type(&self, types: &Types) -> TypeRef {
2117 match types.type_of(&self.function).as_ref() {
2118 Type::PointerType { pointee_type, .. } => match pointee_type.as_ref() {
2119 Type::FuncType { result_type, .. } => result_type.clone(),
2120 ty => panic!("Expected Call's function argument to be of type pointer-to-function, got pointer-to-{:?}", ty),
2121 },
2122 ty => panic!("Expected Call's function argument to be of type pointer-to-function, got {:?}", ty),
2123 }
2124 }
2125}
2126#[cfg(feature = "llvm-15-or-greater")]
2127impl Typed for Call {
2128 fn get_type(&self, _types: &Types) -> TypeRef {
2129 match self.function_ty.as_ref() {
2130 Type::FuncType { result_type, .. } => result_type.clone(),
2131 ty => panic!("Expected Call.function_ty to be a FuncType, got {:?}", ty),
2132 }
2133 }
2134}
2135
2136impl Display for Call {
2137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2138 if let Some(dest) = &self.dest {
2141 write!(f, "{} = ", dest)?;
2142 }
2143 if self.is_tail_call {
2144 write!(f, "tail ")?;
2145 }
2146 write!(
2147 f,
2148 "call {}(",
2149 match &self.function {
2150 Either::Left(_) => "<inline assembly>".into(),
2151 Either::Right(op) => format!("{}", op),
2152 }
2153 )?;
2154 for (i, (arg, _)) in self.arguments.iter().enumerate() {
2155 if i == self.arguments.len() - 1 {
2156 write!(f, "{}", arg)?;
2157 } else {
2158 write!(f, "{}, ", arg)?;
2159 }
2160 }
2161 write!(f, ")")?;
2162 if self.debugloc.is_some() {
2163 write!(f, " (with debugloc)")?;
2164 }
2165 Ok(())
2166 }
2167}
2168
2169#[derive(PartialEq, Clone, Debug, Hash)]
2172pub struct VAArg {
2173 pub arg_list: Operand,
2174 pub cur_type: TypeRef,
2175 pub dest: Name,
2176 pub debugloc: Option<DebugLoc>,
2177 }
2179
2180impl_inst!(VAArg, VAArg);
2181impl_hasresult!(VAArg);
2182
2183impl Typed for VAArg {
2184 fn get_type(&self, _types: &Types) -> TypeRef {
2185 self.cur_type.clone()
2186 }
2187}
2188
2189impl Display for VAArg {
2190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2191 write!(
2192 f,
2193 "{} = va_arg {}, {}",
2194 &self.dest, &self.arg_list, &self.cur_type,
2195 )?;
2196 if self.debugloc.is_some() {
2197 write!(f, " (with debugloc)")?;
2198 }
2199 Ok(())
2200 }
2201}
2202
2203#[derive(PartialEq, Clone, Debug, Hash)]
2206pub struct LandingPad {
2207 pub result_type: TypeRef,
2208 pub clauses: Vec<LandingPadClause>,
2209 pub dest: Name,
2210 pub cleanup: bool,
2211 pub debugloc: Option<DebugLoc>,
2212 }
2214
2215impl_inst!(LandingPad, LandingPad);
2216impl_hasresult!(LandingPad);
2217
2218impl Typed for LandingPad {
2219 fn get_type(&self, _types: &Types) -> TypeRef {
2220 self.result_type.clone()
2221 }
2222}
2223
2224impl Display for LandingPad {
2225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2226 write!(f, "{} = landingpad {}", &self.dest, &self.result_type)?;
2227 if self.cleanup {
2228 write!(f, " cleanup")?;
2229 }
2230 if self.debugloc.is_some() {
2231 write!(f, " (with debugloc)")?;
2232 }
2233 Ok(())
2234 }
2235}
2236
2237#[derive(PartialEq, Clone, Debug, Hash)]
2240pub struct CatchPad {
2241 pub catch_switch: Operand,
2242 pub args: Vec<Operand>,
2243 pub dest: Name,
2244 pub debugloc: Option<DebugLoc>,
2245 }
2247
2248impl_inst!(CatchPad, CatchPad);
2249impl_hasresult!(CatchPad);
2250
2251impl Typed for CatchPad {
2252 fn get_type(&self, types: &Types) -> TypeRef {
2253 types.token_type()
2254 }
2255}
2256
2257impl Display for CatchPad {
2258 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2259 write!(
2260 f,
2261 "{} = catchpad within {} [",
2262 &self.dest, &self.catch_switch,
2263 )?;
2264 for (i, arg) in self.args.iter().enumerate() {
2265 if i == self.args.len() - 1 {
2266 write!(f, "{}", arg)?;
2267 } else {
2268 write!(f, "{}, ", arg)?;
2269 }
2270 }
2271 write!(f, "]")?;
2272 if self.debugloc.is_some() {
2273 write!(f, " (with debugloc)")?;
2274 }
2275 Ok(())
2276 }
2277}
2278
2279#[derive(PartialEq, Clone, Debug, Hash)]
2282pub struct CleanupPad {
2283 pub parent_pad: Operand,
2284 pub args: Vec<Operand>,
2285 pub dest: Name,
2286 pub debugloc: Option<DebugLoc>,
2287 }
2289
2290impl_inst!(CleanupPad, CleanupPad);
2291impl_hasresult!(CleanupPad);
2292
2293impl Typed for CleanupPad {
2294 fn get_type(&self, types: &Types) -> TypeRef {
2295 types.token_type()
2296 }
2297}
2298
2299impl Display for CleanupPad {
2300 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2301 write!(
2302 f,
2303 "{} = cleanuppad within {} [",
2304 &self.dest, &self.parent_pad,
2305 )?;
2306 for (i, arg) in self.args.iter().enumerate() {
2307 if i == self.args.len() - 1 {
2308 write!(f, "{}", arg)?;
2309 } else {
2310 write!(f, "{}, ", arg)?;
2311 }
2312 }
2313 write!(f, "]")?;
2314 if self.debugloc.is_some() {
2315 write!(f, " (with debugloc)")?;
2316 }
2317 Ok(())
2318 }
2319}
2320
2321#[derive(PartialEq, Eq, Clone, Debug, Hash)]
2332#[allow(non_snake_case)]
2333pub struct FastMathFlags {
2334 pub allow_reassoc: bool,
2335 pub no_NaNs: bool,
2336 pub no_Infs: bool,
2337 pub no_signed_zeros: bool,
2338 pub allow_reciprocal: bool,
2339 pub allow_contract: bool,
2340 pub approx_func: bool,
2341}
2342
2343#[derive(PartialEq, Eq, Clone, Debug, Hash)]
2345pub struct Atomicity {
2346 pub synch_scope: SynchronizationScope,
2347 pub mem_ordering: MemoryOrdering,
2348}
2349
2350impl Display for Atomicity {
2351 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2352 match self.synch_scope {
2353 SynchronizationScope::SingleThread => write!(f, "syncscope(\"singlethread\") "),
2354 SynchronizationScope::System => Ok(()),
2355 }?;
2356 write!(f, "{}", &self.mem_ordering)?;
2357 Ok(())
2358 }
2359}
2360
2361#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
2363pub enum SynchronizationScope {
2364 SingleThread,
2365 System,
2366}
2367
2368#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
2370pub enum MemoryOrdering {
2371 Unordered,
2372 Monotonic,
2373 Acquire,
2374 Release,
2375 AcquireRelease,
2376 SequentiallyConsistent,
2377 NotAtomic, }
2379
2380impl Display for MemoryOrdering {
2381 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2382 match self {
2383 MemoryOrdering::Unordered => write!(f, "unordered"),
2384 MemoryOrdering::Monotonic => write!(f, "monotonic"),
2385 MemoryOrdering::Acquire => write!(f, "acquire"),
2386 MemoryOrdering::Release => write!(f, "release"),
2387 MemoryOrdering::AcquireRelease => write!(f, "acq_rel"),
2388 MemoryOrdering::SequentiallyConsistent => write!(f, "seq_cst"),
2389 MemoryOrdering::NotAtomic => write!(f, "not_atomic"),
2390 }
2391 }
2392}
2393
2394#[derive(PartialEq, Eq, Clone, Debug, Hash)]
2419pub struct InlineAssembly {
2420 pub ty: TypeRef,
2421}
2422
2423impl Typed for InlineAssembly {
2424 fn get_type(&self, _types: &Types) -> TypeRef {
2425 self.ty.clone()
2426 }
2427}
2428
2429#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
2431pub enum RMWBinOp {
2432 Xchg,
2433 Add,
2434 Sub,
2435 And,
2436 Nand,
2437 Or,
2438 Xor,
2439 Max,
2440 Min,
2441 UMax,
2442 UMin,
2443 #[cfg(feature = "llvm-10-or-greater")]
2444 FAdd,
2445 #[cfg(feature = "llvm-10-or-greater")]
2446 FSub,
2447 #[cfg(feature = "llvm-15-or-greater")]
2448 FMax,
2449 #[cfg(feature = "llvm-15-or-greater")]
2450 FMin,
2451 #[cfg(feature = "llvm-19-or-greater")]
2452 UIncWrap,
2453 #[cfg(feature = "llvm-19-or-greater")]
2454 UDecWrap,
2455}
2456
2457impl Display for RMWBinOp {
2458 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2459 match self {
2460 Self::Xchg => write!(f, "xchg"),
2461 Self::Add => write!(f, "add"),
2462 Self::Sub => write!(f, "sub"),
2463 Self::And => write!(f, "and"),
2464 Self::Nand => write!(f, "nand"),
2465 Self::Or => write!(f, "or"),
2466 Self::Xor => write!(f, "xor"),
2467 Self::Max => write!(f, "max"),
2468 Self::Min => write!(f, "min"),
2469 Self::UMax => write!(f, "umax"),
2470 Self::UMin => write!(f, "umin"),
2471 #[cfg(feature = "llvm-10-or-greater")]
2472 Self::FAdd => write!(f, "fadd"),
2473 #[cfg(feature = "llvm-10-or-greater")]
2474 Self::FSub => write!(f, "fsub"),
2475 #[cfg(feature = "llvm-15-or-greater")]
2476 Self::FMax => write!(f, "fmax"),
2477 #[cfg(feature = "llvm-15-or-greater")]
2478 Self::FMin => write!(f, "fmin"),
2479 #[cfg(feature = "llvm-19-or-greater")]
2480 Self::UIncWrap => write!(f, "uinc_wrap"),
2481 #[cfg(feature = "llvm-19-or-greater")]
2482 Self::UDecWrap => write!(f, "udec_wrap"),
2483 }
2484 }
2485}
2486
2487#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
2502pub struct LandingPadClause {}
2503
2504use crate::constant::Constant;
2509use crate::from_llvm::*;
2510use crate::function::FunctionContext;
2511use crate::llvm_sys::*;
2512use crate::module::ModuleContext;
2513use crate::types::TypesBuilder;
2514use llvm_sys::LLVMAtomicOrdering;
2515#[cfg(feature = "llvm-10-or-greater")]
2516use llvm_sys::LLVMAtomicRMWBinOp;
2517use llvm_sys::LLVMOpcode;
2518use llvm_sys::LLVMTypeKind::LLVMVoidTypeKind;
2519#[cfg(feature = "llvm-11-or-greater")]
2520use std::convert::TryInto;
2521
2522impl Instruction {
2523 pub(crate) fn from_llvm_ref(
2524 inst: LLVMValueRef,
2525 ctx: &mut ModuleContext,
2526 func_ctx: &mut FunctionContext,
2527 ) -> Self {
2528 debug!("Processing instruction {:?}", unsafe {
2529 print_to_string(inst)
2530 });
2531 match unsafe { LLVMGetInstructionOpcode(inst) } {
2532 LLVMOpcode::LLVMAdd => Instruction::Add(Add::from_llvm_ref(inst, ctx, func_ctx)),
2533 LLVMOpcode::LLVMSub => Instruction::Sub(Sub::from_llvm_ref(inst, ctx, func_ctx)),
2534 LLVMOpcode::LLVMMul => Instruction::Mul(Mul::from_llvm_ref(inst, ctx, func_ctx)),
2535 LLVMOpcode::LLVMUDiv => Instruction::UDiv(UDiv::from_llvm_ref(inst, ctx, func_ctx)),
2536 LLVMOpcode::LLVMSDiv => Instruction::SDiv(SDiv::from_llvm_ref(inst, ctx, func_ctx)),
2537 LLVMOpcode::LLVMURem => Instruction::URem(URem::from_llvm_ref(inst, ctx, func_ctx)),
2538 LLVMOpcode::LLVMSRem => Instruction::SRem(SRem::from_llvm_ref(inst, ctx, func_ctx)),
2539 LLVMOpcode::LLVMAnd => Instruction::And(And::from_llvm_ref(inst, ctx, func_ctx)),
2540 LLVMOpcode::LLVMOr => Instruction::Or(Or::from_llvm_ref(inst, ctx, func_ctx)),
2541 LLVMOpcode::LLVMXor => Instruction::Xor(Xor::from_llvm_ref(inst, ctx, func_ctx)),
2542 LLVMOpcode::LLVMShl => Instruction::Shl(Shl::from_llvm_ref(inst, ctx, func_ctx)),
2543 LLVMOpcode::LLVMLShr => Instruction::LShr(LShr::from_llvm_ref(inst, ctx, func_ctx)),
2544 LLVMOpcode::LLVMAShr => Instruction::AShr(AShr::from_llvm_ref(inst, ctx, func_ctx)),
2545 LLVMOpcode::LLVMFAdd => Instruction::FAdd(FAdd::from_llvm_ref(inst, ctx, func_ctx)),
2546 LLVMOpcode::LLVMFSub => Instruction::FSub(FSub::from_llvm_ref(inst, ctx, func_ctx)),
2547 LLVMOpcode::LLVMFMul => Instruction::FMul(FMul::from_llvm_ref(inst, ctx, func_ctx)),
2548 LLVMOpcode::LLVMFDiv => Instruction::FDiv(FDiv::from_llvm_ref(inst, ctx, func_ctx)),
2549 LLVMOpcode::LLVMFRem => Instruction::FRem(FRem::from_llvm_ref(inst, ctx, func_ctx)),
2550 LLVMOpcode::LLVMFNeg => Instruction::FNeg(FNeg::from_llvm_ref(inst, ctx, func_ctx)),
2551 LLVMOpcode::LLVMExtractElement => {
2552 Instruction::ExtractElement(ExtractElement::from_llvm_ref(inst, ctx, func_ctx))
2553 },
2554 LLVMOpcode::LLVMInsertElement => {
2555 Instruction::InsertElement(InsertElement::from_llvm_ref(inst, ctx, func_ctx))
2556 },
2557 LLVMOpcode::LLVMShuffleVector => {
2558 Instruction::ShuffleVector(ShuffleVector::from_llvm_ref(inst, ctx, func_ctx))
2559 },
2560 LLVMOpcode::LLVMExtractValue => {
2561 Instruction::ExtractValue(ExtractValue::from_llvm_ref(inst, ctx, func_ctx))
2562 },
2563 LLVMOpcode::LLVMInsertValue => {
2564 Instruction::InsertValue(InsertValue::from_llvm_ref(inst, ctx, func_ctx))
2565 },
2566 LLVMOpcode::LLVMAlloca => {
2567 Instruction::Alloca(Alloca::from_llvm_ref(inst, ctx, func_ctx))
2568 },
2569 LLVMOpcode::LLVMLoad => Instruction::Load(Load::from_llvm_ref(inst, ctx, func_ctx)),
2570 LLVMOpcode::LLVMStore => Instruction::Store(Store::from_llvm_ref(inst, ctx, func_ctx)),
2571 LLVMOpcode::LLVMFence => Instruction::Fence(Fence::from_llvm_ref(inst)),
2572 LLVMOpcode::LLVMAtomicCmpXchg => {
2573 Instruction::CmpXchg(CmpXchg::from_llvm_ref(inst, ctx, func_ctx))
2574 },
2575 LLVMOpcode::LLVMAtomicRMW => {
2576 Instruction::AtomicRMW(AtomicRMW::from_llvm_ref(inst, ctx, func_ctx))
2577 },
2578 LLVMOpcode::LLVMGetElementPtr => {
2579 Instruction::GetElementPtr(GetElementPtr::from_llvm_ref(inst, ctx, func_ctx))
2580 },
2581 LLVMOpcode::LLVMTrunc => Instruction::Trunc(Trunc::from_llvm_ref(inst, ctx, func_ctx)),
2582 LLVMOpcode::LLVMZExt => Instruction::ZExt(ZExt::from_llvm_ref(inst, ctx, func_ctx)),
2583 LLVMOpcode::LLVMSExt => Instruction::SExt(SExt::from_llvm_ref(inst, ctx, func_ctx)),
2584 LLVMOpcode::LLVMFPTrunc => {
2585 Instruction::FPTrunc(FPTrunc::from_llvm_ref(inst, ctx, func_ctx))
2586 },
2587 LLVMOpcode::LLVMFPExt => Instruction::FPExt(FPExt::from_llvm_ref(inst, ctx, func_ctx)),
2588 LLVMOpcode::LLVMFPToUI => {
2589 Instruction::FPToUI(FPToUI::from_llvm_ref(inst, ctx, func_ctx))
2590 },
2591 LLVMOpcode::LLVMFPToSI => {
2592 Instruction::FPToSI(FPToSI::from_llvm_ref(inst, ctx, func_ctx))
2593 },
2594 LLVMOpcode::LLVMUIToFP => {
2595 Instruction::UIToFP(UIToFP::from_llvm_ref(inst, ctx, func_ctx))
2596 },
2597 LLVMOpcode::LLVMSIToFP => {
2598 Instruction::SIToFP(SIToFP::from_llvm_ref(inst, ctx, func_ctx))
2599 },
2600 LLVMOpcode::LLVMPtrToInt => {
2601 Instruction::PtrToInt(PtrToInt::from_llvm_ref(inst, ctx, func_ctx))
2602 },
2603 LLVMOpcode::LLVMIntToPtr => {
2604 Instruction::IntToPtr(IntToPtr::from_llvm_ref(inst, ctx, func_ctx))
2605 },
2606 LLVMOpcode::LLVMBitCast => {
2607 Instruction::BitCast(BitCast::from_llvm_ref(inst, ctx, func_ctx))
2608 },
2609 LLVMOpcode::LLVMAddrSpaceCast => {
2610 Instruction::AddrSpaceCast(AddrSpaceCast::from_llvm_ref(inst, ctx, func_ctx))
2611 },
2612 LLVMOpcode::LLVMICmp => Instruction::ICmp(ICmp::from_llvm_ref(inst, ctx, func_ctx)),
2613 LLVMOpcode::LLVMFCmp => Instruction::FCmp(FCmp::from_llvm_ref(inst, ctx, func_ctx)),
2614 LLVMOpcode::LLVMPHI => Instruction::Phi(Phi::from_llvm_ref(inst, ctx, func_ctx)),
2615 LLVMOpcode::LLVMSelect => {
2616 Instruction::Select(Select::from_llvm_ref(inst, ctx, func_ctx))
2617 },
2618 #[cfg(feature = "llvm-10-or-greater")]
2619 LLVMOpcode::LLVMFreeze => {
2620 Instruction::Freeze(Freeze::from_llvm_ref(inst, ctx, func_ctx))
2621 },
2622 LLVMOpcode::LLVMCall => Instruction::Call(Call::from_llvm_ref(inst, ctx, func_ctx)),
2623 LLVMOpcode::LLVMVAArg => Instruction::VAArg(VAArg::from_llvm_ref(inst, ctx, func_ctx)),
2624 LLVMOpcode::LLVMLandingPad => {
2625 Instruction::LandingPad(LandingPad::from_llvm_ref(inst, ctx, func_ctx))
2626 },
2627 LLVMOpcode::LLVMCatchPad => {
2628 Instruction::CatchPad(CatchPad::from_llvm_ref(inst, ctx, func_ctx))
2629 },
2630 LLVMOpcode::LLVMCleanupPad => {
2631 Instruction::CleanupPad(CleanupPad::from_llvm_ref(inst, ctx, func_ctx))
2632 },
2633 opcode => panic!(
2634 "Instruction::from_llvm_ref called with a terminator instruction (opcode {:?})",
2635 opcode
2636 ),
2637 }
2638 }
2639}
2640
2641macro_rules! unop_from_llvm {
2642 ($inst:ident) => {
2643 impl $inst {
2644 pub(crate) fn from_llvm_ref(
2645 inst: LLVMValueRef,
2646 ctx: &mut ModuleContext,
2647 func_ctx: &mut FunctionContext,
2648 ) -> Self {
2649 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
2650 Self {
2651 operand: Operand::from_llvm_ref(
2652 unsafe { LLVMGetOperand(inst, 0) },
2653 ctx,
2654 func_ctx,
2655 ),
2656 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2657 debugloc: DebugLoc::from_llvm_with_col(inst),
2658 }
2660 }
2661 }
2662 };
2663}
2664
2665macro_rules! binop_from_llvm {
2666 ($inst:ident) => {
2667 impl $inst {
2668 pub(crate) fn from_llvm_ref(
2669 inst: LLVMValueRef,
2670 ctx: &mut ModuleContext,
2671 func_ctx: &mut FunctionContext,
2672 ) -> Self {
2673 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2674 Self {
2675 operand0: Operand::from_llvm_ref(
2676 unsafe { LLVMGetOperand(inst, 0) },
2677 ctx,
2678 func_ctx,
2679 ),
2680 operand1: Operand::from_llvm_ref(
2681 unsafe { LLVMGetOperand(inst, 1) },
2682 ctx,
2683 func_ctx,
2684 ),
2685 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2686 debugloc: DebugLoc::from_llvm_with_col(inst),
2687 }
2689 }
2690 }
2691 };
2692}
2693
2694macro_rules! binop_from_llvm_with_nuw_nsw {
2695 ($inst:ident) => {
2696 impl $inst {
2697 pub(crate) fn from_llvm_ref(
2698 inst: LLVMValueRef,
2699 ctx: &mut ModuleContext,
2700 func_ctx: &mut FunctionContext,
2701 ) -> Self {
2702 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2703 Self {
2704 operand0: Operand::from_llvm_ref(
2705 unsafe { LLVMGetOperand(inst, 0) },
2706 ctx,
2707 func_ctx,
2708 ),
2709 operand1: Operand::from_llvm_ref(
2710 unsafe { LLVMGetOperand(inst, 1) },
2711 ctx,
2712 func_ctx,
2713 ),
2714 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2715 #[cfg(feature = "llvm-17-or-greater")]
2716 nuw: unsafe { LLVMGetNUW(inst) } != 0,
2717 #[cfg(feature = "llvm-17-or-greater")]
2718 nsw: unsafe { LLVMGetNSW(inst) } != 0,
2719 debugloc: DebugLoc::from_llvm_with_col(inst),
2720 }
2722 }
2723 }
2724 };
2725}
2726
2727macro_rules! binop_from_llvm_with_exact {
2728 ($inst:ident) => {
2729 impl $inst {
2730 pub(crate) fn from_llvm_ref(
2731 inst: LLVMValueRef,
2732 ctx: &mut ModuleContext,
2733 func_ctx: &mut FunctionContext,
2734 ) -> Self {
2735 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2736 Self {
2737 operand0: Operand::from_llvm_ref(
2738 unsafe { LLVMGetOperand(inst, 0) },
2739 ctx,
2740 func_ctx,
2741 ),
2742 operand1: Operand::from_llvm_ref(
2743 unsafe { LLVMGetOperand(inst, 1) },
2744 ctx,
2745 func_ctx,
2746 ),
2747 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2748 #[cfg(feature = "llvm-17-or-greater")]
2749 exact: unsafe { LLVMGetExact(inst) } != 0,
2750 debugloc: DebugLoc::from_llvm_with_col(inst),
2751 }
2753 }
2754 }
2755 };
2756}
2757
2758binop_from_llvm_with_nuw_nsw!(Add);
2759binop_from_llvm_with_nuw_nsw!(Sub);
2760binop_from_llvm_with_nuw_nsw!(Mul);
2761binop_from_llvm_with_exact!(UDiv);
2762binop_from_llvm_with_exact!(SDiv);
2763binop_from_llvm!(URem);
2764binop_from_llvm!(SRem);
2765binop_from_llvm!(And);
2766binop_from_llvm!(Or);
2767binop_from_llvm!(Xor);
2768binop_from_llvm_with_nuw_nsw!(Shl);
2769binop_from_llvm_with_exact!(LShr);
2770binop_from_llvm_with_exact!(AShr);
2771binop_from_llvm!(FAdd);
2772binop_from_llvm!(FSub);
2773binop_from_llvm!(FMul);
2774binop_from_llvm!(FDiv);
2775binop_from_llvm!(FRem);
2776unop_from_llvm!(FNeg);
2777#[cfg(feature = "llvm-10-or-greater")]
2778unop_from_llvm!(Freeze);
2779
2780impl ExtractElement {
2781 pub(crate) fn from_llvm_ref(
2782 inst: LLVMValueRef,
2783 ctx: &mut ModuleContext,
2784 func_ctx: &mut FunctionContext,
2785 ) -> Self {
2786 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2787 Self {
2788 vector: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2789 index: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
2790 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2791 debugloc: DebugLoc::from_llvm_with_col(inst),
2792 }
2794 }
2795}
2796
2797impl InsertElement {
2798 pub(crate) fn from_llvm_ref(
2799 inst: LLVMValueRef,
2800 ctx: &mut ModuleContext,
2801 func_ctx: &mut FunctionContext,
2802 ) -> Self {
2803 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 3);
2804 Self {
2805 vector: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2806 element: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
2807 index: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 2) }, ctx, func_ctx),
2808 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2809 debugloc: DebugLoc::from_llvm_with_col(inst),
2810 }
2812 }
2813}
2814
2815impl ShuffleVector {
2816 pub(crate) fn from_llvm_ref(
2817 inst: LLVMValueRef,
2818 ctx: &mut ModuleContext,
2819 func_ctx: &mut FunctionContext,
2820 ) -> Self {
2821 #[cfg(feature = "llvm-10-or-lower")]
2822 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 3);
2823 #[cfg(feature = "llvm-11-or-greater")]
2824 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2825 Self {
2826 operand0: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2827 operand1: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
2828 #[cfg(feature = "llvm-10-or-lower")]
2829 mask: Constant::from_llvm_ref(unsafe { LLVMGetOperand(inst, 2) }, ctx),
2830 #[cfg(feature = "llvm-11-or-greater")]
2831 mask: {
2832 let ret_ty = ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) });
2833 match ret_ty.as_ref() {
2834 Type::VectorType { num_elements, scalable, .. } => {
2835 assert_eq!(*num_elements as u32, unsafe { LLVMGetNumMaskElements(inst) });
2836 let undef_elem = unsafe { LLVMGetUndefMaskElem() };
2837 ConstantRef::new(Constant::Vector(
2838 (0 .. *num_elements)
2839 .map(|i| unsafe { LLVMGetMaskValue(inst, i.try_into().unwrap()) })
2840 .map(|val| if val == undef_elem {
2841 Constant::Undef(ctx.types.i32())
2842 } else {
2843 if *scalable {
2844 assert!(val == 0, "LLVM 11+ only allows zero or undef for mask elements in a ShuffleVector on scalable vectors");
2845 } else {
2846 assert!(val >= 0);
2847 }
2848 let val: u32 = val.try_into().unwrap();
2849 Constant::Int { value: val.into(), bits: 32 }
2850 })
2851 .map(ConstantRef::new)
2852 .collect()
2853 ))
2854 },
2855 ty => panic!("ShuffleVector: expected instruction result type to be a vector type; got {:?}", ty),
2856 }
2857 },
2858 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2859 debugloc: DebugLoc::from_llvm_with_col(inst),
2860 }
2862 }
2863}
2864
2865impl ExtractValue {
2866 pub(crate) fn from_llvm_ref(
2867 inst: LLVMValueRef,
2868 ctx: &mut ModuleContext,
2869 func_ctx: &mut FunctionContext,
2870 ) -> Self {
2871 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
2872 Self {
2873 aggregate: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2874 indices: unsafe {
2875 let num_indices = LLVMGetNumIndices(inst);
2876 let ptr = LLVMGetIndices(inst);
2877 std::slice::from_raw_parts(ptr, num_indices as usize).to_vec()
2878 },
2879 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2880 debugloc: DebugLoc::from_llvm_with_col(inst),
2881 }
2883 }
2884}
2885
2886impl InsertValue {
2887 pub(crate) fn from_llvm_ref(
2888 inst: LLVMValueRef,
2889 ctx: &mut ModuleContext,
2890 func_ctx: &mut FunctionContext,
2891 ) -> Self {
2892 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2893 Self {
2894 aggregate: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2895 element: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
2896 indices: unsafe {
2897 let num_indices = LLVMGetNumIndices(inst);
2898 let ptr = LLVMGetIndices(inst);
2899 std::slice::from_raw_parts(ptr, num_indices as usize).to_vec()
2900 },
2901 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2902 debugloc: DebugLoc::from_llvm_with_col(inst),
2903 }
2905 }
2906}
2907
2908impl Alloca {
2909 pub(crate) fn from_llvm_ref(
2910 inst: LLVMValueRef,
2911 ctx: &mut ModuleContext,
2912 func_ctx: &mut FunctionContext,
2913 ) -> Self {
2914 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
2915 Self {
2916 allocated_type: ctx
2917 .types
2918 .type_from_llvm_ref(unsafe { LLVMGetAllocatedType(inst) }),
2919 num_elements: Operand::from_llvm_ref(
2920 unsafe { LLVMGetOperand(inst, 0) }, ctx,
2922 func_ctx,
2923 ),
2924 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2925 alignment: unsafe { LLVMGetAlignment(inst) },
2926 debugloc: DebugLoc::from_llvm_with_col(inst),
2927 }
2929 }
2930}
2931
2932impl Load {
2933 pub(crate) fn from_llvm_ref(
2934 inst: LLVMValueRef,
2935 ctx: &mut ModuleContext,
2936 func_ctx: &mut FunctionContext,
2937 ) -> Self {
2938 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
2939 Self {
2940 address: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2941 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
2942 #[cfg(feature = "llvm-15-or-greater")]
2943 loaded_ty: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) }),
2944 volatile: unsafe { LLVMGetVolatile(inst) } != 0,
2945 atomicity: {
2946 let ordering = unsafe { LLVMGetOrdering(inst) };
2947 if ordering == LLVMAtomicOrdering::LLVMAtomicOrderingNotAtomic {
2948 None
2949 } else {
2950 Some(Atomicity {
2951 synch_scope: SynchronizationScope::from_llvm_ref(inst),
2952 mem_ordering: MemoryOrdering::from_llvm(ordering),
2953 })
2954 }
2955 },
2956 alignment: unsafe { LLVMGetAlignment(inst) },
2957 debugloc: DebugLoc::from_llvm_with_col(inst),
2958 }
2960 }
2961}
2962
2963impl Store {
2964 pub(crate) fn from_llvm_ref(
2965 inst: LLVMValueRef,
2966 ctx: &mut ModuleContext,
2967 func_ctx: &mut FunctionContext,
2968 ) -> Self {
2969 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
2970 Self {
2971 address: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
2972 value: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
2973 volatile: unsafe { LLVMGetVolatile(inst) } != 0,
2974 atomicity: {
2975 let ordering = unsafe { LLVMGetOrdering(inst) };
2976 if ordering == LLVMAtomicOrdering::LLVMAtomicOrderingNotAtomic {
2977 None
2978 } else {
2979 Some(Atomicity {
2980 synch_scope: SynchronizationScope::from_llvm_ref(inst),
2981 mem_ordering: MemoryOrdering::from_llvm(ordering),
2982 })
2983 }
2984 },
2985 alignment: unsafe { LLVMGetAlignment(inst) },
2986 debugloc: DebugLoc::from_llvm_with_col(inst),
2987 }
2989 }
2990}
2991
2992impl Fence {
2993 pub(crate) fn from_llvm_ref(inst: LLVMValueRef) -> Self {
2994 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 0);
2995 Self {
2996 atomicity: Atomicity {
2997 synch_scope: SynchronizationScope::from_llvm_ref(inst),
2998 mem_ordering: MemoryOrdering::from_llvm(unsafe { LLVMGetOrdering(inst) }),
2999 },
3000 debugloc: DebugLoc::from_llvm_with_col(inst),
3001 }
3003 }
3004}
3005
3006impl CmpXchg {
3007 pub(crate) fn from_llvm_ref(
3008 inst: LLVMValueRef,
3009 ctx: &mut ModuleContext,
3010 func_ctx: &mut FunctionContext,
3011 ) -> Self {
3012 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 3);
3013 Self {
3014 address: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3015 expected: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
3016 replacement: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 2) }, ctx, func_ctx),
3017 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3018 volatile: unsafe { LLVMGetVolatile(inst) } != 0,
3019 atomicity: Atomicity {
3020 synch_scope: SynchronizationScope::from_llvm_ref(inst),
3021 mem_ordering: MemoryOrdering::from_llvm(unsafe {
3022 LLVMGetCmpXchgSuccessOrdering(inst)
3023 }),
3024 },
3025 failure_memory_ordering: MemoryOrdering::from_llvm(unsafe {
3026 LLVMGetCmpXchgFailureOrdering(inst)
3027 }),
3028 #[cfg(feature = "llvm-10-or-greater")]
3029 weak: unsafe { LLVMGetWeak(inst) } != 0,
3030 debugloc: DebugLoc::from_llvm_with_col(inst),
3031 }
3033 }
3034}
3035
3036impl AtomicRMW {
3037 pub(crate) fn from_llvm_ref(
3038 inst: LLVMValueRef,
3039 ctx: &mut ModuleContext,
3040 func_ctx: &mut FunctionContext,
3041 ) -> Self {
3042 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
3043 Self {
3044 #[cfg(feature = "llvm-10-or-greater")]
3046 operation: RMWBinOp::from_llvm(unsafe { LLVMGetAtomicRMWBinOp(inst) }),
3047 address: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3048 value: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
3049 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3050 volatile: unsafe { LLVMGetVolatile(inst) } != 0,
3051 atomicity: Atomicity {
3052 synch_scope: SynchronizationScope::from_llvm_ref(inst),
3053 mem_ordering: MemoryOrdering::from_llvm(unsafe { LLVMGetOrdering(inst) }),
3054 },
3055 debugloc: DebugLoc::from_llvm_with_col(inst),
3056 }
3058 }
3059}
3060
3061impl GetElementPtr {
3062 pub(crate) fn from_llvm_ref(
3063 inst: LLVMValueRef,
3064 ctx: &mut ModuleContext,
3065 func_ctx: &mut FunctionContext,
3066 ) -> Self {
3067 Self {
3068 address: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3069 indices: {
3070 let num_indices = unsafe { LLVMGetNumIndices(inst) };
3071 (1 ..= num_indices)
3072 .map(|i| {
3073 Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, i) }, ctx, func_ctx)
3074 })
3075 .collect()
3076 },
3077 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3078 in_bounds: unsafe { LLVMIsInBounds(inst) } != 0,
3079 debugloc: DebugLoc::from_llvm_with_col(inst),
3080 #[cfg(feature = "llvm-14-or-greater")]
3081 source_element_type: ctx.types.type_from_llvm_ref(unsafe { LLVMGetGEPSourceElementType(inst) }),
3082 }
3084 }
3085}
3086
3087macro_rules! typed_unop_from_llvm {
3090 ($inst:ident) => {
3091 impl $inst {
3092 pub(crate) fn from_llvm_ref(
3093 inst: LLVMValueRef,
3094 ctx: &mut ModuleContext,
3095 func_ctx: &mut FunctionContext,
3096 ) -> Self {
3097 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
3098 Self {
3099 operand: Operand::from_llvm_ref(
3100 unsafe { LLVMGetOperand(inst, 0) },
3101 ctx,
3102 func_ctx,
3103 ),
3104 to_type: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) }),
3105 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3106 debugloc: DebugLoc::from_llvm_with_col(inst),
3107 }
3109 }
3110 }
3111 };
3112}
3113
3114typed_unop_from_llvm!(Trunc);
3115typed_unop_from_llvm!(ZExt);
3116typed_unop_from_llvm!(SExt);
3117typed_unop_from_llvm!(FPTrunc);
3118typed_unop_from_llvm!(FPExt);
3119typed_unop_from_llvm!(FPToUI);
3120typed_unop_from_llvm!(FPToSI);
3121typed_unop_from_llvm!(UIToFP);
3122typed_unop_from_llvm!(SIToFP);
3123typed_unop_from_llvm!(PtrToInt);
3124typed_unop_from_llvm!(IntToPtr);
3125typed_unop_from_llvm!(BitCast);
3126typed_unop_from_llvm!(AddrSpaceCast);
3127
3128impl ICmp {
3129 pub(crate) fn from_llvm_ref(
3130 inst: LLVMValueRef,
3131 ctx: &mut ModuleContext,
3132 func_ctx: &mut FunctionContext,
3133 ) -> Self {
3134 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
3135 Self {
3136 predicate: IntPredicate::from_llvm(unsafe { LLVMGetICmpPredicate(inst) }),
3137 operand0: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3138 operand1: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
3139 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3140 debugloc: DebugLoc::from_llvm_with_col(inst),
3141 }
3143 }
3144}
3145
3146impl FCmp {
3147 pub(crate) fn from_llvm_ref(
3148 inst: LLVMValueRef,
3149 ctx: &mut ModuleContext,
3150 func_ctx: &mut FunctionContext,
3151 ) -> Self {
3152 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 2);
3153 Self {
3154 predicate: FPPredicate::from_llvm(unsafe { LLVMGetFCmpPredicate(inst) }),
3155 operand0: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3156 operand1: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
3157 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3158 debugloc: DebugLoc::from_llvm_with_col(inst),
3159 }
3161 }
3162}
3163
3164impl Phi {
3165 pub(crate) fn from_llvm_ref(
3166 inst: LLVMValueRef,
3167 ctx: &mut ModuleContext,
3168 func_ctx: &mut FunctionContext,
3169 ) -> Self {
3170 Self {
3171 incoming_values: {
3172 let num_incoming = unsafe { LLVMCountIncoming(inst) };
3173 (0 .. num_incoming)
3174 .map(|i| {
3175 let operand = Operand::from_llvm_ref(
3176 unsafe { LLVMGetIncomingValue(inst, i) },
3177 ctx,
3178 func_ctx,
3179 );
3180 let name = func_ctx
3181 .bb_names
3182 .get(unsafe { &LLVMGetIncomingBlock(inst, i) })
3183 .expect("Failed to find incoming block in the map")
3184 .clone();
3185 (operand, name)
3186 })
3187 .collect()
3188 },
3189 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3190 to_type: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) }),
3191 debugloc: DebugLoc::from_llvm_with_col(inst),
3192 }
3194 }
3195}
3196
3197impl Select {
3198 pub(crate) fn from_llvm_ref(
3199 inst: LLVMValueRef,
3200 ctx: &mut ModuleContext,
3201 func_ctx: &mut FunctionContext,
3202 ) -> Self {
3203 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 3);
3204 Self {
3205 condition: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3206 true_value: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 1) }, ctx, func_ctx),
3207 false_value: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 2) }, ctx, func_ctx),
3208 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3209 debugloc: DebugLoc::from_llvm_with_col(inst),
3210 }
3212 }
3213}
3214
3215pub(crate) struct CallInfo {
3217 pub function: Either<InlineAssembly, Operand>,
3218 #[cfg(feature = "llvm-15-or-greater")]
3219 pub function_ty: TypeRef,
3220 pub arguments: Vec<(Operand, Vec<ParameterAttribute>)>,
3221 pub return_attributes: Vec<ParameterAttribute>,
3222 pub function_attributes: Vec<FunctionAttribute>,
3223 pub calling_convention: CallingConvention,
3224}
3225
3226impl CallInfo {
3227 pub(crate) fn from_llvm_ref(
3229 inst: LLVMValueRef,
3230 ctx: &mut ModuleContext,
3231 func_ctx: &mut FunctionContext,
3232 ) -> Self {
3233 use llvm_sys::{LLVMAttributeFunctionIndex, LLVMAttributeReturnIndex};
3234 let called_val = unsafe { LLVMGetCalledValue(inst) };
3235 Self {
3236 function: {
3237 let asm = unsafe { LLVMIsAInlineAsm(called_val) };
3238 if !asm.is_null() {
3239 Either::Left(InlineAssembly::from_llvm_ref(asm, &mut ctx.types))
3240 } else {
3241 Either::Right(Operand::from_llvm_ref(called_val, ctx, func_ctx))
3242 }
3243 },
3244 #[cfg(feature = "llvm-15-or-greater")]
3245 function_ty: ctx
3246 .types
3247 .type_from_llvm_ref(unsafe { LLVMGetCalledFunctionType(inst) }),
3248 arguments: {
3249 let num_args: u32 = unsafe { LLVMGetNumArgOperands(inst) } as u32;
3250 (0 .. num_args) .map(|i| {
3252 let operand = Operand::from_llvm_ref(
3253 unsafe { LLVMGetOperand(inst, i) },
3254 ctx,
3255 func_ctx,
3256 );
3257 let attrs = {
3258 let num_attrs =
3259 unsafe { LLVMGetCallSiteAttributeCount(inst, (i + 1) as u32) }; let mut attrs: Vec<LLVMAttributeRef> =
3261 Vec::with_capacity(num_attrs as usize);
3262 unsafe {
3263 LLVMGetCallSiteAttributes(inst, (i + 1) as u32, attrs.as_mut_ptr());
3264 attrs.set_len(num_attrs as usize);
3265 };
3266 attrs
3267 .into_iter()
3268 .map(|attr| {
3269 ParameterAttribute::from_llvm_ref(
3270 attr,
3271 &ctx.attrsdata,
3272 #[cfg(feature = "llvm-12-or-greater")]
3273 &mut ctx.types,
3274 )
3275 })
3276 .collect()
3277 };
3278 (operand, attrs)
3279 })
3280 .collect()
3281 },
3282 return_attributes: {
3283 let num_attrs =
3284 unsafe { LLVMGetCallSiteAttributeCount(inst, LLVMAttributeReturnIndex) };
3285 let mut attrs: Vec<LLVMAttributeRef> = Vec::with_capacity(num_attrs as usize);
3286 unsafe {
3287 LLVMGetCallSiteAttributes(inst, LLVMAttributeReturnIndex, attrs.as_mut_ptr());
3288 attrs.set_len(num_attrs as usize);
3289 };
3290 attrs
3291 .into_iter()
3292 .map(|attr| {
3293 ParameterAttribute::from_llvm_ref(
3294 attr,
3295 &ctx.attrsdata,
3296 #[cfg(feature = "llvm-12-or-greater")]
3297 &mut ctx.types,
3298 )
3299 })
3300 .collect()
3301 },
3302 function_attributes: {
3303 let num_attrs =
3304 unsafe { LLVMGetCallSiteAttributeCount(inst, LLVMAttributeFunctionIndex) };
3305 let mut attrs: Vec<LLVMAttributeRef> = Vec::with_capacity(num_attrs as usize);
3306 unsafe {
3307 LLVMGetCallSiteAttributes(inst, LLVMAttributeFunctionIndex, attrs.as_mut_ptr());
3308 attrs.set_len(num_attrs as usize);
3309 };
3310 attrs
3311 .into_iter()
3312 .map(|attr| FunctionAttribute::from_llvm_ref(attr, &ctx.attrsdata))
3313 .collect()
3314 },
3315 calling_convention: CallingConvention::from_u32(unsafe {
3316 LLVMGetInstructionCallConv(inst)
3317 }),
3318 }
3319 }
3320}
3321
3322impl Call {
3323 pub(crate) fn from_llvm_ref(
3324 inst: LLVMValueRef,
3325 ctx: &mut ModuleContext,
3326 func_ctx: &mut FunctionContext,
3327 ) -> Self {
3328 let callinfo = CallInfo::from_llvm_ref(inst, ctx, func_ctx);
3329 Self {
3330 function: callinfo.function,
3331 #[cfg(feature = "llvm-15-or-greater")]
3332 function_ty: callinfo.function_ty,
3333 arguments: callinfo.arguments,
3334 return_attributes: callinfo.return_attributes,
3335 dest: if unsafe {
3336 LLVMGetTypeKind(LLVMGetReturnType(LLVMGetCalledFunctionType(inst)))
3337 == LLVMVoidTypeKind
3338 } {
3339 None
3340 } else {
3341 Some(Name::name_or_num(
3342 unsafe { get_value_name(inst) },
3343 &mut func_ctx.ctr,
3344 ))
3345 },
3346 function_attributes: callinfo.function_attributes,
3347 is_tail_call: unsafe { LLVMIsTailCall(inst) } != 0,
3348 calling_convention: callinfo.calling_convention,
3349 debugloc: DebugLoc::from_llvm_with_col(inst),
3350 }
3352 }
3353}
3354
3355impl VAArg {
3356 pub(crate) fn from_llvm_ref(
3357 inst: LLVMValueRef,
3358 ctx: &mut ModuleContext,
3359 func_ctx: &mut FunctionContext,
3360 ) -> Self {
3361 assert_eq!(unsafe { LLVMGetNumOperands(inst) }, 1);
3362 Self {
3363 arg_list: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3364 cur_type: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) }),
3365 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3366 debugloc: DebugLoc::from_llvm_with_col(inst),
3367 }
3369 }
3370}
3371
3372impl LandingPad {
3373 pub(crate) fn from_llvm_ref(
3374 inst: LLVMValueRef,
3375 ctx: &mut ModuleContext,
3376 func_ctx: &mut FunctionContext,
3377 ) -> Self {
3378 Self {
3379 result_type: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(inst) }),
3380 clauses: {
3381 let num_clauses = unsafe { LLVMGetNumClauses(inst) };
3382 (0 .. num_clauses)
3383 .map(|i| LandingPadClause::from_llvm_ref(unsafe { LLVMGetClause(inst, i) }))
3384 .collect()
3385 },
3386 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3387 cleanup: unsafe { LLVMIsCleanup(inst) } != 0,
3388 debugloc: DebugLoc::from_llvm_with_col(inst),
3389 }
3391 }
3392}
3393
3394impl CatchPad {
3395 pub(crate) fn from_llvm_ref(
3396 inst: LLVMValueRef,
3397 ctx: &mut ModuleContext,
3398 func_ctx: &mut FunctionContext,
3399 ) -> Self {
3400 Self {
3401 catch_switch: Operand::from_llvm_ref(
3402 unsafe { LLVMGetParentCatchSwitch(inst) },
3403 ctx,
3404 func_ctx,
3405 ),
3406 args: {
3407 let num_args = unsafe { LLVMGetNumArgOperands(inst) };
3408 (0 .. num_args)
3409 .map(|i| {
3410 Operand::from_llvm_ref(unsafe { LLVMGetArgOperand(inst, i) }, ctx, func_ctx)
3411 })
3412 .collect()
3413 },
3414 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3415 debugloc: DebugLoc::from_llvm_with_col(inst),
3416 }
3418 }
3419}
3420
3421impl CleanupPad {
3422 pub(crate) fn from_llvm_ref(
3423 inst: LLVMValueRef,
3424 ctx: &mut ModuleContext,
3425 func_ctx: &mut FunctionContext,
3426 ) -> Self {
3427 Self {
3428 parent_pad: Operand::from_llvm_ref(unsafe { LLVMGetOperand(inst, 0) }, ctx, func_ctx),
3429 args: {
3430 let num_args = unsafe { LLVMGetNumArgOperands(inst) };
3431 (0 .. num_args)
3432 .map(|i| {
3433 Operand::from_llvm_ref(unsafe { LLVMGetArgOperand(inst, i) }, ctx, func_ctx)
3434 })
3435 .collect()
3436 },
3437 dest: Name::name_or_num(unsafe { get_value_name(inst) }, &mut func_ctx.ctr),
3438 debugloc: DebugLoc::from_llvm_with_col(inst),
3439 }
3441 }
3442}
3443
3444impl SynchronizationScope {
3445 pub(crate) fn from_llvm_ref(inst: LLVMValueRef) -> Self {
3446 if unsafe { LLVMIsAtomicSingleThread(inst) } != 0 {
3447 SynchronizationScope::SingleThread
3448 } else {
3449 SynchronizationScope::System
3450 }
3451 }
3452}
3453
3454impl MemoryOrdering {
3455 #[rustfmt::skip] pub(crate) fn from_llvm(ao: LLVMAtomicOrdering) -> Self {
3457 match ao {
3458 LLVMAtomicOrdering::LLVMAtomicOrderingUnordered => MemoryOrdering::Unordered,
3459 LLVMAtomicOrdering::LLVMAtomicOrderingMonotonic => MemoryOrdering::Monotonic,
3460 LLVMAtomicOrdering::LLVMAtomicOrderingAcquire => MemoryOrdering::Acquire,
3461 LLVMAtomicOrdering::LLVMAtomicOrderingRelease => MemoryOrdering::Release,
3462 LLVMAtomicOrdering::LLVMAtomicOrderingAcquireRelease => MemoryOrdering::AcquireRelease,
3463 LLVMAtomicOrdering::LLVMAtomicOrderingSequentiallyConsistent => MemoryOrdering::SequentiallyConsistent,
3464 LLVMAtomicOrdering::LLVMAtomicOrderingNotAtomic => MemoryOrdering::NotAtomic,
3465 }
3466 }
3467}
3468
3469#[cfg(feature = "llvm-10-or-greater")]
3470impl RMWBinOp {
3471 pub(crate) fn from_llvm(rmwbo: LLVMAtomicRMWBinOp) -> Self {
3472 match rmwbo {
3473 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpXchg => Self::Xchg,
3474 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpAdd => Self::Add,
3475 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpSub => Self::Sub,
3476 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpAnd => Self::And,
3477 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpNand => Self::Nand,
3478 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpOr => Self::Or,
3479 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpXor => Self::Xor,
3480 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpMax => Self::Max,
3481 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpMin => Self::Min,
3482 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpUMax => Self::UMax,
3483 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpUMin => Self::UMin,
3484 #[cfg(feature = "llvm-10-or-greater")]
3485 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpFAdd => Self::FAdd,
3486 #[cfg(feature = "llvm-10-or-greater")]
3487 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpFSub => Self::FSub,
3488 #[cfg(feature = "llvm-15-or-greater")]
3489 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpFMax => Self::FMax,
3490 #[cfg(feature = "llvm-15-or-greater")]
3491 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpFMin => Self::FMin,
3492 #[cfg(feature = "llvm-19-or-greater")]
3493 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpUIncWrap => Self::UIncWrap,
3494 #[cfg(feature = "llvm-19-or-greater")]
3495 LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpUDecWrap => Self::UDecWrap,
3496 }
3497 }
3498}
3499
3500impl InlineAssembly {
3501 pub(crate) fn from_llvm_ref(asm: LLVMValueRef, types: &mut TypesBuilder) -> Self {
3502 Self {
3507 ty: types.type_from_llvm_ref(unsafe { LLVMTypeOf(asm) }),
3508 }
3509 }
3510}
3511
3512impl LandingPadClause {
3513 pub(crate) fn from_llvm_ref(_lpc: LLVMValueRef) -> Self {
3514 Self {}
3518 }
3519}