asm_lsp/
types.rs

1use std::{
2    collections::{BTreeMap, HashMap, HashSet},
3    fmt::{Display, Write as _},
4    path::PathBuf,
5    str::FromStr,
6};
7
8use bincode::{BorrowDecode, Encode};
9use compile_commands::{CompilationDatabase, SourceFile};
10use log::{info, warn};
11use lsp_textdocument::TextDocuments;
12use lsp_types::{CompletionItem, Uri};
13use schemars::JsonSchema;
14use serde::{Deserialize, Serialize};
15use strum_macros::{AsRefStr, Display, EnumString};
16use tree_sitter::{Parser, Tree};
17
18use crate::{
19    UriConversion, populate_name_to_directive_map, populate_name_to_instruction_map,
20    populate_name_to_register_map, process_uri,
21};
22
23pub const BINCODE_CFG: bincode::config::Configuration = bincode::config::standard().with_no_limit();
24
25// Instruction
26#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
27pub struct Instruction {
28    pub name: String,
29    pub summary: String,
30    pub forms: Vec<InstructionForm>,
31    pub asm_templates: Vec<String>,
32    pub aliases: Vec<InstructionAlias>,
33    pub url: Option<String>,
34    pub arch: Arch,
35}
36
37impl Hoverable for Instruction {}
38impl Completable for Instruction {}
39
40impl Default for Instruction {
41    fn default() -> Self {
42        let name = String::new();
43        let summary = String::new();
44        let forms = vec![];
45        let asm_templates = vec![];
46        let aliases = vec![];
47        let url = None;
48        let arch = Arch::None;
49
50        Self {
51            name,
52            summary,
53            forms,
54            asm_templates,
55            aliases,
56            url,
57            arch,
58        }
59    }
60}
61
62impl std::fmt::Display for Instruction {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        // basic fields
65        let header = format!("{} [{}]", &self.name, self.arch.as_ref());
66
67        //let mut v: Vec<&str> = vec![&header, &self.summary, "\n", "## Forms", "\n"];
68        let mut v: Vec<&str> = vec![&header, &self.summary, "\n"];
69
70        if !self.forms.is_empty() {
71            v.append(&mut vec!["## Forms", "\n"]);
72        }
73
74        // instruction forms
75        let instruction_form_strs: Vec<String> =
76            self.forms.iter().map(|f| format!("{f}")).collect();
77        for item in &instruction_form_strs {
78            v.push(item.as_str());
79        }
80
81        if !self.asm_templates.is_empty() {
82            v.append(&mut vec!["## Templates", "\n"]);
83        }
84        // instruction templates
85        let instruction_template_strs: Vec<String> = self
86            .asm_templates
87            .iter()
88            .map(|f| format!(" + `{}`", f.as_str()))
89            .collect();
90        for item in &instruction_template_strs {
91            v.push(item.as_str());
92        }
93
94        if !self.aliases.is_empty() {
95            v.append(&mut vec!["## Aliases", "\n"]);
96        }
97
98        // instruction aliases
99        let instruction_alias_strs: Vec<String> =
100            self.aliases.iter().map(|f| format!("{f}\n")).collect();
101        for item in &instruction_alias_strs {
102            v.push(item.as_str());
103        }
104
105        // url
106        let more_info: String;
107        if let Some(url) = &self.url {
108            more_info = format!("\nMore info: {url}");
109            v.push(&more_info);
110        }
111
112        let s = v.join("\n");
113        write!(f, "{s}")?;
114        Ok(())
115    }
116}
117
118impl<'own> Instruction {
119    /// Add a new form at the current instruction
120    pub fn push_form(&mut self, form: InstructionForm) {
121        self.forms.push(form);
122    }
123
124    /// Add a new alias at the current instruction
125    pub fn push_alias(&mut self, form: InstructionAlias) {
126        self.aliases.push(form);
127    }
128
129    /// Get the primary names
130    #[must_use]
131    pub fn get_primary_names(&'own self) -> Vec<&'own str> {
132        let names = vec![self.name.as_ref()];
133
134        names
135    }
136
137    /// Get the names of all the associated commands (includes Go and Gas forms)
138    #[must_use]
139    pub fn get_associated_names(&'own self) -> Vec<&'own str> {
140        let mut names = Vec::<&'own str>::new();
141
142        for f in &self.forms {
143            for name in [&f.gas_name, &f.go_name, &f.z80_name]
144                .iter()
145                .copied()
146                .flatten()
147            {
148                names.push(name);
149            }
150        }
151
152        names
153    }
154}
155
156// TODO: Rework this to use a tagged union...
157// InstructionForm
158#[derive(
159    Default, Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize, Encode, BorrowDecode,
160)]
161pub struct InstructionForm {
162    // --- Gas/Go-Specific Information ---
163    pub gas_name: Option<String>,
164    pub go_name: Option<String>,
165    pub mmx_mode: Option<MMXMode>,
166    pub xmm_mode: Option<XMMMode>,
167    pub cancelling_inputs: Option<bool>,
168    pub nacl_version: Option<u8>,
169    pub nacl_zero_extends_outputs: Option<bool>,
170    // --- Z80-Specific Information ---
171    pub z80_name: Option<String>,
172    pub z80_form: Option<String>,
173    pub z80_opcode: Option<String>,
174    pub z80_timing: Option<Z80Timing>,
175    // --- Avr-Specific Information ---
176    pub avr_mneumonic: Option<String>,
177    pub avr_summary: Option<String>,
178    pub avr_version: Option<String>,
179    pub avr_timing: Option<AvrTiming>,
180    pub avr_status_register: Option<AvrStatusRegister>,
181    // --- Assembler/Architecture Agnostic Info ---
182    pub isa: Option<ISA>,
183    pub operands: Vec<Operand>,
184    pub urls: Vec<String>,
185}
186
187impl std::fmt::Display for InstructionForm {
188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189        let mut s = String::new();
190        if let Some(val) = &self.gas_name {
191            write!(s, "*GAS*: {val} | ")?;
192        }
193        if let Some(val) = &self.go_name {
194            write!(s, "*GO*: {val} | ")?;
195        }
196        if let Some(val) = &self.z80_form {
197            write!(s, "*Z80*: {val} | ")?;
198        }
199        if let Some(val) = &self.avr_mneumonic {
200            let version_str = self
201                .avr_version
202                .as_ref()
203                .map_or_else(String::new, |version| format!(" ({version})"));
204            write!(s, "*AVR*: {val}{version_str} | ")?;
205        }
206
207        if let Some(val) = &self.mmx_mode {
208            write!(s, "*MMX*: {} | ", val.as_ref())?;
209        }
210        if let Some(val) = &self.xmm_mode {
211            write!(s, "*XMM*: {} | ", val.as_ref())?;
212        }
213        if let Some(val) = &self.z80_opcode {
214            if val.contains(',') {
215                write!(s, "*Opcodes*: {val} | ")?;
216            } else {
217                write!(s, "*Opcode*: {val} | ")?;
218            }
219        }
220
221        // cancelling inputs
222        // nacl_version
223        // nacl_zero_extends_outputs
224
225        // ISA
226        if let Some(val) = &self.isa {
227            write!(s, "*ISA*: {} | ", val.as_ref())?;
228        }
229
230        if !s.is_empty() {
231            s = format!("- {}\n\n", &s[..s.len() - 3]);
232        }
233
234        // Operands
235        let operands_str: String = if self.operands.is_empty() {
236            String::new()
237        } else {
238            self.operands
239                .iter()
240                .map(|op| {
241                    let mut s = format!("  + {:<8}", format!("[{}]", op.type_.as_ref()));
242                    if let Some(input) = op.input {
243                        write!(s, " input = {input:<5} ").unwrap();
244                    }
245                    if let Some(output) = op.output {
246                        write!(s, " output = {output:<5}").unwrap();
247                    }
248                    if let Some(extended_size) = op.extended_size {
249                        write!(s, " extended-size = {extended_size}").unwrap();
250                    }
251
252                    s.trim_end().to_owned()
253                })
254                .collect::<Vec<String>>()
255                .join("\n")
256        };
257
258        s += &operands_str;
259
260        if let Some(ref timing) = self.z80_timing {
261            write!(s, "\n  + {timing}")?;
262        }
263
264        if let Some(summary) = &self.avr_summary {
265            write!(s, "\n\n{summary}")?;
266        }
267        if let Some(sreg) = &self.avr_status_register {
268            write!(s, "\n\n{sreg}")?;
269        }
270        if let Some(ref timing) = self.avr_timing {
271            writeln!(s, "\n\n{timing}")?;
272        }
273
274        for url in &self.urls {
275            writeln!(s, "\n  + More info: {url}")?;
276        }
277
278        write!(f, "{s}")?;
279        Ok(())
280    }
281}
282
283// InstructionAlias
284#[derive(
285    Default, Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize, Encode, BorrowDecode,
286)]
287pub struct InstructionAlias {
288    pub title: String,
289    pub summary: String,
290    pub asm_templates: Vec<String>,
291}
292
293impl std::fmt::Display for InstructionAlias {
294    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295        let mut s = self.title.clone();
296
297        if !self.summary.is_empty() {
298            write!(s, "\n {}", self.summary)?;
299        }
300
301        for template in &self.asm_templates {
302            write!(s, "\n + `{template}`")?;
303        }
304
305        write!(f, "{s}")?;
306        Ok(())
307    }
308}
309
310#[derive(
311    Debug, Default, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize, Encode, BorrowDecode,
312)]
313pub enum Z80TimingValue {
314    #[default]
315    Unknown,
316    Val(u8),
317}
318
319impl Display for Z80TimingValue {
320    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321        match self {
322            Self::Unknown => {
323                write!(f, "?")?;
324            }
325            Self::Val(val) => {
326                write!(f, "{val}")?;
327            }
328        }
329
330        Ok(())
331    }
332}
333
334impl FromStr for Z80TimingValue {
335    type Err = std::num::ParseIntError;
336    fn from_str(s: &str) -> Result<Self, Self::Err> {
337        if s.eq("?") {
338            Ok(Self::Unknown)
339        } else {
340            match s.parse::<u8>() {
341                Ok(val) => Ok(Self::Val(val)),
342                Err(e) => Err(e),
343            }
344        }
345    }
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Serialize, Deserialize, Encode, BorrowDecode)]
349pub enum Z80TimingInfo {
350    OneNum(Z80TimingValue), // better names here?
351    TwoNum((Z80TimingValue, Z80TimingValue)),
352    ThreeNum((Z80TimingValue, Z80TimingValue, Z80TimingValue)),
353}
354
355impl Default for Z80TimingInfo {
356    fn default() -> Self {
357        Self::OneNum(Z80TimingValue::Unknown)
358    }
359}
360
361impl Display for Z80TimingInfo {
362    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363        match self {
364            Self::OneNum(num) => {
365                write!(f, "{num}")?;
366            }
367            Self::TwoNum((num1, num2)) => {
368                write!(f, "{num1}/{num2}")?;
369            }
370            Self::ThreeNum((num1, num2, num3)) => {
371                write!(f, "{num1}/{num2}/{num3}")?;
372            }
373        }
374        Ok(())
375    }
376}
377
378impl FromStr for Z80TimingInfo {
379    type Err = String;
380    fn from_str(s: &str) -> Result<Self, Self::Err> {
381        if s.starts_with('/') || s.ends_with('/') {
382            return Err(String::from("Cannot have an empty num value"));
383        }
384
385        let pieces: Vec<Result<Z80TimingValue, std::num::ParseIntError>> =
386            s.split('/').map(str::parse).collect();
387
388        match pieces.len() {
389            1 => pieces[0].as_ref().map_or_else(
390                |_| Err(String::from("Failed to parse one timing value")),
391                |num| Ok(Self::OneNum(*num)),
392            ),
393            2 => match (&pieces[0], &pieces[1]) {
394                (Ok(num1), Ok(num2)) => Ok(Self::TwoNum((*num1, *num2))),
395                _ => Err(String::from("Failed to parse one or more timing values")),
396            },
397            3 => match (&pieces[0], &pieces[1], &pieces[2]) {
398                (Ok(num1), Ok(num2), Ok(num3)) => Ok(Self::ThreeNum((*num1, *num2, *num3))),
399                _ => Err(String::from("Failed to parse one or more timing values")),
400            },
401            n => Err(format!("Expected 1-3 timing values, got {n}")),
402        }
403    }
404}
405
406#[derive(
407    Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
408)]
409pub struct Z80Timing {
410    pub z80: Z80TimingInfo,
411    pub z80_plus_m1: Z80TimingInfo,
412    pub r800: Z80TimingInfo,
413    pub r800_plus_wait: Z80TimingInfo,
414}
415
416impl Display for Z80Timing {
417    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
418        write!(
419            f,
420            "Z80: {}, Z80 + M1: {}, R800: {}, R800 + Wait: {}",
421            self.z80, self.z80_plus_m1, self.r800, self.z80_plus_m1
422        )?;
423        Ok(())
424    }
425}
426
427#[derive(
428    Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
429)]
430pub struct AvrTiming {
431    pub avre: Option<String>,
432    pub avrxm: Option<String>,
433    pub avrxt: Option<String>,
434    pub avrrc: Option<String>,
435}
436
437impl Display for AvrTiming {
438    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
439        write!(f, "Timing: ")?;
440        let mut has_prev = false;
441        if let Some(ref cycles) = self.avre {
442            write!(f, "AVRE: {cycles}")?;
443            has_prev = true;
444        }
445        if let Some(ref cycles) = self.avrxm {
446            if has_prev {
447                write!(f, " | ")?;
448            }
449            write!(f, "AVRXM: {cycles}")?;
450            has_prev = true;
451        }
452        if let Some(ref cycles) = self.avrxt {
453            if has_prev {
454                write!(f, " | ")?;
455            }
456            write!(f, "AVRXT: {cycles}")?;
457            has_prev = true;
458        }
459        if let Some(ref cycles) = self.avrrc {
460            if has_prev {
461                write!(f, " | ")?;
462            }
463            write!(f, "AVRRC: {cycles}")?;
464        }
465
466        Ok(())
467    }
468}
469
470#[derive(
471    Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
472)]
473pub struct AvrStatusRegister {
474    pub i: char,
475    pub t: char,
476    pub h: char,
477    pub s: char,
478    pub v: char,
479    pub n: char,
480    pub c: char,
481    pub z: char,
482}
483
484impl std::fmt::Display for AvrStatusRegister {
485    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
486        writeln!(f, "I T H S V N Z C")?;
487        writeln!(
488            f,
489            "{} {} {} {} {} {} {} {}",
490            self.i, self.t, self.h, self.s, self.v, self.n, self.c, self.z
491        )?;
492        Ok(())
493    }
494}
495
496// Directive
497#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
498pub struct Directive {
499    pub name: String,
500    pub signatures: Vec<String>,
501    pub description: String,
502    pub deprecated: bool,
503    pub url: Option<String>,
504    pub assembler: Assembler,
505}
506
507impl Hoverable for Directive {}
508impl Completable for Directive {}
509
510impl Default for Directive {
511    fn default() -> Self {
512        let name = String::new();
513        let signatures = vec![];
514        let description = String::new();
515        let deprecated = false;
516        let url = None;
517        let assembler = Assembler::None;
518
519        Self {
520            name,
521            signatures,
522            description,
523            deprecated,
524            url,
525            assembler,
526        }
527    }
528}
529
530impl std::fmt::Display for Directive {
531    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
532        // basic fields
533        // &self.assembler {
534        let header = format!(
535            "{} [{}]{}",
536            &self.name,
537            self.assembler,
538            if self.deprecated {
539                "\n**DEPRECATED**"
540            } else {
541                ""
542            }
543        );
544
545        let mut v: Vec<&str> = vec![&header, &self.description, "\n"];
546
547        // signature(s)
548        let mut sigs = String::new();
549        for sig in &self.signatures {
550            writeln!(sigs, "- {sig}")?;
551        }
552        v.push(&sigs);
553
554        // url
555        let more_info: String;
556        match &self.url {
557            None => {}
558            Some(url_) => {
559                more_info = format!("\nMore info: {url_}");
560                v.push(&more_info);
561            }
562        }
563
564        let s = v.join("\n");
565        write!(f, "{}", s.trim())?;
566        Ok(())
567    }
568}
569
570#[derive(Default, Debug, Clone)]
571pub enum Z80Register8Bit {
572    #[default]
573    A,
574    AShadow,
575    F,
576    FShadow,
577    B,
578    BShadow,
579    C,
580    CShadow,
581    D,
582    DShadow,
583    E,
584    EShadow,
585    H,
586    HShadow,
587    L,
588    LShadow,
589}
590
591#[derive(Default, Debug, Clone)]
592pub enum Z80Register16Bit {
593    AF,
594    AFShadow,
595    BC,
596    BCShadow,
597    DE,
598    DEShadow,
599    #[default]
600    HL,
601    HLShadow,
602}
603
604impl<'own> Directive {
605    /// get the names of all the associated directives
606    #[must_use]
607    pub fn get_associated_names(&'own self) -> Vec<&'own str> {
608        let names = vec![self.name.as_ref()];
609
610        names
611    }
612}
613
614// Register
615#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
616pub struct Register {
617    pub name: String,
618    pub description: Option<String>,
619    pub reg_type: Option<RegisterType>,
620    pub width: Option<RegisterWidth>,
621    pub flag_info: Vec<RegisterBitInfo>,
622    pub arch: Arch,
623    pub url: Option<String>,
624}
625
626impl Hoverable for Register {}
627impl Completable for Register {}
628
629impl Default for Register {
630    fn default() -> Self {
631        let name = String::new();
632        let description = None;
633        let reg_type = None;
634        let width = None;
635        let flag_info = vec![];
636        let arch = Arch::None;
637        let url = None;
638
639        Self {
640            name,
641            description,
642            reg_type,
643            width,
644            flag_info,
645            arch,
646            url,
647        }
648    }
649}
650
651impl std::fmt::Display for Register {
652    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
653        // basic fields
654        let header = format!("{} [{}]", &self.name.to_uppercase(), self.arch.as_ref());
655
656        let mut v: Vec<String> = if let Some(description_) = &self.description {
657            vec![header, description_.clone(), String::from("\n")]
658        } else {
659            vec![header, String::from("\n")]
660        };
661
662        // Register Type
663        if let Some(reg_type_) = &self.reg_type {
664            let reg_type = format!("Type: {reg_type_}");
665            v.push(reg_type);
666        }
667
668        // Register Width
669        if let Some(reg_width_) = self.width {
670            let reg_width = format!("Width: {reg_width_}");
671            v.push(reg_width);
672        }
673
674        // Bit-mask flag meanings if applicable
675        if !self.flag_info.is_empty() {
676            let flag_heading = String::from("\n## Flags:");
677            v.push(flag_heading);
678
679            let flags: Vec<String> = self
680                .flag_info
681                .iter()
682                .map(|flag| format!("{flag}"))
683                .collect();
684            for flag in &flags {
685                v.push(flag.clone());
686            }
687        }
688
689        // TODO: URL support
690        if let Some(url_) = &self.url {
691            let more_info = format!("\nMore info: {url_}");
692            v.push(more_info);
693        }
694
695        let s = v.join("\n");
696        write!(f, "{s}")?;
697        Ok(())
698    }
699}
700
701impl<'own> Register {
702    /// Add a new bit flag entry at the current instruction
703    pub fn push_flag(&mut self, flag: RegisterBitInfo) {
704        self.flag_info.push(flag);
705    }
706
707    /// get the names of all the associated registers
708    #[must_use]
709    pub fn get_associated_names(&'own self) -> Vec<&'own str> {
710        let names = vec![self.name.as_ref()];
711
712        names
713    }
714}
715
716// helper structs, types and functions
717#[derive(Debug, Clone, Default)]
718pub struct NameToInfoMaps {
719    pub instructions: NameToInstructionMap,
720    pub registers: NameToRegisterMap,
721    pub directives: NameToDirectiveMap,
722}
723
724pub type NameToInstructionMap = HashMap<(Arch, String), Instruction>;
725
726pub type NameToRegisterMap = HashMap<(Arch, String), Register>;
727
728pub type NameToDirectiveMap = HashMap<(Assembler, String), Directive>;
729
730pub trait Hoverable: Display + Clone {}
731pub trait Completable: Display {}
732pub trait ArchOrAssembler: Clone + Copy {}
733
734#[derive(
735    Debug,
736    Clone,
737    PartialEq,
738    Eq,
739    Hash,
740    EnumString,
741    AsRefStr,
742    Serialize,
743    Deserialize,
744    Encode,
745    BorrowDecode,
746)]
747pub enum XMMMode {
748    SSE,
749    AVX,
750}
751
752#[derive(
753    Debug,
754    Clone,
755    Eq,
756    PartialEq,
757    Hash,
758    EnumString,
759    AsRefStr,
760    Serialize,
761    Deserialize,
762    Encode,
763    BorrowDecode,
764)]
765pub enum MMXMode {
766    FPU,
767    MMX,
768}
769
770#[allow(non_camel_case_types)]
771#[derive(
772    Debug,
773    Hash,
774    PartialEq,
775    Eq,
776    Clone,
777    Copy,
778    EnumString,
779    AsRefStr,
780    Serialize,
781    Deserialize,
782    Encode,
783    BorrowDecode,
784    JsonSchema,
785)]
786pub enum Arch {
787    #[strum(serialize = "x86")]
788    #[serde(rename = "x86")]
789    X86,
790    #[strum(serialize = "x86-64")]
791    #[serde(rename = "x86-64")]
792    X86_64,
793    /// enables both `Arch::X86` and `Arch::X86_64`
794    #[strum(serialize = "x86/x86-64")]
795    #[serde(rename = "x86/x86-64")]
796    X86_AND_X86_64,
797    #[strum(serialize = "arm")]
798    #[serde(rename = "arm")]
799    ARM,
800    #[strum(serialize = "arm64")]
801    #[serde(rename = "arm64")]
802    ARM64,
803    #[strum(serialize = "riscv")]
804    #[serde(rename = "riscv")]
805    RISCV,
806    #[strum(serialize = "z80")]
807    #[serde(rename = "z80")]
808    Z80,
809    #[strum(serialize = "6502")]
810    #[serde(rename = "6502")]
811    MOS6502,
812    #[strum(serialize = "power-isa")]
813    #[serde(rename = "power-isa")]
814    PowerISA,
815    #[strum(serialize = "AVR")]
816    #[serde(rename = "AVR")] // TODO: lower-case this in the generation code
817    Avr,
818    #[strum(serialize = "mips")]
819    #[serde(rename = "mips")]
820    Mips,
821    /// For testing purposes *only*. This is not a valid config option
822    #[serde(skip)]
823    None,
824}
825
826impl ArchOrAssembler for Arch {}
827
828impl Arch {
829    /// Setup registers for a particular architecture
830    ///
831    /// # Panics
832    ///
833    /// Panics if unable to deserialize `Register`
834    pub fn setup_registers(self, names_to_registers: &mut HashMap<(Self, String), Register>) {
835        macro_rules! load_registers_with_path {
836            ($arch:expr, $path:literal) => {{
837                let start = std::time::Instant::now();
838                let serialized_regs = include_bytes!($path);
839                let registers = bincode::borrow_decode_from_slice::<Vec<Register>, _>(serialized_regs, BINCODE_CFG)
840                    .unwrap_or_else(|e| panic!("Error deserializing {} registers -- {}\nRegenerate serialized data with regenerate.sh", $arch, e)).0;
841
842                info!(
843                    "{} register set loaded in {}ms",
844                    $arch,
845                    start.elapsed().as_millis()
846                );
847
848                populate_name_to_register_map($arch, &registers, names_to_registers);
849            }};
850        }
851
852        match self {
853            Self::ARM => load_registers_with_path!(Self::ARM, "serialized/registers/arm"),
854            Self::ARM64 => load_registers_with_path!(Self::ARM64, "serialized/registers/arm"),
855            Self::Avr => load_registers_with_path!(Self::Avr, "serialized/registers/avr"),
856            Self::Mips => load_registers_with_path!(Self::Mips, "serialized/registers/mips"),
857            Self::MOS6502 => load_registers_with_path!(Self::MOS6502, "serialized/registers/6502"),
858            Self::PowerISA => {
859                load_registers_with_path!(Self::PowerISA, "serialized/registers/power-isa");
860            }
861            Self::RISCV => load_registers_with_path!(Self::RISCV, "serialized/registers/riscv"),
862            Self::X86 => load_registers_with_path!(Self::X86, "serialized/registers/x86"),
863            Self::X86_64 => load_registers_with_path!(Self::X86_64, "serialized/registers/x86_64"),
864            Self::X86_AND_X86_64 => {
865                load_registers_with_path!(Self::X86, "serialized/registers/x86");
866                load_registers_with_path!(Self::X86_64, "serialized/registers/x86_64");
867            }
868            Self::Z80 => load_registers_with_path!(Self::Z80, "serialized/registers/z80"),
869            Self::None => unreachable!(),
870        }
871    }
872
873    /// Setup instructions for a particular architecture
874    ///
875    /// # Panics
876    ///
877    /// Panics if unable to deserialize `Instruction`s
878    pub fn setup_instructions(
879        self,
880        assembler: Option<Assembler>,
881        names_to_instructions: &mut HashMap<(Self, String), Instruction>,
882    ) {
883        macro_rules! load_instructions_with_path {
884            ($arch:expr, $path:literal) => {{
885                let start = std::time::Instant::now();
886                let serialized_instrs = include_bytes!($path);
887                let instructions = bincode::borrow_decode_from_slice::<Vec<Instruction>, _>(serialized_instrs, BINCODE_CFG)
888                    .unwrap_or_else(|e| panic!("Error deserializing {} instructions -- {}\nRegenerate serialized data with regenerate.sh", $arch, e))
889                    .0;
890
891                info!(
892                    "{} instruction set loaded in {}ms",
893                    $arch,
894                    start.elapsed().as_millis()
895                );
896
897                populate_name_to_instruction_map($arch, &instructions, names_to_instructions);
898            }};
899        }
900
901        match self {
902            Self::ARM => load_instructions_with_path!(Self::ARM, "serialized/opcodes/arm"),
903            // NOTE: Actually, the arm file are all arm64 so we needed to get
904            // the arm32 versions then do the below
905            Self::ARM64 => load_instructions_with_path!(Self::ARM64, "serialized/opcodes/arm"),
906            Self::Avr => load_instructions_with_path!(Self::Avr, "serialized/opcodes/avr"),
907            Self::MOS6502 => load_instructions_with_path!(Self::MOS6502, "serialized/opcodes/6502"),
908            Self::Mips => {
909                load_instructions_with_path!(Self::Mips, "serialized/opcodes/mips");
910                if Some(Assembler::Mars) == assembler {
911                    load_instructions_with_path!(Self::Mips, "serialized/opcodes/mars");
912                }
913            }
914            Self::PowerISA => {
915                load_instructions_with_path!(Self::PowerISA, "serialized/opcodes/power-isa");
916            }
917            Self::RISCV => load_instructions_with_path!(Self::RISCV, "serialized/opcodes/riscv"),
918            Self::X86 => load_instructions_with_path!(Self::X86, "serialized/opcodes/x86"),
919            Self::X86_64 => load_instructions_with_path!(Self::X86_64, "serialized/opcodes/x86_64"),
920            Self::X86_AND_X86_64 => {
921                load_instructions_with_path!(Self::X86, "serialized/opcodes/x86");
922                load_instructions_with_path!(Self::X86_64, "serialized/opcodes/x86_64");
923            }
924            Self::Z80 => load_instructions_with_path!(Self::Z80, "serialized/opcodes/z80"),
925            Self::None => unreachable!(),
926        }
927    }
928}
929
930impl Default for Arch {
931    fn default() -> Self {
932        match () {
933            () if cfg!(target_arch = "x86") => {
934                info!("Detected host arch as x86");
935                Self::X86
936            }
937            () if cfg!(target_arch = "arm") => {
938                info!("Detected host arch as arm");
939                Self::ARM
940            }
941            () if cfg!(target_arch = "aarch64") => {
942                info!("Detected host arch as aarch64");
943                Self::ARM64
944            }
945            () if cfg!(target_arch = "riscv32") => {
946                info!("Detected host arch as riscv32");
947                Self::RISCV
948            }
949            () if cfg!(target_arch = "riscv64") => {
950                info!("Detected host arch as riscv64");
951                Self::RISCV
952            }
953            () => {
954                if cfg!(target_arch = "x86_64") {
955                    info!("Detected host arch as x86-64");
956                } else {
957                    info!("Failed to detect host arch, defaulting to x86-64");
958                }
959                Self::X86_64 // Somewhat arbitrary default
960            }
961        }
962    }
963}
964
965impl std::fmt::Display for Arch {
966    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
967        match self {
968            Self::ARM => write!(f, "arm")?,
969            Self::ARM64 => write!(f, "arm64")?,
970            Self::Avr => write!(f, "avr")?,
971            Self::Mips => write!(f, "mips")?,
972            Self::MOS6502 => write!(f, "6502")?,
973            Self::PowerISA => write!(f, "power-isa")?,
974            Self::RISCV => write!(f, "riscv")?,
975            Self::X86 => write!(f, "x86")?,
976            Self::X86_64 => write!(f, "x86-64")?,
977            Self::X86_AND_X86_64 => write!(f, "x86/x86-64")?,
978            Self::Z80 => write!(f, "z80")?,
979            Self::None => write!(f, "None")?,
980        }
981        Ok(())
982    }
983}
984
985#[derive(
986    Debug,
987    Display,
988    Default,
989    Hash,
990    PartialEq,
991    Eq,
992    Clone,
993    Copy,
994    EnumString,
995    AsRefStr,
996    Serialize,
997    Deserialize,
998    Encode,
999    BorrowDecode,
1000    JsonSchema,
1001)]
1002pub enum Assembler {
1003    #[strum(serialize = "avr")]
1004    #[serde(rename = "avr")]
1005    Avr,
1006    #[strum(serialize = "ca65")]
1007    #[serde(rename = "ca65")]
1008    Ca65,
1009    #[strum(serialize = "fasm")]
1010    #[serde(rename = "fasm")]
1011    Fasm,
1012    #[default]
1013    #[strum(serialize = "gas")]
1014    #[serde(rename = "gas")]
1015    Gas,
1016    #[strum(serialize = "go")]
1017    #[serde(rename = "go")]
1018    Go,
1019    #[strum(serialize = "mars")]
1020    #[serde(rename = "mars")]
1021    Mars,
1022    #[strum(serialize = "masm")]
1023    #[serde(rename = "masm")]
1024    Masm,
1025    #[strum(serialize = "nasm")]
1026    #[serde(rename = "nasm")]
1027    Nasm,
1028    #[serde(skip)]
1029    None,
1030}
1031
1032impl ArchOrAssembler for Assembler {}
1033
1034impl Assembler {
1035    /// Setup directives for an assembler
1036    ///
1037    /// # Panics
1038    ///
1039    /// Panics if unable to deserialize `Directive`s
1040    pub fn setup_directives(self, names_to_directives: &mut HashMap<(Self, String), Directive>) {
1041        macro_rules! load_directives_with_path {
1042            ($assembler:expr, $path:literal) => {{
1043                let start = std::time::Instant::now();
1044                let serialized_dirs = include_bytes!($path);
1045                let directives = bincode::borrow_decode_from_slice::<Vec<Directive>, _>(serialized_dirs, BINCODE_CFG)
1046                    .unwrap_or_else(|e| panic!("Error deserializing {} directives -- {}\nRegenerate serialized data with regenerate.sh", $assembler, e))
1047                    .0;
1048
1049                info!(
1050                    "{} directive set loaded in {}ms",
1051                    $assembler,
1052                    start.elapsed().as_millis()
1053                );
1054
1055                populate_name_to_directive_map($assembler, &directives, names_to_directives);
1056            }};
1057        }
1058
1059        match self {
1060            Self::Avr => load_directives_with_path!(Self::Avr, "serialized/directives/avr"),
1061            Self::Ca65 => load_directives_with_path!(Self::Ca65, "serialized/directives/ca65"),
1062            Self::Fasm => load_directives_with_path!(Self::Fasm, "serialized/directives/fasm"),
1063            Self::Gas => load_directives_with_path!(Self::Gas, "serialized/directives/gas"),
1064            Self::Go => warn!("There is currently no Go-specific assembler documentation"),
1065            Self::Mars => load_directives_with_path!(Self::Mars, "serialized/directives/mars"),
1066            Self::Masm => load_directives_with_path!(Self::Masm, "serialized/directives/masm"),
1067            Self::Nasm => load_directives_with_path!(Self::Nasm, "serialized/directives/nasm"),
1068            Self::None => unreachable!(),
1069        }
1070    }
1071}
1072
1073#[derive(
1074    Debug,
1075    Hash,
1076    PartialEq,
1077    Eq,
1078    Clone,
1079    Copy,
1080    EnumString,
1081    AsRefStr,
1082    Display,
1083    Serialize,
1084    Deserialize,
1085    Encode,
1086    BorrowDecode,
1087)]
1088pub enum RegisterType {
1089    #[strum(serialize = "General Purpose Register")]
1090    GeneralPurpose,
1091    #[strum(serialize = "Special Purpose Register")]
1092    SpecialPurpose,
1093    #[strum(serialize = "Pointer Register")]
1094    Pointer,
1095    #[strum(serialize = "Segment Register")]
1096    Segment,
1097    #[strum(serialize = "Flag Register")]
1098    Flag,
1099    #[strum(serialize = "Control Register")]
1100    Control,
1101    #[strum(serialize = "Extended Control Register")]
1102    ExtendedControl,
1103    #[strum(serialize = "Machine State Register")]
1104    MSR,
1105    #[strum(serialize = "Debug Register")]
1106    Debug,
1107    #[strum(serialize = "Test Register")]
1108    Test,
1109    #[strum(serialize = "Protected Mode Register")]
1110    ProtectedMode,
1111    #[strum(serialize = "Floating Point Register")]
1112    FloatingPoint,
1113}
1114
1115#[derive(
1116    Debug,
1117    Hash,
1118    PartialEq,
1119    Eq,
1120    Clone,
1121    Copy,
1122    EnumString,
1123    AsRefStr,
1124    Display,
1125    Serialize,
1126    Deserialize,
1127    Encode,
1128    BorrowDecode,
1129)]
1130pub enum RegisterWidth {
1131    #[strum(serialize = "512 bits")]
1132    Bits512,
1133    #[strum(serialize = "256 bits")]
1134    Bits256,
1135    #[strum(serialize = "128 bits")]
1136    Bits128,
1137    #[strum(serialize = "32(64) bits")]
1138    Bits32Or64,
1139    #[strum(serialize = "64 bits")]
1140    Bits64,
1141    #[strum(serialize = "48 bits")]
1142    Bits48,
1143    #[strum(serialize = "32 bits")]
1144    Bits32,
1145    #[strum(serialize = "16 bits")]
1146    Bits16,
1147    #[strum(serialize = "8 bits")]
1148    Bits8,
1149    #[strum(serialize = "8 high bits of lower 16 bits")]
1150    Upper8Lower16,
1151    #[strum(serialize = "8 lower bits")]
1152    Lower8Lower16,
1153}
1154
1155#[derive(
1156    Debug, Clone, PartialEq, Eq, Hash, Serialize, Default, Deserialize, Encode, BorrowDecode,
1157)]
1158pub struct RegisterBitInfo {
1159    pub bit: u32,
1160    pub label: String,
1161    pub description: String,
1162    pub pae: String,
1163    pub long_mode: String,
1164}
1165
1166impl std::fmt::Display for RegisterBitInfo {
1167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1168        let mut s = if self.label.is_empty() {
1169            format!("{:2}: {}", self.bit, self.description)
1170        } else {
1171            format!("{:2}: {} - {}", self.bit, self.label, self.description)
1172        };
1173        if !self.pae.is_empty() {
1174            write!(s, ", PAE: {}", self.pae)?;
1175        }
1176        if !self.long_mode.is_empty() {
1177            write!(s, " , Long Mode: {}", self.long_mode)?;
1178        }
1179
1180        write!(f, "{s}")?;
1181        Ok(())
1182    }
1183}
1184
1185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1186pub struct RootConfig {
1187    pub default_config: Option<Config>,
1188    #[serde(rename = "project")]
1189    pub projects: Option<Vec<ProjectConfig>>,
1190}
1191
1192impl Default for RootConfig {
1193    fn default() -> Self {
1194        Self {
1195            default_config: Some(Config::default()),
1196            projects: None,
1197        }
1198    }
1199}
1200
1201impl RootConfig {
1202    /// Returns the `Project` associated with `uri`
1203    ///
1204    /// # Panics
1205    ///
1206    /// Will panic if `req_uri` cannot be canonicalized
1207    #[must_use]
1208    pub fn get_project<'a>(&'a self, request_path: &PathBuf) -> Option<&'a ProjectConfig> {
1209        if let Some(projects) = &self.projects {
1210            for project in projects {
1211                if (project.path.is_dir() && request_path.starts_with(&project.path))
1212                    || (project.path.is_file() && request_path.eq(&project.path))
1213                {
1214                    return Some(project);
1215                }
1216            }
1217        }
1218
1219        None
1220    }
1221
1222    /// Returns the project-specific `Config` associated with `uri`, or the default if no
1223    /// matching configuration is found
1224    ///
1225    /// # Panics
1226    ///
1227    /// Will panic if `self` does not have a valid configuration for `req_uri`, meaning
1228    /// no default config and no applicable project config
1229    pub fn get_config<'a>(&'a self, req_uri: &'a Uri) -> &'a Config {
1230        let request_path = match process_uri(req_uri) {
1231            UriConversion::Canonicalized(p) => p,
1232            UriConversion::Unchecked(p) => {
1233                warn!(
1234                    "Failed to canonicalize request path {}, using {}",
1235                    req_uri.path().as_str(),
1236                    p.display()
1237                );
1238                p
1239            }
1240        };
1241        if let Some(project) = self.get_project(&request_path) {
1242            info!(
1243                "Selected project config with path \"{}\"",
1244                project.path.display()
1245            );
1246            return &project.config;
1247        }
1248        if let Some(root) = &self.default_config {
1249            info!("Selected root config");
1250            return root;
1251        }
1252
1253        panic!(
1254            "Invalid configuration for \"{}\" -- Must contain a per-project configuration or default",
1255            req_uri.path()
1256        );
1257    }
1258
1259    /// # Panics
1260    ///
1261    /// Will panic if `self.default_config` is `None`
1262    #[must_use]
1263    pub fn effective_arches(&self) -> Vec<Arch> {
1264        let mut arch_set = HashSet::new();
1265
1266        // NOTE: `self.default_config` is assumed to be set to `Some` in
1267        // `get_root_config`
1268        assert!(self.default_config.is_some());
1269        arch_set.insert(self.default_config.as_ref().unwrap().instruction_set);
1270        if let Some(ref projects) = self.projects {
1271            for project in projects {
1272                arch_set.insert(project.config.instruction_set);
1273            }
1274        }
1275
1276        arch_set.into_iter().collect()
1277    }
1278
1279    /// # Panics
1280    ///
1281    /// Will panic if `self.default_config` is `None`
1282    #[must_use]
1283    pub fn effective_assemblers(&self) -> Vec<Assembler> {
1284        let mut assembler_set = HashSet::new();
1285
1286        // NOTE: `self.default_config` is assumed to be set to `Some` in
1287        // `get_root_config`
1288        assert!(self.default_config.is_some());
1289        assembler_set.insert(self.default_config.as_ref().unwrap().assembler);
1290        if let Some(ref projects) = self.projects {
1291            for project in projects {
1292                assembler_set.insert(project.config.assembler);
1293            }
1294        }
1295
1296        assembler_set.into_iter().collect()
1297    }
1298
1299    #[must_use]
1300    pub fn is_isa_enabled(&self, isa: Arch) -> bool {
1301        if let Some(ref root) = self.default_config
1302            && root.is_isa_enabled(isa)
1303        {
1304            return true;
1305        }
1306
1307        if let Some(ref projects) = self.projects {
1308            for project in projects {
1309                if project.config.is_isa_enabled(isa) {
1310                    return true;
1311                }
1312            }
1313        }
1314
1315        false
1316    }
1317
1318    #[must_use]
1319    pub fn is_assembler_enabled(&self, assembler: Assembler) -> bool {
1320        if let Some(ref root) = self.default_config
1321            && root.is_assembler_enabled(assembler)
1322        {
1323            return true;
1324        }
1325
1326        if let Some(ref projects) = self.projects {
1327            for project in projects {
1328                if project.config.is_assembler_enabled(assembler) {
1329                    return true;
1330                }
1331            }
1332        }
1333
1334        false
1335    }
1336}
1337
1338#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1339pub struct ProjectConfig {
1340    // Path to a directory or source file on which this config applies
1341    // Can be relative to the server's root directory, or absolute
1342    pub path: PathBuf,
1343    /// Config for this project. If `path` is a directory, applies to all files
1344    /// and subdirectories. If `path` is a file, just applies to that file
1345    #[serde(flatten)]
1346    pub config: Config,
1347}
1348
1349#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1350pub struct Config {
1351    pub version: Option<String>,
1352    pub assembler: Assembler,
1353    pub instruction_set: Arch,
1354    pub opts: Option<ConfigOptions>,
1355}
1356
1357impl Default for Config {
1358    fn default() -> Self {
1359        Self {
1360            version: None,
1361            assembler: Assembler::default(),
1362            instruction_set: Arch::default(),
1363            opts: Some(ConfigOptions::default()),
1364        }
1365    }
1366}
1367
1368impl Config {
1369    #[allow(clippy::missing_const_for_fn)]
1370    #[must_use]
1371    pub fn get_compiler(&self) -> Option<&str> {
1372        match self.opts {
1373            Some(ConfigOptions {
1374                compiler: Some(ref compiler),
1375                ..
1376            }) => Some(compiler),
1377            _ => None,
1378        }
1379    }
1380
1381    #[must_use]
1382    pub const fn get_compile_flags_txt(&self) -> Option<&Vec<String>> {
1383        match self.opts {
1384            Some(ConfigOptions {
1385                compile_flags_txt: Some(ref flags),
1386                ..
1387            }) => Some(flags),
1388            _ => None,
1389        }
1390    }
1391
1392    #[must_use]
1393    pub fn is_isa_enabled(&self, isa: Arch) -> bool {
1394        match self.instruction_set {
1395            Arch::X86_AND_X86_64 => {
1396                isa == Arch::X86 || isa == Arch::X86_64 || isa == Arch::X86_AND_X86_64
1397            }
1398            // TODO: Same treatment as above for ARM32/ARM64
1399            arch => isa == arch,
1400        }
1401    }
1402
1403    #[must_use]
1404    pub fn is_assembler_enabled(&self, assembler: Assembler) -> bool {
1405        self.assembler == assembler
1406    }
1407}
1408
1409#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1410pub struct ConfigOptions {
1411    // Specify compiler to generate diagnostics via `compile_flags.txt`
1412    pub compiler: Option<String>,
1413    // List of compile flags to override compilation behavior for this config.
1414    // Do not include the input source file as an argument
1415    // *Not* a path to `compile_flags.txt`
1416    pub compile_flags_txt: Option<Vec<String>>,
1417    // Turn diagnostics feature on/off
1418    pub diagnostics: Option<bool>,
1419    // Turn default diagnostics (no compilation db detected) on/off
1420    pub default_diagnostics: Option<bool>,
1421}
1422
1423impl Default for ConfigOptions {
1424    fn default() -> Self {
1425        Self {
1426            compiler: None,
1427            compile_flags_txt: None,
1428            diagnostics: Some(true),
1429            default_diagnostics: Some(true),
1430        }
1431    }
1432}
1433
1434// Instruction Set Architecture
1435#[derive(
1436    Debug,
1437    Copy,
1438    Clone,
1439    PartialEq,
1440    Eq,
1441    Hash,
1442    EnumString,
1443    AsRefStr,
1444    Serialize,
1445    Deserialize,
1446    Encode,
1447    BorrowDecode,
1448)]
1449pub enum ISA {
1450    #[strum(serialize = "RAO-INT")]
1451    RAOINT,
1452    GFNI,
1453    VAES,
1454    VPCLMULQDQ,
1455    RDTSC,
1456    RDTSCP,
1457    CPUID,
1458    CMOV,
1459    CMPCCXADD,
1460    CMPXCHG8B,
1461    CMPXCHG16B,
1462    #[strum(serialize = "CET-IBT")]
1463    CETIBT,
1464    MMX,
1465    #[strum(serialize = "MMX+")]
1466    MMXPlus,
1467    FEMMS,
1468    #[strum(serialize = "3dnow!")]
1469    _3DNow,
1470    #[strum(serialize = "3dnow!+")]
1471    _3DNowPlus,
1472    #[strum(serialize = "3dnow! Geode")]
1473    _3DNowGeode,
1474    SM3,
1475    SM4,
1476    SSE,
1477    SSE2,
1478    SSE3,
1479    SSSE3,
1480    #[strum(serialize = "SSE4.1")]
1481    SSE4_1, //
1482    #[strum(serialize = "SSE4.2")]
1483    SSE4_2, //
1484    SSE4A,
1485    #[strum(serialize = "AMX-TILE")]
1486    AMXTILE,
1487    #[strum(serialize = "AMX-COMPLEX")]
1488    AMXCOMPLEX,
1489    #[strum(serialize = "AMX-INT8")]
1490    AMXINT8,
1491    #[strum(serialize = "AMX-BF16")]
1492    AMXBF16,
1493    #[strum(serialize = "AMX-FP16")]
1494    AMXFP16,
1495    AVX,
1496    AVX2,
1497    XOP,
1498    FMA3,
1499    FMA4,
1500    F16C,
1501    PCLMULQDQ,
1502    AES,
1503    SHA,
1504    SHA512,
1505    RDRAND,
1506    RDSEED,
1507    RDPID,
1508    RDPMC,
1509    RDPRU,
1510    MOVBE,
1511    MOVDIRI,
1512    MOVDIR64B,
1513    POPCNT,
1514    LZCNT,
1515    BMI,
1516    BMI2,
1517    TBM,
1518    ADX,
1519    CLDEMOTE,
1520    CLFLUSH,
1521    CLFLUSHOPT,
1522    CLWB,
1523    LAHFSAHF,
1524    FSGSBASE,
1525    MCOMMIT,
1526    CLZERO,
1527    PREFETCH,
1528    PREFETCHI,
1529    PREFETCHW,
1530    PREFETCHWT1,
1531    MONITOR,
1532    MONITORX,
1533    SERIALIZE,
1534    WAITPKG,
1535    AVX512F,
1536    AVX512BW,
1537    AVX512DQ,
1538    AVX512VL,
1539    AVX512PF,
1540    AVX512ER,
1541    AVX512CD,
1542    #[strum(serialize = "AVX512-IFMA")]
1543    AVX512IFMA,
1544    #[strum(serialize = "AVX512-VPOPCNTDQ")]
1545    AVX512VPOPCNTDQ,
1546    #[strum(serialize = "AVX512-BF16")]
1547    AVX512BF16,
1548    #[strum(serialize = "AVX512-FP16")]
1549    AVX512FP16,
1550    #[strum(serialize = "AVX512-BITALG")]
1551    AVX512BITALG,
1552    #[strum(serialize = "AVX512-VBMI")]
1553    AVX512VBMI,
1554    #[strum(serialize = "AVX512-VBMI2")]
1555    AVX512VBMI2,
1556    #[strum(serialize = "AVX512-VNNI")]
1557    AVX512VNNI,
1558    #[strum(serialize = "AVX-VNNI")]
1559    AVXVNNI,
1560    #[strum(serialize = "AVX-VNNI-INT8")]
1561    AVXVNNIINT8,
1562    #[strum(serialize = "AVX-VNNI-INT16")]
1563    AVXVNNIINT16,
1564    #[strum(serialize = "AVX-NE-CONVERT")]
1565    AVXNECONVERT,
1566    #[strum(serialize = "AVX-IFMA")]
1567    AVXIFMA,
1568    // ARM
1569    A64,
1570}
1571
1572// Operand
1573#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode)]
1574pub struct Operand {
1575    pub type_: OperandType,
1576    pub input: Option<bool>,
1577    pub output: Option<bool>,
1578    pub extended_size: Option<usize>,
1579}
1580
1581#[allow(non_camel_case_types)]
1582#[derive(
1583    Debug,
1584    Clone,
1585    PartialEq,
1586    Eq,
1587    Hash,
1588    EnumString,
1589    AsRefStr,
1590    Serialize,
1591    Deserialize,
1592    Encode,
1593    BorrowDecode,
1594)]
1595pub enum OperandType {
1596    #[strum(serialize = "1")]
1597    _1,
1598    #[strum(serialize = "3")]
1599    _3,
1600    imm4,
1601    imm8,
1602    imm16,
1603    imm32,
1604    imm64,
1605    al,
1606    cl,
1607    r8,
1608    r8l,
1609    ax,
1610    r16,
1611    r16l,
1612    eax,
1613    r32,
1614    r32l,
1615    rax,
1616    r64,
1617    mm,
1618    xmm0,
1619    xmm,
1620    #[strum(serialize = "xmm{k}")]
1621    xmm_k,
1622    #[strum(serialize = "xmm{k}{z}")]
1623    xmm_k_z,
1624    ymm,
1625    #[strum(serialize = "ymm{k}")]
1626    ymm_k,
1627    #[strum(serialize = "ymm{k}{z}")]
1628    ymm_k_z,
1629    zmm,
1630    #[strum(serialize = "zmm{k}")]
1631    zmm_k,
1632    #[strum(serialize = "zmm{k}{z}")]
1633    zmm_k_z,
1634    k,
1635    #[strum(serialize = "k{k}")]
1636    k_k,
1637    moffs32,
1638    moffs64,
1639    m,
1640    m8,
1641    m16,
1642    #[strum(serialize = "m16{k}")]
1643    m16_k,
1644    #[strum(serialize = "m16{k}{z}")]
1645    m16_k_z,
1646    m32,
1647    #[strum(serialize = "m32{k}")]
1648    m32_k,
1649    #[strum(serialize = "m32{k}{z}")]
1650    m32_k_z,
1651    #[strum(serialize = "m32/m16bcst")]
1652    m32_m16bcst,
1653    m64,
1654    #[strum(serialize = "m64{k}")]
1655    m64_k,
1656    #[strum(serialize = "m64{k}{z}")]
1657    m64_k_z,
1658    #[strum(serialize = "m64/m16bcst")]
1659    m64_m16bcst,
1660    m128,
1661    #[strum(serialize = "m128{k}")]
1662    m128_k,
1663    #[strum(serialize = "m128{k}{z}")]
1664    m128_k_z,
1665    m256,
1666    #[strum(serialize = "m256{k}")]
1667    m256_k,
1668    #[strum(serialize = "m256{k}{z}")]
1669    m256_k_z,
1670    m512,
1671    #[strum(serialize = "m512{k}")]
1672    m512_k,
1673    #[strum(serialize = "m512{k}{z}")]
1674    m512_k_z,
1675    #[strum(serialize = "m64/m32bcst")]
1676    m64_m32bcst,
1677    #[strum(serialize = "m128/m32bcst")]
1678    m128_m32bcst,
1679    #[strum(serialize = "m256/m32bcst")]
1680    m256_m32bcst,
1681    #[strum(serialize = "m512/m32bcst")]
1682    m512_m32bcst,
1683    #[strum(serialize = "m128/m16bcst")]
1684    m128_m16bcst,
1685    #[strum(serialize = "m128/m64bcst")]
1686    m128_m64bcst,
1687    #[strum(serialize = "m256/m16bcst")]
1688    m256_m16bcst,
1689    #[strum(serialize = "m256/m64bcst")]
1690    m256_m64bcst,
1691    #[strum(serialize = "m512/m16bcst")]
1692    m512_m16bcst,
1693    #[strum(serialize = "m512/m64bcst")]
1694    m512_m64bcst,
1695    vm32x,
1696    #[strum(serialize = "vm32x{k}")]
1697    vm32x_k,
1698    vm64x,
1699    #[strum(serialize = "vm64x{k}")]
1700    vm64xk,
1701    vm32y,
1702    #[strum(serialize = "vm32y{k}")]
1703    vm32yk_,
1704    vm64y,
1705    #[strum(serialize = "vm64y{k}")]
1706    vm64y_k,
1707    vm32z,
1708    #[strum(serialize = "vm32z{k}")]
1709    vm32z_k,
1710    vm64z,
1711    #[strum(serialize = "vm64z{k}")]
1712    vm64z_k,
1713    rel8,
1714    rel32,
1715    rel32m,
1716    #[strum(serialize = "{er}")]
1717    er,
1718    #[strum(serialize = "{sae}")]
1719    sae,
1720    sibmem,
1721    tmm,
1722
1723    // Avr operand types
1724    Rd,
1725    Rr,
1726    X,
1727    Y,
1728    Z,
1729    #[strum(serialize = "-X")]
1730    NegX,
1731    #[strum(serialize = "-Y")]
1732    NegY,
1733    #[strum(serialize = "-Z")]
1734    NegZ,
1735    #[strum(serialize = "X+")]
1736    XPlus,
1737    #[strum(serialize = "Y+")]
1738    YPlus,
1739    #[strum(serialize = "Z+")]
1740    ZPlus,
1741    #[strum(serialize = "Y+q")]
1742    YPlusQ,
1743    #[strum(serialize = "Z+q")]
1744    ZPlusQ,
1745    A,
1746    K,
1747    // `k` is already covered
1748    s,
1749    b,
1750}
1751
1752// lsp types
1753
1754/// Represents a text cursor between characters, pointing at the next character in the buffer.
1755pub type Column = usize;
1756
1757/// Stores a tree-sitter tree and it associated parser for a given source file
1758pub struct TreeEntry {
1759    pub tree: Option<Tree>,
1760    pub parser: Parser,
1761}
1762
1763/// Associates URIs with their corresponding tree-sitter tree and parser
1764pub type TreeStore = BTreeMap<Uri, TreeEntry>;
1765
1766#[derive(Default)]
1767pub struct DocumentStore {
1768    pub tree_store: TreeStore,
1769    pub text_store: TextDocuments,
1770}
1771
1772impl DocumentStore {
1773    #[must_use]
1774    pub fn new() -> Self {
1775        Self {
1776            tree_store: TreeStore::new(),
1777            text_store: TextDocuments::new(),
1778        }
1779    }
1780}
1781
1782#[derive(Debug, Clone, Default)]
1783pub struct CompletionItems {
1784    pub instructions: Vec<(Arch, CompletionItem)>,
1785    pub registers: Vec<(Arch, CompletionItem)>,
1786    pub directives: Vec<(Assembler, CompletionItem)>,
1787}
1788
1789impl CompletionItems {
1790    #[must_use]
1791    pub const fn new() -> Self {
1792        Self {
1793            instructions: Vec::new(),
1794            registers: Vec::new(),
1795            directives: Vec::new(),
1796        }
1797    }
1798}
1799
1800/// Struct to store all documentation the server uses to service user requests
1801#[derive(Default, Debug)]
1802pub struct ServerStore {
1803    /// Links names of instructions, registers, and directives to their documentation
1804    pub names_to_info: NameToInfoMaps,
1805    /// `Completion` items for instructions, registers, and directives
1806    pub completion_items: CompletionItems,
1807    /// Compilation database loaded from `compile_commands.json` or `compile_flags.txt`
1808    pub compile_commands: CompilationDatabase,
1809    /// Include directories
1810    pub include_dirs: HashMap<SourceFile, Vec<PathBuf>>,
1811}