1use backtrace::Backtrace;
2use openvm_stark_backend::p3_field::Field;
3use serde::{Deserialize, Serialize};
4
5use crate::{utils::isize_to_field, LocalOpcode, PhantomDiscriminant, SystemOpcode, VmOpcode};
6
7pub const NUM_OPERANDS: usize = 7;
9
10#[repr(C)]
11#[allow(clippy::too_many_arguments)]
12#[derive(Clone, Debug, PartialEq, Eq, derive_new::new, Serialize, Deserialize)]
13pub struct Instruction<F> {
14 pub opcode: VmOpcode,
15 pub a: F,
16 pub b: F,
17 pub c: F,
18 pub d: F,
19 pub e: F,
20 pub f: F,
21 pub g: F,
22}
23
24impl<F: Field> Instruction<F> {
25 #[allow(clippy::too_many_arguments)]
26 pub fn from_isize(opcode: VmOpcode, a: isize, b: isize, c: isize, d: isize, e: isize) -> Self {
27 Self {
28 opcode,
29 a: isize_to_field::<F>(a),
30 b: isize_to_field::<F>(b),
31 c: isize_to_field::<F>(c),
32 d: isize_to_field::<F>(d),
33 e: isize_to_field::<F>(e),
34 f: isize_to_field::<F>(0),
35 g: isize_to_field::<F>(0),
36 }
37 }
38
39 pub fn from_usize<const N: usize>(opcode: VmOpcode, operands: [usize; N]) -> Self {
40 let mut operands = operands.map(F::from_canonical_usize).to_vec();
41 operands.resize(NUM_OPERANDS, F::ZERO);
42 Self {
43 opcode,
44 a: operands[0],
45 b: operands[1],
46 c: operands[2],
47 d: operands[3],
48 e: operands[4],
49 f: operands[5],
50 g: operands[6],
51 }
52 }
53
54 #[allow(clippy::too_many_arguments)]
55 pub fn large_from_isize(
56 opcode: VmOpcode,
57 a: isize,
58 b: isize,
59 c: isize,
60 d: isize,
61 e: isize,
62 f: isize,
63 g: isize,
64 ) -> Self {
65 Self {
66 opcode,
67 a: isize_to_field::<F>(a),
68 b: isize_to_field::<F>(b),
69 c: isize_to_field::<F>(c),
70 d: isize_to_field::<F>(d),
71 e: isize_to_field::<F>(e),
72 f: isize_to_field::<F>(f),
73 g: isize_to_field::<F>(g),
74 }
75 }
76
77 pub fn phantom(discriminant: PhantomDiscriminant, a: F, b: F, c_upper: u16) -> Self {
78 Self {
79 opcode: SystemOpcode::PHANTOM.global_opcode(),
80 a,
81 b,
82 c: F::from_canonical_u32((discriminant.0 as u32) | ((c_upper as u32) << 16)),
83 ..Default::default()
84 }
85 }
86
87 pub fn debug(discriminant: PhantomDiscriminant) -> Self {
88 Self {
89 opcode: SystemOpcode::PHANTOM.global_opcode(),
90 c: F::from_canonical_u32(discriminant.0 as u32),
91 ..Default::default()
92 }
93 }
94
95 pub fn operands(&self) -> Vec<F> {
96 vec![self.a, self.b, self.c, self.d, self.e, self.f, self.g]
97 }
98}
99
100impl<T: Default> Default for Instruction<T> {
101 fn default() -> Self {
102 Self {
103 opcode: VmOpcode::from_usize(0), a: T::default(),
105 b: T::default(),
106 c: T::default(),
107 d: T::default(),
108 e: T::default(),
109 f: T::default(),
110 g: T::default(),
111 }
112 }
113}
114
115#[derive(Debug, Clone, Default, Serialize, Deserialize)]
116pub struct DebugInfo {
117 pub dsl_instruction: String,
118 pub trace: Option<Backtrace>,
119}
120
121impl DebugInfo {
122 pub fn new(dsl_instruction: String, trace: Option<Backtrace>) -> Self {
123 Self {
124 dsl_instruction,
125 trace,
126 }
127 }
128}