#Name mangling
Linker will mangle names internally, but we’re hoping to keep the mangling details out of the public api.
See also renaming host visible names in Visibility.
(TBD)
- Extend scheme to support generics.
- Can we find an explicit naming scheme where packages specify names for their host exposed WESL parts
rather than publishing automatically mangled names?
- e.g.
@publicName("mypkg_util_bar") @compute fn compute_shader() {}
- that way the host code doesn’t need to change if the WESL file structure is refactored.
- e.g.
#What gets mangled
All declaration identifiers get mangled, except:
- root module declarations (this is being discussed, see https://github.com/wgsl-tooling-wg/wesl-js/issues/98)
- declarations imported in the root module
- if the import renames the declaration (using the
import foo as bar
syntax), the declaration is renamed. - if the import is a module (
import some::module
wheresome/module.wesl
exists) it does not affect mangling.
- if the import renames the declaration (using the
#Mangling
To join multiple modules into one, we need to make sure that names do not collide. This is done by name mangling.
Mangling is the process of renaming a declaration and its references to avoid name collisions. It is not easy: because of name shadowing, local-scope declarations can have the same name as module-scope ones. To rename all references to a declaration, one has to walk the syntax tree while keeping track of the scope (list of local declarations).
Compiled WGSL files have a few exposed parts, namely the names of the entry functions and pipeline overridable constants (together called “host-visible names”).
#Underscore-count mangling
For sharing tests, we need a stable and predictable scheme. This one is also reversible and human-readable.
For name mangling, we introduce the concept of a fully qualified path.
This is the absolute path to the module, plus the item. e.g. bevy_pbr::lighting::main
_
is the path separator- Split into segments (
bevy_pbr
,lighting
,main
) - If a segment contains
_
, prefix it with_n
wheren
the number of underscores it contains. (_1bevy_pbr
,lighting
,main
) - The result is joined with
_
. (_1bevy_pbr_lighting_main
)
#Only-conflict mangling
A simple mangling strategy is
- load everything in a predictable order
- when emitting, keep track of which identifier names have already been used at the global scope
- if one identifier name is used twice, give the second one a name with an incrementing number appended to it
This strategy is very human readable, but cannot be unmangled, since information is lost. For reproducible builds: It relies on the linker assigning these names in a predictable order. This could be violated by hashmaps, async code or incremental re-compilation, so special care must be taken.