diff --git a/etk-asm/src/asm.rs b/etk-asm/src/asm.rs index d74e39d7..195ee683 100644 --- a/etk-asm/src/asm.rs +++ b/etk-asm/src/asm.rs @@ -223,89 +223,21 @@ impl Assembler { Self::default() } - /// Backpatch dynamic operations and emit the assembled program. + /// Feed instructions into the `Assembler`. /// - /// Errors if there are any undeclared labels. - fn backpatch_and_emit(&mut self) -> Result, Error> { - if !self.undeclared_labels.is_empty() { - return error::UndeclaredLabels { - labels: self - .undeclared_labels - .iter() - .map(|l| l.to_owned()) - .collect::>(), - } - .fail(); - } - let mut output = Vec::new(); - for op in self.ready.iter() { - if let RawOp::Op(ref op) = op { - match op - .clone() - .concretize((&self.declared_labels, &self.declared_macros).into()) - { - Ok(mut cop) => { - if let AbstractOp::Push(imm) = op { - let exp = imm.tree.eval_with_context( - (&self.declared_labels, &self.declared_macros).into(), - ); - - let labels: HashSet = imm - .tree - .labels(&self.declared_macros) - .unwrap() - .into_iter() - .collect(); - if !labels.is_empty() { - if let Ok(val) = exp { - let extra = val.to_usize().unwrap() / 256; - if extra > 0 { - self.concrete_len += extra; - - for label in labels { - if let Some(position) = - self.declared_labels.get_mut(&label) - { - *position = position.map(|v| v + 1); - } - } - } - } - } - - cop = op - .clone() - .concretize((&self.declared_labels, &self.declared_macros).into()) - .unwrap(); - } - cop.assemble(&mut output) - } - Err(ops::Error::ContextIncomplete { - source: UnknownLabel { .. }, - }) => { - return error::UndeclaredLabels { - labels: self.undeclared_labels.to_vec(), - } - .fail(); - } - Err(ops::Error::ContextIncomplete { - source: UnknownMacro { name, .. }, - }) => { - return error::UndeclaredInstructionMacro { name }.fail(); - } - Err(ops::Error::ContextIncomplete { - source: UndefinedVariable { name, .. }, - }) => { - return error::UndeclaredVariableMacro { var: name }.fail(); - } + /// Returns the code of the assembled program. + pub fn assemble(&mut self, ops: &[O]) -> Result, Error> + where + O: Into + Clone, + { + self.declare_macros(ops)?; - Err(_) => unreachable!("all ops should be concretizable"), - } - } else if let RawOp::Raw(raw) = op { - output.extend(raw); - } + for op in ops { + self.push(op.clone().into())?; } + let output = self.backpatch_and_emit()?; + self.ready.clear(); Ok(output) } @@ -333,24 +265,6 @@ impl Assembler { Ok(()) } - /// Feed instructions into the `Assembler`. - /// - /// Returns the code of the assembled program. - pub fn assemble(&mut self, ops: &[O]) -> Result, Error> - where - O: Into + Clone, - { - self.declare_macros(ops)?; - - for op in ops { - self.push(op.clone().into())?; - } - - let output = self.backpatch_and_emit()?; - self.ready.clear(); - Ok(output) - } - /// Feed a single instruction into the `Assembler`. fn push(&mut self, rop: O) -> Result where @@ -432,6 +346,92 @@ impl Assembler { Ok(self.concrete_len) } + /// Backpatch dynamic operations and emit the assembled program. + /// + /// Errors if there are any undeclared labels. + fn backpatch_and_emit(&mut self) -> Result, Error> { + if !self.undeclared_labels.is_empty() { + return error::UndeclaredLabels { + labels: self + .undeclared_labels + .iter() + .map(|l| l.to_owned()) + .collect::>(), + } + .fail(); + } + let mut output = Vec::new(); + for op in self.ready.iter() { + if let RawOp::Op(ref op) = op { + match op + .clone() + .concretize((&self.declared_labels, &self.declared_macros).into()) + { + Ok(mut cop) => { + if let AbstractOp::Push(imm) = op { + let exp = imm.tree.eval_with_context( + (&self.declared_labels, &self.declared_macros).into(), + ); + + let labels: HashSet = imm + .tree + .labels(&self.declared_macros) + .unwrap() + .into_iter() + .collect(); + if !labels.is_empty() { + if let Ok(val) = exp { + let extra = val.to_usize().unwrap() / 256; + if extra > 0 { + self.concrete_len += extra; + + for label in labels { + if let Some(position) = + self.declared_labels.get_mut(&label) + { + *position = position.map(|v| v + 1); + } + } + } + } + } + + cop = op + .clone() + .concretize((&self.declared_labels, &self.declared_macros).into()) + .unwrap(); + } + cop.assemble(&mut output) + } + Err(ops::Error::ContextIncomplete { + source: UnknownLabel { .. }, + }) => { + return error::UndeclaredLabels { + labels: self.undeclared_labels.to_vec(), + } + .fail(); + } + Err(ops::Error::ContextIncomplete { + source: UnknownMacro { name, .. }, + }) => { + return error::UndeclaredInstructionMacro { name }.fail(); + } + Err(ops::Error::ContextIncomplete { + source: UndefinedVariable { name, .. }, + }) => { + return error::UndeclaredVariableMacro { var: name }.fail(); + } + + Err(_) => unreachable!("all ops should be concretizable"), + } + } else if let RawOp::Raw(raw) = op { + output.extend(raw); + } + } + + Ok(output) + } + fn declare_label(&mut self, rop: &RawOp) -> Result<(), Error> { if let RawOp::Op(AbstractOp::Label(label)) = rop { if self.declared_labels.contains_key(label) {