dynasm\arch/
mod.rs

1use syn::parse;
2use proc_macro_error2::emit_error;
3
4use crate::State;
5
6use std::fmt::Debug;
7
8pub mod x64;
9pub mod aarch64;
10pub mod riscv;
11
12pub(crate) trait Arch : Debug + Send {
13    /// When the .features directive is used for an architecture, this architecture method will be
14    /// called with the list of features as argument
15    fn set_features(&mut self, features: &[syn::Ident]);
16    /// The default byte to pad with for alignment for this architecture.
17    fn default_align(&self) -> u8;
18    /// The core of the architecture. This function parses a single instruction, storing the to be
19    /// emitted code in the passed `state` parameter. 
20    fn compile_instruction(&self, state: &mut State, input: parse::ParseStream) -> parse::Result<()>;
21}
22
23#[derive(Clone, Debug)]
24pub struct DummyArch {}
25
26impl DummyArch {
27    fn new() -> DummyArch {
28        DummyArch{}
29    }
30}
31
32impl Arch for DummyArch {
33    fn set_features(&mut self, features: &[syn::Ident]) {
34        if let Some(feature) = features.first() {
35            emit_error!(feature, "Cannot set features when the assembling architecture is undefined. Define it using a .arch directive");
36        }
37    }
38
39    fn default_align(&self) -> u8 {
40        0
41    }
42
43    fn compile_instruction(&self, _state: &mut State, input: parse::ParseStream) -> parse::Result<()> {
44        emit_error!(input.cursor().span(), "Current assembling architecture is undefined. Define it using a .arch directive");
45        Ok(())
46    }
47}
48
49pub(crate) fn from_str(s: &str) -> Option<Box<dyn Arch>> {
50    match s {
51        "x64" => Some(Box::new(x64::Archx64::default())),
52        "x86" => Some(Box::new(x64::Archx86::default())),
53        "aarch64" => Some(Box::new(aarch64::ArchAarch64::default())),
54        "riscv64i" | "riscv64" => Some(Box::new(riscv::ArchRiscV64I::default())),
55        "riscv64e" => Some(Box::new(riscv::ArchRiscV64E::default())),
56        "riscv32i" | "riscv32" => Some(Box::new(riscv::ArchRiscV32I::default())),
57        "riscv32e" => Some(Box::new(riscv::ArchRiscV32E::default())),
58        "unknown" => Some(Box::new(DummyArch::new())),
59        _ => None
60    }
61}
62
63#[cfg(target_arch="x86_64")]
64pub const CURRENT_ARCH: &str = "x64";
65#[cfg(target_arch="x86")]
66pub const CURRENT_ARCH: &str = "x86";
67#[cfg(target_arch="aarch64")]
68pub const CURRENT_ARCH: &str = "aarch64";
69// TODO: there seems to be no good way to detect riscv64i from riscv64e. You're probably not running
70// rustc on an embedded targets so assume the i variant.
71#[cfg(target_arch="riscv64")]
72pub const CURRENT_ARCH: &str = "riscv64i";
73#[cfg(target_arch="riscv32")]
74pub const CURRENT_ARCH: &str = "riscv32i";
75#[cfg(not(any(
76    target_arch="x86",
77    target_arch="x86_64",
78    target_arch="aarch64",
79    target_arch="riscv64",
80    target_arch="riscv32"
81)))]
82pub const CURRENT_ARCH: &str = "unknown";