dynasm/arch/
mod.rs

1use crate::State;
2use crate::common::{Expr, Jump, Size, Stmt, Value};
3
4use std::fmt::{self, Debug};
5
6pub mod x64;
7// pub mod aarch64;
8
9pub trait Arch: Debug + Send {
10    fn name(&self) -> &str;
11    fn set_features(&mut self, features: &[String]);
12    fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size);
13    fn default_align(&self) -> u8;
14}
15
16/// An environment that can dynamically build expressions from values.
17///
18/// These are used to integrate dynamic user expression into assembled code where values appear
19/// only in a modified form.
20pub trait BasicExprBuilder {
21    /// Append a new statement.
22    fn push(&mut self, _: Stmt);
23    /// Emit an error message.
24    /// When any error is generated then the instruction compilation is expected to fail.
25    fn emit_error_at(&mut self, _: ErrorSpan, _: fmt::Arguments);
26    /// a | b
27    fn bit_or(&mut self, _: Expr, _: Value) -> Option<Expr>;
28    /// a & b
29    fn bit_and(&mut self, _: Expr, _: Value) -> Option<Expr>;
30    /// a ^ b
31    fn bit_xor(&mut self, _: Expr, _: Value) -> Option<Expr>;
32    /// a + b
33    fn add(&mut self, _: Expr, _: Value) -> Option<Expr>;
34    /// a * b
35    fn mul(&mut self, _: Expr, _: Value) -> Option<Expr>;
36    /// !a
37    fn neg(&mut self, _: Expr) -> Option<Expr>;
38    /// Log2, mostly used to encode scalings.
39    fn log2(&mut self, _: Expr) -> Option<Expr>;
40    /// (val & mask) << shift
41    fn mask_shift(&mut self, val: Expr, mask: u64, shift: i8) -> Option<Expr>;
42}
43
44#[derive(Debug, Clone)]
45pub enum Error {
46    BadArgument {
47        message: String,
48    },
49    /// Expressions had to be combined but that failed.
50    BadExprCombinator {
51        /// The expression that should have been added to some other value.
52        expr: Expr,
53    },
54    /// An unexplained error happened.
55    #[deprecated]
56    UndiagnosedError,
57}
58
59/// An opaque description of an error origin.
60#[derive(Debug, Clone, Copy)]
61pub enum ErrorSpan {
62    InstructionPart {
63        idx: usize,
64    },
65    Argument {
66        idx: usize,
67    },
68}
69
70impl ErrorSpan {
71    pub fn instruction_part(idx: usize) -> Self {
72        ErrorSpan::InstructionPart { idx }
73    }
74
75    pub fn argument(idx: usize) -> Self {
76        ErrorSpan::Argument { idx }
77    }
78}
79
80impl From<&'static str> for Error {
81    fn from(message: &'_ str) -> Self {
82        message.to_string().into()
83    }
84}
85
86impl From<String> for Error {
87    fn from(message: String) -> Self {
88        Error::BadArgument { message }
89    }
90}
91
92impl From<Option<String>> for Error {
93    fn from(arg: Option<String>) -> Self {
94        match arg {
95            Some(message) => Error::BadArgument { message },
96            #[allow(deprecated)]
97            None => Error::UndiagnosedError,
98        }
99    }
100}
101
102pub trait BasicExprBuilderExt: BasicExprBuilder {
103    fn bit_or_else_err(&mut self, a: Expr, b: Value) -> Result<Expr, Error> {
104        self.bit_or(a, b).ok_or_else(|| Error::BadExprCombinator { expr: a })
105    }
106
107    fn bit_and_else_err(&mut self, a: Expr, b: Value) -> Result<Expr, Error> {
108        self.bit_and(a, b).ok_or_else(|| Error::BadExprCombinator { expr: a })
109    }
110
111    fn bit_xor_else_err(&mut self, a: Expr, b: Value) -> Result<Expr, Error> {
112        self.bit_xor(a, b).ok_or_else(|| Error::BadExprCombinator { expr: a })
113    }
114
115    fn neg_else_err(&mut self, a: Expr) -> Result<Expr, Error> {
116        self.neg(a).ok_or_else(|| Error::BadExprCombinator { expr: a })
117    }
118
119    fn add_else_err(&mut self, a: Expr, b: Value) -> Result<Expr, Error> {
120        self.add(a, b).ok_or_else(|| Error::BadExprCombinator { expr: a })
121    }
122
123    fn mul_else_err(&mut self, a: Expr, b: Value) -> Result<Expr, Error> {
124        self.mul(a, b).ok_or_else(|| Error::BadExprCombinator { expr: a })
125    }
126
127    fn add_many(&mut self, iter: impl IntoIterator<Item=Expr>) -> Option<Value> {
128        let mut res = Value::Byte(0);
129        for expr in iter {
130            res = self.add(expr, res)?.into();
131        }
132        Some(res)
133    }
134
135    fn add_many_else_err(&mut self, iter: impl IntoIterator<Item=Expr>) -> Result<Value, Error> {
136        let mut res = Value::Byte(0);
137        for expr in iter {
138            res = self.add_else_err(expr, res)?.into();
139        }
140        Ok(res)
141    }
142
143    /// reg | ((val & mask) << shift)
144    /// `val` is not a Value since then the lib could already constant fold until `|`.
145    fn mask_shift_or(&mut self, reg: Value, val: Expr, mask: u64, shift: i8) -> Option<Expr> {
146        let operand = self.mask_shift(val, mask, shift)?;
147        self.bit_or(operand, reg)
148    }
149
150    /// reg | ((val & mask) << shift)
151    fn mask_shift_or_else_err(&mut self, reg: Value, val: Expr, mask: u64, shift: i8) -> Result<Expr, Error> {
152        let operand = self.mask_shift_else_err(val, mask, shift)?;
153        self.bit_or_else_err(operand, reg)
154    }
155
156    /// reg & !((val & mask) << shift)
157    /// `val` is not a Value since then the lib could already constant fold until `|`.
158    fn mask_shift_inverted_and(&mut self, reg: Value, val: Expr, mask: u64, shift: i8) -> Option<Expr> {
159        let operand = self.mask_shift(val, mask, shift)?;
160        let operand = self.neg(operand)?;
161        self.bit_and(operand, reg)
162    }
163
164    /// reg | ((val & mask) << shift)
165    fn mask_shift_inverted_and_else_err(&mut self, reg: Value, val: Expr, mask: u64, shift: i8) -> Result<Expr, Error> {
166        let operand = self.mask_shift_else_err(val, mask, shift)?;
167        let operand = self.neg_else_err(operand)?;
168        self.bit_and_else_err(operand, reg)
169    }
170
171    fn log2_else_err(&mut self, a: Expr) -> Result<Expr, Error> {
172        self.log2(a).ok_or_else(|| Error::BadExprCombinator { expr: a })
173    }
174
175    fn dynscale(&mut self, _: Expr, _: Value) -> Result<(Expr, Expr), Error> {
176        unimplemented!()
177    }
178
179    fn mask_shift_else_err(&mut self, val: Expr, mask: u64, shift: i8) -> Result<Expr, Error> {
180        self.mask_shift(val, mask, shift).ok_or_else(|| Error::BadExprCombinator { expr: val })
181    }
182}
183
184impl<T: BasicExprBuilder + ?Sized> BasicExprBuilderExt for T { }
185
186#[derive(Clone, Debug)]
187pub struct DummyArch {
188    name: &'static str
189}
190
191impl DummyArch {
192    fn new(name: &'static str) -> DummyArch {
193        DummyArch { name }
194    }
195}
196
197impl Arch for DummyArch {
198    fn name(&self) -> &str {
199        self.name
200    }
201
202    fn set_features(&mut self, features: &[String]) {
203        if let Some(feature) = features.first() {
204            eprintln!("Cannot set features when the assembling architecture is undefined. Define it using a .arch directive");
205        }
206    }
207
208    fn handle_static_reloc(&self, _stmts: &mut Vec<Stmt>, _reloc: Jump, _size: Size) {
209        eprintln!("Current assembling architecture is undefined. Define it using a .arch directive");
210    }
211
212    fn default_align(&self) -> u8 {
213        0
214    }
215}
216
217/// A simple implementation of a `BasicExprBuilder`.
218///
219/// It can not combine any expressions, pushes statements into a `Vec` and emits errors onto
220/// standard error directly.
221impl BasicExprBuilder for State<'_> {
222    fn push(&mut self, stmt: Stmt) {
223        self.stmts.push(stmt)
224    }
225
226    /// Emits the error message on `stderr`.
227    fn emit_error_at(&mut self, _: ErrorSpan, args: fmt::Arguments) {
228        eprintln!("{}", args);
229    }
230
231    fn bit_or(&mut self, _: Expr, _: Value) -> Option<Expr> {
232        None 
233    }
234
235    fn bit_and(&mut self, _: Expr, _: Value) -> Option<Expr> {
236        None
237    }
238
239    fn bit_xor(&mut self, _: Expr, _: Value) -> Option<Expr> {
240        None
241    }
242
243    fn add(&mut self, _: Expr, _: Value) -> Option<Expr> {
244        None
245    }
246
247    fn mul(&mut self, _: Expr, _: Value) -> Option<Expr> {
248        None
249    }
250
251    fn neg(&mut self, _: Expr) -> Option<Expr> {
252        None
253    }
254
255    fn log2(&mut self, _: Expr) -> Option<Expr> {
256        None
257    }
258
259    fn mask_shift(&mut self, _: Expr, _: u64, _: i8) -> Option<Expr> {
260        None
261    }
262}
263
264pub(crate) fn from_str(s: &str) -> Option<Box<dyn Arch>> {
265    match s {
266        "x64" => Some(Box::new(x64::Archx64::default())),
267        "x86" => Some(Box::new(x64::Archx86::default())),
268        // "aarch64" => Some(Box::new(aarch64::ArchAarch64::default())),
269        "unknown" => Some(Box::new(DummyArch::new("unknown"))),
270        _ => None
271    }
272}
273
274#[cfg(target_arch="x86_64")]
275pub const CURRENT_ARCH: &str = "x64";
276#[cfg(target_arch="x86")]
277pub const CURRENT_ARCH: &str = "x86";
278#[cfg(target_arch="aarch64")]
279pub const CURRENT_ARCH: &str = "aarch64";
280#[cfg(not(any(target_arch="x86", target_arch="x86_64", target_arch="aarch64")))]
281pub const CURRENT_ARCH: &str = "unknown";