1use std::ffi::{CStr, c_char};
2use std::marker::PhantomData;
3use std::ptr::{NonNull, null_mut};
4use std::{fmt, ops};
5
6use paste::paste;
7use smallvec::SmallVec;
8
9use crate::{MemoryFile, MirContext, ffi};
10
11#[repr(transparent)]
13pub(crate) struct ErrorType(pub(crate) ffi::MIR_error_type);
14
15macro_rules! impl_error_type_variants {
16 ($($var:ident),* $(,)?) => {
17 impl fmt::Display for ErrorType {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self.0 {
20 $(paste!(ffi:: [<MIR_ $var _error>]) => concat!("MIR_", stringify!($var), "_error"),)*
21 raw => return raw.fmt(f),
22 }
23 .fmt(f)
24 }
25 }
26 };
27}
28
29impl_error_type_variants! {
30 no,
31 syntax,
32 binary_io,
33 alloc,
34 finish,
35 no_module,
36 nested_module,
37 no_func,
38 func,
39 vararg_func,
40 nested_func,
41 wrong_param_value,
42 hard_reg,
43 reserved_name,
44 import_export,
45 undeclared_func_reg,
46 repeated_decl,
47 reg_type,
48 wrong_type,
49 unique_reg,
50 undeclared_op_ref,
51 ops_num,
52 call_op,
53 unspec_op,
54 wrong_lref,
55 ret,
56 op_mode,
57 out_op,
58 invalid_insn,
59 ctx_change,
60}
61
62#[derive(Clone, Copy, PartialEq, Eq)]
64#[repr(transparent)]
65pub struct Ty(pub(crate) ffi::MIR_type_t);
66
67macro_rules! impl_ty_variants {
68 ($($var:ident),* $(,)?) => {
69 impl Ty {
70 $(
71 #[doc = concat!("`MIR_T_", stringify!($var), "`")]
72 pub const $var: Self = Self(paste!(ffi::[<MIR_T_ $var>]));
73 )*
74 }
75
76 impl fmt::Debug for Ty {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 let s = match *self {
79 $(Self::$var => concat!("Ty(MIR_T_", stringify!($var), ")"),)*
80 Self(raw) => return f.debug_tuple("Ty").field(&raw).finish(),
81 };
82 f.write_str(s)
83 }
84 }
85 };
86}
87
88impl_ty_variants! {
89 I8, U8, I16, U16, I32, U32, I64, U64,
90 F, D, LD, P,
91 BLK, RBLK, UNDEF, BOUND,
92}
93
94#[test]
95fn ty_debug() {
96 assert_eq!(format!("{:?}", Ty::I64), "Ty(MIR_T_I64)");
97 assert_eq!(format!("{:?}", Ty(99)), "Ty(99)");
98}
99
100#[derive(Debug, Clone, Copy)]
102#[repr(transparent)]
103pub struct Reg(pub(crate) ffi::MIR_reg_t);
104
105#[derive(Clone, Copy, PartialEq, Eq)]
107#[repr(transparent)]
108pub struct ItemType(pub(crate) ffi::MIR_item_type_t);
109
110macro_rules! impl_item_type_variants {
111 ($($var:ident),* $(,)?) => {
112 impl ItemType {
113 $(
114 #[doc = paste!(concat!("`MIR_", stringify!([<$var:lower>]), "_item`"))]
115 pub const $var: Self = Self(paste!(ffi::[<MIR_ $var:lower _item>]));
116 )*
117 }
118
119 impl fmt::Debug for ItemType {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 let s = match *self {
122 $(Self::$var => paste!(concat!("ItemType(MIR_", stringify!($var:lower), "_item)")),)*
123 Self(raw) => return f.debug_tuple("ItemType").field(&raw).finish(),
124 };
125 f.write_str(s)
126 }
127 }
128 };
129}
130
131impl_item_type_variants! {
132 FUNC, PROTO,
133 IMPORT, EXPORT, FORWARD,
134 DATA, REF_DATA, LREF_DATA, EXPR_DATA,
135 BSS,
136}
137
138#[derive(Clone, Copy)]
140#[repr(transparent)]
141pub struct ItemRef<'a>(
142 pub(crate) NonNull<ffi::MIR_item>,
143 pub(crate) PhantomData<&'a ffi::MIR_item>,
144);
145
146impl ItemRef<'_> {
147 pub(crate) unsafe fn from_raw(raw: *mut ffi::MIR_item) -> Self {
148 let raw = NonNull::new(raw).expect("item must not be null");
149 Self(raw, PhantomData)
150 }
151
152 #[must_use]
154 pub fn as_raw(&self) -> *mut ffi::MIR_item {
155 self.0.as_ptr()
156 }
157
158 #[must_use]
160 pub fn dump(&self, ctx: &MirContext) -> String {
161 MemoryFile::with(|file| unsafe { ffi::MIR_output_item(ctx.as_raw(), file, self.as_raw()) })
162 .1
163 }
164
165 #[must_use]
167 pub fn type_(&self) -> ItemType {
168 unsafe { ItemType(self.0.as_ref().item_type) }
169 }
170
171 #[must_use]
173 pub fn name(&self) -> Option<&CStr> {
174 let item = unsafe { self.0.as_ref() };
175 let data = &item.u;
176 let ptr = unsafe {
177 match item.item_type {
178 ffi::MIR_func_item => (*data.func.cast::<FuncItemData>()).0.name,
179 ffi::MIR_proto_item => (*data.func.cast::<ProtoItemData>()).0.name,
180 ffi::MIR_import_item => data.import_id,
181 ffi::MIR_export_item => data.export_id,
182 ffi::MIR_forward_item => data.forward_id,
183 ffi::MIR_data_item => (*data.data.cast::<DataItemData>()).0.name,
184 ffi::MIR_ref_data_item => (*data.ref_data.cast::<RefDataItemData>()).0.name,
185 ffi::MIR_lref_data_item => (*data.lref_data.cast::<LabelRefDataItemData>()).0.name,
186 ffi::MIR_expr_data_item => (*data.expr_data.cast::<ExprDataItemData>()).0.name,
187 ffi::MIR_bss_item => (*data.bss.cast::<BssItemData>()).0.name,
188 _ => return None,
189 }
190 };
191 if ptr.is_null() {
192 None
193 } else {
194 unsafe { Some(CStr::from_ptr(ptr)) }
195 }
196 }
197}
198
199impl<'a> From<ItemRef<'a>> for Operand<'a> {
200 fn from(item: ItemRef<'a>) -> Self {
201 Operand {
202 op: unsafe { ffi::MIR_new_ref_op(null_mut(), item.as_raw()) },
203 _marker: PhantomData,
204 }
205 }
206}
207
208impl fmt::Debug for ItemRef<'_> {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 let mut fs = f.debug_struct("ItemRef");
211 let item = unsafe { self.0.as_ref() };
212 fs.field("ptr", &std::ptr::from_ref(self))
213 .field("module", &item.module)
214 .field("addr", &item.addr)
215 .field("type", &self.type_());
216 let data = &item.u;
217 let mut cb = |data| {
218 fs.field("u", data);
219 };
220 match item.item_type {
221 ffi::MIR_func_item => cb(unsafe { &*data.func.cast::<FuncItemData>() }),
222 ffi::MIR_proto_item => cb(unsafe { &*data.func.cast::<ProtoItemData>() }),
223 ffi::MIR_import_item => cb(&DebugImportLikeItemData(
224 "ImportItemData",
225 "import_id",
226 unsafe { data.import_id },
227 )),
228 ffi::MIR_export_item => cb(&DebugImportLikeItemData(
229 "ExportItemData",
230 "export_id",
231 unsafe { data.export_id },
232 )),
233 ffi::MIR_forward_item => cb(&DebugImportLikeItemData(
234 "ForwardItemData",
235 "forward_id",
236 unsafe { data.forward_id },
237 )),
238 ffi::MIR_data_item => cb(unsafe { &*data.data.cast::<DataItemData>() }),
239 ffi::MIR_ref_data_item => cb(unsafe { &*data.ref_data.cast::<RefDataItemData>() }),
240 ffi::MIR_lref_data_item => {
241 cb(unsafe { &*data.lref_data.cast::<LabelRefDataItemData>() });
242 }
243 ffi::MIR_expr_data_item => cb(unsafe { &*data.expr_data.cast::<ExprDataItemData>() }),
244 ffi::MIR_bss_item => cb(unsafe { &*data.bss.cast::<BssItemData>() }),
245 _ => {}
246 }
247 fs.finish_non_exhaustive()
248 }
249}
250
251#[derive(Debug, Clone)]
253pub struct ItemRefDowncastError(());
254
255impl fmt::Display for ItemRefDowncastError {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 f.write_str("item type mismatch")
258 }
259}
260
261impl std::error::Error for ItemRefDowncastError {}
262
263macro_rules! def_item_ref_variant {
264 ($name:ident, $item_type:expr, $doc:literal) => {
265 #[doc = $doc]
267 #[derive(Debug, Clone, Copy)]
269 #[repr(transparent)]
270 pub struct $name<'a>(pub(crate) ItemRef<'a>);
271
272 impl<'a> ops::Deref for $name<'a> {
273 type Target = ItemRef<'a>;
274
275 fn deref(&self) -> &Self::Target {
276 &self.0
277 }
278 }
279
280 impl<'a> From<$name<'a>> for Operand<'a> {
281 fn from(item: $name<'a>) -> Self {
282 item.0.into()
283 }
284 }
285
286 impl<'a> TryFrom<ItemRef<'a>> for $name<'a> {
287 type Error = ItemRefDowncastError;
288 fn try_from(item: ItemRef<'a>) -> Result<Self, Self::Error> {
289 if unsafe { item.0.as_ref().item_type } == $item_type {
290 Ok(Self(item))
291 } else {
292 Err(ItemRefDowncastError(()))
293 }
294 }
295 }
296 };
297}
298
299def_item_ref_variant!(FuncItemRef, ffi::MIR_func_item, "function");
300
301impl FuncItemRef<'_> {
302 pub(crate) unsafe fn data(&self) -> &ffi::MIR_func {
305 unsafe { &*self.0.0.as_ref().u.func }
306 }
307}
308
309#[repr(transparent)]
310struct FuncItemData(ffi::MIR_func);
311
312impl fmt::Debug for FuncItemData {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 let u = &self.0;
315 f.debug_struct("FuncItemData")
316 .field("name", &unsafe { CStr::from_ptr(u.name) })
317 .field("func_item", &u.func_item)
318 .field("original_vars_num", &u.original_insns)
319 .field("nres", &u.nres)
320 .field("nargs", &u.nargs)
321 .field("res_types", &unsafe {
322 std::slice::from_raw_parts(u.res_types.cast::<Ty>(), u.nres as usize)
323 })
324 .field("varargs_p", &(u.vararg_p != 0))
325 .field("expr_p", &(u.expr_p != 0))
326 .field("jret_p", &(u.jret_p != 0))
327 .field("vars", &DebugVars(u.vars))
328 .field("global_vars", &DebugVars(u.global_vars))
329 .finish_non_exhaustive()
330 }
331}
332
333#[repr(transparent)]
334struct DebugVar(ffi::MIR_var);
335
336impl fmt::Debug for DebugVar {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 f.debug_struct("Var")
339 .field("type", &Ty(self.0.type_))
340 .field("name", &unsafe { CStr::from_ptr(self.0.name) })
341 .finish_non_exhaustive()
343 }
344}
345
346struct DebugVars(*mut ffi::VARR_MIR_var_t);
347
348impl fmt::Debug for DebugVars {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 let vars = if self.0.is_null() {
351 &[]
352 } else {
353 unsafe {
354 let varr = &*self.0;
355 std::slice::from_raw_parts(varr.varr.cast::<DebugVar>().cast_const(), varr.els_num)
356 }
357 };
358 vars.fmt(f)
359 }
360}
361
362def_item_ref_variant!(ProtoItemRef, ffi::MIR_proto_item, "prototype");
363
364#[repr(transparent)]
365struct ProtoItemData(ffi::MIR_proto);
366
367impl fmt::Debug for ProtoItemData {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 let u = &self.0;
370 f.debug_struct("ProtoItemData")
371 .field("name", &unsafe { CStr::from_ptr(u.name) })
372 .field("nres", &u.nres)
373 .field("res_types", &unsafe {
374 std::slice::from_raw_parts(u.res_types.cast::<Ty>(), u.nres as usize)
375 })
376 .finish_non_exhaustive()
377 }
378}
379
380def_item_ref_variant!(ImportItemRef, ffi::MIR_import_item, "import");
381def_item_ref_variant!(ExportItemRef, ffi::MIR_export_item, "export");
382def_item_ref_variant!(ForwardItemRef, ffi::MIR_forward_item, "forward declaration");
383
384struct DebugImportLikeItemData(&'static str, &'static str, *const c_char);
385
386impl fmt::Debug for DebugImportLikeItemData {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 f.debug_struct(self.0)
389 .field(self.1, &unsafe { CStr::from_ptr(self.2) })
390 .finish()
391 }
392}
393
394def_item_ref_variant!(DataItemRef, ffi::MIR_data_item, "data");
395
396#[repr(transparent)]
397struct DataItemData(ffi::MIR_data);
398
399impl fmt::Debug for DataItemData {
400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401 let u = &self.0;
402 f.debug_struct("DataItemData")
403 .field("name", &unsafe { CStr::from_ptr(u.name) })
404 .field("el_type", &Ty(u.el_type))
405 .field("nel", &u.nel)
406 .finish_non_exhaustive()
407 }
408}
409
410def_item_ref_variant!(RefDataItemRef, ffi::MIR_ref_data_item, "referential data");
411
412#[repr(transparent)]
413struct RefDataItemData(ffi::MIR_ref_data);
414
415impl fmt::Debug for RefDataItemData {
416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417 let u = &self.0;
418 f.debug_struct("RefDataItemData")
419 .field("name", &unsafe { CStr::from_ptr(u.name) })
420 .field("ref_item", &unsafe { ItemRef::from_raw(u.ref_item) })
421 .field("disp", &u.disp)
422 .field("load_addr", &u.load_addr)
423 .finish()
424 }
425}
426
427def_item_ref_variant!(LabelRefDataItemRef, ffi::MIR_lref_data_item, "label data");
428
429#[repr(transparent)]
430struct LabelRefDataItemData(ffi::MIR_lref_data);
431
432impl fmt::Debug for LabelRefDataItemData {
433 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434 let u = &self.0;
435 f.debug_struct("LabelRefDataItemData")
436 .field("name", &unsafe { CStr::from_ptr(u.name) })
437 .field("disp", &u.disp)
438 .field("load_addr", &u.load_addr)
439 .finish()
440 }
441}
442
443def_item_ref_variant!(ExprDataItemRef, ffi::MIR_expr_data_item, "computed data");
444
445#[repr(transparent)]
446struct ExprDataItemData(ffi::MIR_expr_data);
447
448impl fmt::Debug for ExprDataItemData {
449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450 let u = &self.0;
451 f.debug_struct("ExprItemData")
452 .field("name", &unsafe { CStr::from_ptr(u.name) })
453 .field("expr_item", &unsafe { ItemRef::from_raw(u.expr_item) })
454 .finish_non_exhaustive()
455 }
456}
457
458def_item_ref_variant!(BssItemRef, ffi::MIR_bss_item, "writable memory segment");
459
460#[repr(transparent)]
461struct BssItemData(ffi::MIR_bss);
462
463impl fmt::Debug for BssItemData {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 let u = &self.0;
466 f.debug_struct("BssItemData")
467 .field("name", &unsafe { CStr::from_ptr(u.name) })
468 .field("len", &u.len)
469 .finish()
470 }
471}
472
473#[derive(Clone, Copy)]
475#[repr(transparent)]
476pub struct Operand<'a> {
477 pub(crate) op: ffi::MIR_op_t,
478 pub(crate) _marker: PhantomData<&'a ()>,
479}
480
481impl fmt::Debug for Operand<'_> {
482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 let mut s = f.debug_struct("Operand");
484 unsafe {
485 match ffi::MIR_op_mode_t::from(self.op.mode) {
486 ffi::MIR_OP_REG => s.field("reg", &self.op.u.reg),
487 ffi::MIR_OP_VAR => s.field("var", &self.op.u.var),
488 ffi::MIR_OP_INT => s.field("int", &self.op.u.i),
489 ffi::MIR_OP_UINT => s.field("uint", &self.op.u.u),
490 ffi::MIR_OP_FLOAT => s.field("float", &self.op.u.f),
491 ffi::MIR_OP_DOUBLE => s.field("double", &self.op.u.d),
492 ffi::MIR_OP_REF => s.field("ref", &ItemRef::from_raw(self.op.u.ref_)),
493 ffi::MIR_OP_MEM => s.field("mem", &self.op.u.mem),
494 ffi::MIR_OP_LABEL => s.field("label", &..),
495 _ => return s.finish_non_exhaustive(),
500 }
501 .finish()
502 }
503 }
504}
505
506pub trait IntoOperand<'a>: Into<Operand<'a>> {}
508
509pub trait IntoOutOperand<'a>: IntoOperand<'a> {}
511
512impl<'a, T> IntoOperand<'a> for T where Operand<'a>: From<T> {}
513
514impl IntoOutOperand<'_> for Reg {}
515impl From<Reg> for Operand<'_> {
516 fn from(reg: Reg) -> Self {
517 Self {
518 op: unsafe { ffi::MIR_new_reg_op(null_mut(), reg.0) },
519 _marker: PhantomData,
520 }
521 }
522}
523
524#[derive(Debug, Clone, Copy)]
526#[repr(transparent)]
527pub struct Label<'a>(pub(crate) ffi::MIR_label_t, pub(crate) PhantomData<&'a ()>);
528
529impl<'a> From<Label<'a>> for Operand<'a> {
530 fn from(label: Label<'a>) -> Self {
531 Self {
532 op: unsafe { ffi::MIR_new_label_op(null_mut(), label.0) },
533 _marker: PhantomData,
534 }
535 }
536}
537
538#[derive(Debug, Clone, Copy)]
543pub struct MemOp {
544 ty: Ty,
545 disp: i64,
546 base: Reg,
547 index: Reg,
548 scale: u8,
549}
550
551impl MemOp {
552 #[must_use]
554 pub fn new_base(ty: Ty, base: Reg) -> Self {
555 Self {
556 ty,
557 disp: 0,
558 base,
559 index: Reg(0),
560 scale: 1,
561 }
562 }
563
564 #[must_use]
566 pub fn disp(self, disp: i64) -> Self {
567 Self { disp, ..self }
568 }
569
570 #[must_use]
572 pub fn index(self, index: Reg) -> Self {
573 Self { index, ..self }
574 }
575
576 #[must_use]
582 pub fn scale(self, scale: u8) -> Self {
583 assert!(matches!(scale, 1 | 2 | 4 | 8), "scale must be 1, 2, 4 or 8");
584 Self { scale, ..self }
585 }
586}
587
588impl IntoOutOperand<'_> for MemOp {}
589impl From<MemOp> for Operand<'_> {
590 fn from(mem: MemOp) -> Self {
591 Self {
592 op: unsafe {
593 ffi::MIR_new_mem_op(
594 null_mut(),
595 mem.ty.0,
596 mem.disp,
597 mem.base.0,
598 mem.index.0,
599 mem.scale,
600 )
601 },
602 _marker: PhantomData,
603 }
604 }
605}
606
607macro_rules! impl_literal_into_op {
608 ($($ty:ident, $func:ident;)*) => {
609 $(
610 impl From<$ty> for Operand<'_> {
611 fn from(v: $ty) -> Self {
612 Self {
613 op: unsafe { ffi::$func(null_mut(), v) },
614 _marker: PhantomData,
615 }
616 }
617 }
618 )*
619 };
620}
621
622impl_literal_into_op! {
623 i64, MIR_new_int_op;
624 u64, MIR_new_uint_op;
625 f32, MIR_new_float_op;
626 f64, MIR_new_double_op;
627}
628
629macro_rules! def_simple_insn {
630 (__impl $args:tt $name:ident) => {
631 def_simple_insn!(__impl $args $name paste!(ffi::[<MIR_ $name:upper>]));
632 };
633 (__impl (dst $(, $src:ident)*) $name:ident $code:expr) => {
634 fn $name<'o>(self, dst: impl IntoOutOperand<'o>, $($src: impl IntoOperand<'o>),*) {
635 build_insn(self, $code, [dst.into(), $($src.into()),*]);
636 }
637 };
638 (__impl (_ $(, $src:ident)*) $name:ident $code:expr) => {
639 fn $name<'o>(self, $($src: impl IntoOperand<'o>),*) {
640 build_insn(self, $code, [$($src.into()),*]);
641 }
642 };
643 (
644 $args:tt;
645 $($name:ident $(($code:expr))?),*
646 $(,)?
647 ) => {
648 $(def_simple_insn!(__impl $args $name $($code)?);)*
649 };
650}
651
652macro_rules! def_jump_insn {
653 (__impl (label $(, $src:ident)*) $name:ident) => {
654 #[allow(clippy::needless_lifetimes)]
655 fn $name<'o>(self, label: Label<'o>, $($src: impl IntoOperand<'o>),*) {
656 build_insn(self, paste!(ffi::[<MIR_ $name:upper>]), [label.into(), $($src.into()),*]);
657 }
658 };
659 (
660 $args:tt;
661 $($name:ident $(($code:expr))?),*
662 $(,)?
663 ) => {
664 $(def_jump_insn!(__impl $args $name $($code)?);)*
665 };
666}
667
668macro_rules! def_call_insn {
669 ($($name:ident),* $(,)?) => {
670 $(
671 fn $name<'o>(
672 self,
673 proto: ProtoItemRef<'o>,
674 func: impl IntoOperand<'o>,
675 results: impl IntoIterator<Item = Operand<'o>>,
676 args: impl IntoIterator<Item = Operand<'o>>,
677 ) {
678 build_insn(
679 self,
680 paste!(ffi::[<MIR_ $name:upper>]),
681 [proto.into(), func.into()]
682 .into_iter()
683 .chain(results)
684 .chain(args),
685 );
686 }
687 )*
688 };
689}
690
691#[doc(hidden)]
696pub unsafe trait InsnBuilderBase<'module>: Sized {
697 fn get_raw_ctx(&self) -> ffi::MIR_context_t;
698 unsafe fn insert(self, insn: ffi::MIR_insn_t);
701}
702
703impl<'module, T: InsnBuilderBase<'module>> InsnBuilder<'module> for T {}
704
705#[allow(missing_docs)]
723pub trait InsnBuilder<'module>: InsnBuilderBase<'module> {
724 def_simple_insn! {
728 (dst, src);
729
730 mov, fmov, dmov, ext8, ext16, ext32, uext8, uext16, uext32,
733
734 i2f, i2d, ui2f, ui2d, f2i, d2i, f2d, d2f, neg, negs, fneg, dneg, addr, addr8, addr16, addr32,
742 }
743
744 def_simple_insn! {
746 (dst, a, b);
747
748 add, adds, fadd, dadd, sub, subs, fsub, dsub, mul, muls, fmul, dmul, div, divs, udiv, udivs, fdiv, ddiv, mod_(ffi::MIR_MOD), mods, umod, umods,
753
754 and, ands, or, ors, xor, xors,
755 lsh, lshs, rsh, rshs, ursh, urshs,
756
757 eq, eqs, feq, deq, ne, nes, fne, dne, lt, lts, ult, ults, flt, dlt, le, les, ule, ules, fle, dle, gt, gts, ugt, ugts, fgt, dgt, ge, ges, uge, uges, fge, dge, addo, addos, subo, subos, mulo, mulos, umulo, umulos,
765 }
766
767 def_jump_insn!((label); jmp, bo, bno, ubo, ubno);
769 def_simple_insn!((_, label_op); jmpi);
770 def_jump_insn!((label, v); bt, bts, bf, bfs);
771 def_jump_insn! {
772 (label, a, b);
773 beq, beqs, fbeq, dbeq, bne, bnes, fbne, dbne, blt, blts, ublt, ublts, fblt, dblt, ble, bles, uble, ubles, fble, dble, bgt, bgts, ubgt, ubgts, fbgt, dbgt, bge, bges, ubge, ubges, fbge, dbge, }
780 fn laddr<'o>(self, dst: impl IntoOutOperand<'o>, label: Label<'_>) {
781 build_insn(self, ffi::MIR_LADDR, [dst.into(), label.into()]);
782 }
783
784 def_call_insn!(call, inline, jcall);
786 def_simple_insn!((_, v); ret, jret);
787
788 def_simple_insn!((dst, len); alloca);
790 def_simple_insn!((_, va_list); va_start, va_end);
791 def_simple_insn!((dst, va_list, size, block_type); va_block_arg);
792 fn va_arg<'o>(self, dst: impl IntoOutOperand<'o>, va_list: impl IntoOperand<'o>, mem: MemOp) {
793 build_insn(
794 self,
795 ffi::MIR_VA_ARG,
796 [dst.into(), va_list.into(), mem.into()],
797 );
798 }
799
800 fn label(self, label: Label<'_>) {
803 unsafe { self.insert(label.0) };
804 }
805 fn new_label(self) -> Label<'module> {
807 let insn = unsafe { ffi::MIR_new_label(self.get_raw_ctx()) };
808 unsafe { self.insert(insn) };
809 Label(insn, PhantomData)
810 }
811}
812
813fn build_insn<'module, 'o>(
814 this: impl InsnBuilderBase<'module>,
815 code: mir_sys::MIR_insn_code_t,
816 ops: impl IntoIterator<Item = Operand<'o>>,
817) {
818 let ctx = this.get_raw_ctx();
819 let ops = ops.into_iter().collect::<SmallVec<[Operand; 6]>>();
820 let insn = unsafe {
821 ffi::MIR_new_insn_arr(
822 ctx,
823 code,
824 ops.len(),
825 ops.as_ptr().cast::<ffi::MIR_op_t>().cast_mut(),
826 )
827 };
828 unsafe { this.insert(insn) };
829}