1use std::collections::hash_map::Entry;
2
3use crate::common::{Const, Expr, NumericRepr, Stmt, Size, Value};
4use crate::arch;
5use crate::DynasmData;
6
7pub enum Directive {
8 Arch(String),
10 Feature(Vec<String>),
12 Data(Size, Vec<Const>),
14 Byte(Expr),
16 Align {
18 value: Expr,
19 with: Option<Expr>,
20 },
21 Alias {
22 alias: String,
24 reg: String,
26 },
27 Expr(Expr),
29}
30
31pub enum MalformedDirectiveError {
32 UnknownArchitecture(String),
34
35 UnknownFeature {
37 idx: usize,
39 what: String,
41 },
42
43 DuplicateAlias {
44 reused: String,
46 },
47
48 UnknownDirective,
50}
51
52pub(crate) fn evaluate_directive(file_data: &mut DynasmData, stmts: &mut Vec<Stmt>, directive: &Directive)
53 -> Result<(), MalformedDirectiveError>
54{
55 match directive {
56 Directive::Arch(arch) => {
58 if let Some(a) = arch::from_str(&arch) {
60 file_data.current_arch = a;
61 } else {
62 return Err(MalformedDirectiveError::UnknownArchitecture(arch.to_string()));
63 }
64 },
65 Directive::Feature(features) => {
66 if features.len() == 1 && features[0] == "none" {
68 file_data.current_arch.set_features(&[]);
69 } else {
70 file_data.current_arch.set_features(features);
71 }
72 },
73 Directive::Data(size, consts) => {
75 directive_const(file_data, stmts, &consts, *size);
76 },
77 Directive::Byte(expr) => {
78 stmts.push(Stmt::ExprExtend(expr.into()));
80 },
81 Directive::Align { value, with } => {
82 let with = if let Some(with) = with {
84 Value::Expr(*with)
85 } else {
86 let with = file_data.current_arch.default_align();
87 Value::Byte(with)
88 };
89
90 stmts.push(Stmt::Align(*value, with));
91 },
92 Directive::Alias { alias, reg, } => {
93 match file_data.aliases.entry(alias.clone()) {
95 Entry::Occupied(_) => {
96 return Err(MalformedDirectiveError::DuplicateAlias {
97 reused: alias.clone(),
98 });
99 },
100 Entry::Vacant(v) => {
101 v.insert(reg.clone());
102 }
103 }
104 },
105 d => {
106 return Err(MalformedDirectiveError::UnknownDirective);
108 }
109 }
110
111 Ok(())
112}
113
114fn directive_const(file_data: &mut DynasmData, stmts: &mut Vec<Stmt>, values: &[Const], size: Size) {
115 for value in values {
116 match value {
117 Const::Relocate(jump) => {
118 file_data.current_arch.handle_static_reloc(stmts, jump.clone(), size);
119 },
120 Const::Value(mut expr) => {
121 expr.repr = NumericRepr::signed(size);
122 stmts.push(Stmt::Const(expr.into()));
123 },
124 }
125 }
126}