summaryrefslogtreecommitdiffstats
path: root/third_party/rust/naga/src/proc/namer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/naga/src/proc/namer.rs')
-rw-r--r--third_party/rust/naga/src/proc/namer.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/third_party/rust/naga/src/proc/namer.rs b/third_party/rust/naga/src/proc/namer.rs
new file mode 100644
index 0000000000..03b508904b
--- /dev/null
+++ b/third_party/rust/naga/src/proc/namer.rs
@@ -0,0 +1,113 @@
+use crate::{arena::Handle, FastHashMap};
+use std::collections::hash_map::Entry;
+
+pub type EntryPointIndex = u16;
+
+#[derive(Debug, Eq, Hash, PartialEq)]
+pub enum NameKey {
+ GlobalVariable(Handle<crate::GlobalVariable>),
+ Type(Handle<crate::Type>),
+ StructMember(Handle<crate::Type>, u32),
+ Function(Handle<crate::Function>),
+ FunctionArgument(Handle<crate::Function>, u32),
+ FunctionLocal(Handle<crate::Function>, Handle<crate::LocalVariable>),
+ EntryPoint(EntryPointIndex),
+ EntryPointLocal(EntryPointIndex, Handle<crate::LocalVariable>),
+}
+
+/// This processor assigns names to all the things in a module
+/// that may need identifiers in a textual backend.
+pub struct Namer {
+ unique: FastHashMap<String, u32>,
+}
+
+impl Namer {
+ fn sanitize(string: &str) -> String {
+ let mut base = string
+ .chars()
+ .skip_while(|c| c.is_numeric())
+ .filter(|&c| c.is_ascii_alphanumeric() || c == '_')
+ .collect::<String>();
+ // close the name by '_' if the re is a number, so that
+ // we can have our own number!
+ match base.chars().next_back() {
+ Some(c) if !c.is_numeric() => {}
+ _ => base.push('_'),
+ };
+ base
+ }
+
+ fn call(&mut self, label_raw: &str) -> String {
+ let base = Self::sanitize(label_raw);
+ match self.unique.entry(base) {
+ Entry::Occupied(mut e) => {
+ *e.get_mut() += 1;
+ format!("{}{}", e.key(), e.get())
+ }
+ Entry::Vacant(e) => {
+ let name = e.key().to_string();
+ e.insert(0);
+ name
+ }
+ }
+ }
+
+ fn call_or(&mut self, label: &Option<String>, fallback: &str) -> String {
+ self.call(match *label {
+ Some(ref name) => name,
+ None => fallback,
+ })
+ }
+
+ pub fn process(
+ module: &crate::Module,
+ reserved: &[&str],
+ output: &mut FastHashMap<NameKey, String>,
+ ) {
+ let mut this = Namer {
+ unique: reserved
+ .iter()
+ .map(|string| (string.to_string(), 0))
+ .collect(),
+ };
+
+ for (handle, var) in module.global_variables.iter() {
+ let name = this.call_or(&var.name, "global");
+ output.insert(NameKey::GlobalVariable(handle), name);
+ }
+
+ for (ty_handle, ty) in module.types.iter() {
+ let ty_name = this.call_or(&ty.name, "type");
+ output.insert(NameKey::Type(ty_handle), ty_name);
+
+ if let crate::TypeInner::Struct { ref members } = ty.inner {
+ for (index, member) in members.iter().enumerate() {
+ let name = this.call_or(&member.name, "member");
+ output.insert(NameKey::StructMember(ty_handle, index as u32), name);
+ }
+ }
+ }
+
+ for (fun_handle, fun) in module.functions.iter() {
+ let fun_name = this.call_or(&fun.name, "function");
+ output.insert(NameKey::Function(fun_handle), fun_name);
+ for (index, arg) in fun.arguments.iter().enumerate() {
+ let name = this.call_or(&arg.name, "param");
+ output.insert(NameKey::FunctionArgument(fun_handle, index as u32), name);
+ }
+ for (handle, var) in fun.local_variables.iter() {
+ let name = this.call_or(&var.name, "local");
+ output.insert(NameKey::FunctionLocal(fun_handle, handle), name);
+ }
+ }
+
+ for (ep_index, (&(_, ref base_name), ep)) in module.entry_points.iter().enumerate() {
+ let ep_name = this.call(base_name);
+ output.insert(NameKey::EntryPoint(ep_index as _), ep_name);
+ for (handle, var) in ep.function.local_variables.iter() {
+ let name = this.call_or(&var.name, "local");
+ output.insert(NameKey::EntryPointLocal(ep_index as _, handle), name);
+ }
+ }
+ }
+}