sleigh_compiler/
compiler.rs1use std::{collections::BTreeMap, path::Path};
2
3use crate::ffi::sys::{self, PreprocessorDefine};
4use cxx::UniquePtr;
5
6pub type SleighCompilerResponse = sys::CompileResponse;
7
8#[derive(thiserror::Error, Debug)]
9pub enum Error {
10 #[error("non-zero exit code: {exit_code}", exit_code = .0.exit_code)]
11 NonZeroExitCode(SleighCompilerResponse),
12
13 #[error("internal compiler error: {0}")]
14 InternalCompilerError(Box<dyn std::error::Error + Send + Sync>),
15}
16
17pub type Result<T> = std::result::Result<T, Error>;
18
19pub struct SleighCompiler {
21 compiler: UniquePtr<sys::SleighCompileProxy>,
22}
23
24pub struct SleighCompilerOptions {
26 pub defines: BTreeMap<String, String>,
28
29 pub unnecessary_pcode_warnings: bool,
31
32 pub lenient_conflict: bool,
34
35 pub all_collision_warning: bool,
37
38 pub all_nop_warning: bool,
40
41 pub dead_temp_warning: bool,
43
44 pub enforce_local_keyword: bool,
46
47 pub large_temporary_warning: bool,
49
50 pub case_sensitive_register_names: bool,
52
53 pub debug_output: bool,
55}
56
57impl Default for SleighCompilerOptions {
58 fn default() -> Self {
59 Self {
61 defines: Default::default(),
62 unnecessary_pcode_warnings: false,
63 lenient_conflict: true,
64 all_collision_warning: false,
65 all_nop_warning: false,
66 dead_temp_warning: false,
67 enforce_local_keyword: false,
68 large_temporary_warning: false,
69 case_sensitive_register_names: false,
70 debug_output: false,
71 }
72 }
73}
74
75impl SleighCompiler {
76 pub fn new(options: SleighCompilerOptions) -> Self {
79 let mut compiler = sys::new_sleigh_compiler();
80
81 let mut defines = cxx::CxxVector::new();
82 for (name, value) in options.defines {
83 defines.pin_mut().push(PreprocessorDefine { name, value });
84 }
85
86 compiler.pin_mut().set_all_options(
87 defines.as_ref().unwrap(),
88 options.unnecessary_pcode_warnings,
89 options.lenient_conflict,
90 options.all_collision_warning,
91 options.all_nop_warning,
92 options.dead_temp_warning,
93 options.enforce_local_keyword,
94 options.large_temporary_warning,
95 options.case_sensitive_register_names,
96 options.debug_output,
97 );
98
99 Self { compiler }
100 }
101
102 pub fn compile(
106 &mut self,
107 input_slaspec_path: impl AsRef<Path>,
108 output_sla_path: impl AsRef<Path>,
109 ) -> Result<SleighCompilerResponse> {
110 cxx::let_cxx_string!(filein = input_slaspec_path.as_ref().as_os_str().as_encoded_bytes());
111 cxx::let_cxx_string!(fileout = output_sla_path.as_ref().as_os_str().as_encoded_bytes());
112
113 let response = self
114 .compiler
115 .pin_mut()
116 .run_compilation(filein.as_ref(), fileout.as_ref())
117 .map_err(|err| Error::InternalCompilerError(Box::new(err)))?;
118
119 if response.exit_code == 0 {
120 Ok(response)
121 } else {
122 Err(Error::NonZeroExitCode(response))
123 }
124 }
125}
126
127impl Default for SleighCompiler {
128 fn default() -> Self {
129 Self::new(SleighCompilerOptions::default())
130 }
131}