aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/xixanta/src/assembler.rs66
-rw-r--r--lib/xixanta/src/object.rs32
2 files changed, 67 insertions, 31 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index bdc2e9d..f63e785 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -397,6 +397,7 @@ impl<'a> Assembler<'a> {
object_type: ObjectType::Value,
asan_ignore: false,
asan_reserve: 1,
+ accessed: 0,
};
if let Err(err) = self.context.set_variable(&var_name, &var_value, false) {
@@ -504,6 +505,7 @@ impl<'a> Assembler<'a> {
object_type: ObjectType::Value,
asan_ignore: self.asan_next_ignore,
asan_reserve: self.asan_next_reserve,
+ accessed: 0,
},
false,
) {
@@ -674,6 +676,7 @@ impl<'a> Assembler<'a> {
object_type: ObjectType::Address,
asan_ignore: false,
asan_reserve: 1,
+ accessed: 0,
};
if !node.value.is_empty() {
@@ -852,31 +855,50 @@ impl<'a> Assembler<'a> {
continue;
}
+ // If it doesn't have the proper prefix, skip as well.
+ if !name.starts_with("zp_") && !name.starts_with("m_") && !name.starts_with("wr_") {
+ continue;
+ }
+
+ // Build up the memory range object for this bundle.
+ let val = bundle.bundle.value() as usize;
+ let range = MemoryRange {
+ range: (val..val + bundle.asan_reserve as usize),
+ name: name.clone(),
+ };
+
+ // Check if this variable was ever accessed and warn about
+ // it. Even if later it conflicts with another memory range, the
+ // fact that it's not used is not a danger and hence a conflict
+ // does not have to be reported. Hence, skip after issueing the
+ // warning.
+ if bundle.accessed == 0 {
+ self.warnings.push(Error {
+ line: 0,
+ message: format!("variable {range} is unused"),
+ source: self.sources[0].clone(),
+ global: true,
+ });
+ continue;
+ }
+
// Evaluate if the given object conflicts with an existing
// range.
- if name.starts_with("zp_") || name.starts_with("m_") || name.starts_with("wr_") {
- let val = bundle.bundle.value() as usize;
- let range = MemoryRange {
- range: (val..val + bundle.asan_reserve as usize),
- name: name.clone(),
- };
-
- for existing in &memory.memory_ranges {
- if (range.range.start >= existing.range.start
- && range.range.start < existing.range.end)
- || (range.range.end > existing.range.start
- && range.range.end < existing.range.end)
- {
- errors.push(Error {
- line: 0,
- global: true,
- message: format!("The variable {range} conflicts with {existing}",),
- source: self.sources[0].clone(),
- });
- }
+ for existing in &memory.memory_ranges {
+ if (range.range.start >= existing.range.start
+ && range.range.start < existing.range.end)
+ || (range.range.end > existing.range.start
+ && range.range.end < existing.range.end)
+ {
+ errors.push(Error {
+ line: 0,
+ global: true,
+ message: format!("The variable {range} conflicts with {existing}",),
+ source: self.sources[0].clone(),
+ });
}
- memory.memory_ranges.push(range);
}
+ memory.memory_ranges.push(range);
// Increase the counters for memory usage on either RAM slot and
// check for bounds.
@@ -1041,6 +1063,7 @@ impl<'a> Assembler<'a> {
object_type: ObjectType::Value,
asan_ignore: false,
asan_reserve: 1,
+ accessed: 0,
};
// Note that we overwrite the variable value from previous
@@ -1841,6 +1864,7 @@ impl<'a> Assembler<'a> {
asan_ignore: false,
object_type: ObjectType::Value,
asan_reserve: 1,
+ accessed: 0,
},
true,
) {
diff --git a/lib/xixanta/src/object.rs b/lib/xixanta/src/object.rs
index 920a4f8..049798f 100644
--- a/lib/xixanta/src/object.rs
+++ b/lib/xixanta/src/object.rs
@@ -139,6 +139,9 @@ pub struct Object {
/// Amount of bytes reserved for this object on the address sanitizer.
pub asan_reserve: u8,
+
+ /// Number of times this object was accessed. Incremented by `get_variable`.
+ pub accessed: usize,
}
impl Object {
@@ -152,6 +155,7 @@ impl Object {
object_type,
asan_ignore: false,
asan_reserve: 1,
+ accessed: 0,
}
}
}
@@ -198,7 +202,7 @@ impl Context {
/// this `id` can be scoped or not, and this function will try to pick the
/// variable from the right scope. The value itself will be resolved if the
/// type is ObjectType::Address.
- pub fn get_variable(&self, id: &PString, mappings: &[Mapping]) -> Result<Object, String> {
+ pub fn get_variable(&mut self, id: &PString, mappings: &[Mapping]) -> Result<Object, String> {
// First of all, figure out the name of the scope and the real name of
// the variable. If this was not scoped at all (None case when trying to
// rsplit by the "::" operator), then we assume on the current scope.
@@ -207,25 +211,32 @@ impl Context {
None => (self.name(), id.value.as_str()),
};
- self.get_variable_in_scope(scope_name, var_name, mappings)
+ let scope_name_obj = scope_name.to_string();
+ self.get_variable_in_scope(&scope_name_obj, var_name, mappings)
}
// Get the `var_name` variable on the `scope_name` scope (or parents). For
// further context, take the `mappings` into consideration when resolving
// labels, and `line` when producing context errors.
fn get_variable_in_scope(
- &self,
- scope_name: &str,
+ &mut self,
+ scope_name: &String,
var_name: &str,
mappings: &[Mapping],
) -> Result<Object, String> {
// And with that, the only thing left is to find the scope and the
// variable in it.
- match self.map.get(scope_name) {
- Some(scope) => match scope.get(var_name) {
+ match self.map.get_mut(scope_name) {
+ Some(scope) => match scope.get_mut(var_name) {
Some(var) => match var.object_type {
- ObjectType::Value => Ok(var.clone()),
- ObjectType::Address => Ok(self.resolve_label(mappings, var)?),
+ ObjectType::Value => {
+ var.accessed += 1;
+ Ok(var.clone())
+ }
+ ObjectType::Address => {
+ let var_to_resolve = var.clone();
+ Ok(self.resolve_label(mappings, &var_to_resolve)?)
+ }
},
None => {
// If it cannot be found, then we have to move up through
@@ -248,8 +259,9 @@ impl Context {
// error from the recursive call, preserve the original
// error so it better reflects the original scope where
// this was first attempted.
- let parent = self.parent(scope_name);
- if let Ok(object) = self.get_variable_in_scope(parent, var_name, mappings) {
+ let parent = self.parent(scope_name).to_string();
+ if let Ok(object) = self.get_variable_in_scope(&parent, var_name, mappings)
+ {
Ok(object)
} else {
err