aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/xixanta/src/assembler.rs42
1 files changed, 38 insertions, 4 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index d624c7e..1b963f2 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -58,6 +58,15 @@ struct PendingNode {
node: PNode,
labels_seen: usize,
macro_context: Vec<ExpandedFrom>,
+ pending_defines: Option<Vec<PendingDefine>>,
+}
+
+/// A definition that is pending to be re-created whenever we crunch for
+/// PendingNode's.
+#[derive(Clone, Debug)]
+struct PendingDefine {
+ id: PString,
+ obj: Object,
}
/// Memory range that can be identified by a name.
@@ -143,6 +152,10 @@ struct Assembler<'a> {
// 'Error' so the programmer gets information on all the macro expansions
// that happened before reaching a given error.
macro_context: Vec<ExpandedFrom>,
+
+ // Stack of pending definitions. The last element from this list is the list
+ // to be set to the next PendingNode push.
+ pending_defines: Vec<Vec<PendingDefine>>,
}
/// The result to be given at the end of `assembler::assemble` and
@@ -382,6 +395,7 @@ impl<'a> Assembler<'a> {
asan_next_ignore: false,
asan_next_reserve: 1,
macro_context: vec![],
+ pending_defines: vec![],
}
}
@@ -906,6 +920,7 @@ impl<'a> Assembler<'a> {
node: node.to_owned(),
labels_seen: self.context.labels_seen(),
macro_context: self.macro_context.clone(),
+ pending_defines: self.pending_defines.last().cloned(),
});
}
_ => {}
@@ -949,6 +964,14 @@ impl<'a> Assembler<'a> {
continue;
}
+ // Re-create the definitions for this context which only made sense
+ // locally. These are basically arguments from a macro call.
+ if let Some(pd) = &pn.pending_defines {
+ for d in pd {
+ let _ = self.context.set_variable(&d.id, &d.obj, true);
+ }
+ }
+
self.literal_mode = None;
match self.evaluate_node(&pn.node) {
Ok(mut bundle) => {
@@ -1302,6 +1325,12 @@ impl<'a> Assembler<'a> {
.into());
}
+ // All arguments are going to be added here as well so the inner block
+ // can take it as a list of PendingDefine's. This way we can re-create
+ // the values for the arguments used for this bundle call without having
+ // to go over the full bundle call.
+ let mut defines = vec![];
+
// If there are arguments defined by the macro, set their values now.
if given_args > 0 {
let mut margs = mcr.args.as_ref().unwrap().iter();
@@ -1322,10 +1351,8 @@ impl<'a> Assembler<'a> {
// Note that we overwrite the variable value from previous
// calls, just in case a macro is applied multiple times and we
// need to get the latest value.
- if let Err(message) =
- self.context
- .set_variable(&margs.next().unwrap().value, &obj, true)
- {
+ let id = &margs.next().unwrap().value;
+ if let Err(message) = self.context.set_variable(id, &obj, true) {
return Err(Error {
line: node.value.line,
message,
@@ -1335,6 +1362,10 @@ impl<'a> Assembler<'a> {
}
.into());
}
+ defines.push(PendingDefine {
+ id: id.clone(),
+ obj,
+ });
}
}
@@ -1358,7 +1389,9 @@ impl<'a> Assembler<'a> {
line: node.value.line,
source: self.source_for(node),
});
+ self.pending_defines.push(defines);
self.bundle(inner)?;
+ self.pending_defines.pop();
let _ = self.macro_context.pop();
}
Ok(())
@@ -1379,6 +1412,7 @@ impl<'a> Assembler<'a> {
node: node.to_owned(),
labels_seen: self.context.labels_seen(),
macro_context: self.macro_context.clone(),
+ pending_defines: self.pending_defines.last().cloned(),
});
}
current.segments[self.current_segment].bundles.push(bundle);