Learn C++ Itanium Symbol Mangling

Lesson 3: Basic Templates

In this lesson we will look at C++'s most important features and another big motivation of why symbol mangling exists and is as complicated as it is: templates.

If you're not familiar with templates already, templates provide a way to write a function that is generic over a type (or value, which we will get to later). It can then be instantiated with different types and change its behavior depending on which type it was instantiated with.

template<typename T>
void empty(T a) {}
          

Here we create an empty function that takes an argument of type T, where T is a template parameter. We can call empty with all sorts of types.

int main() {
  empty(0);   // T=int
  empty("0"); // T=const char*
  empty(0l);  // T=long
}
          

For every call with a unique type, the compiler will essentially copy-paste the function and fill in the concrete template. So for every different type, there's a different instantiation. The symbol mangling scheme must ensure that different instantiations get different symbols, otherwise we coul get conflicts between different instantiations. This is achieved by encoding the template parameters into the symbol.

The way this is handled is by wrapping all the arguments between a I (you can remember it as "instantiation") and E (end) and appending this to the name, before the type of the function.

We will also learn about a new type, the template parameter type, used to encode the parameter of the example function above. Template parameter types are not encoded as their instantiated types, but as a "parameter type". The first template parameter type is denoted with a T followed by an underscore.

One last thing: templated functions include the return type as the first type in the argument list.

With this, our example instantiation below will have the following mangled symbol: _Z5emptyIiEvT_.

template<typename T>
void empty(T a) {}
int main() {
  empty(0);   // T=int
}
          
  • _Z5empty: prefix and function name
  • I: start of template arguments
  • i: template argument of type int
  • E: end of template arguments
  • v: return type of the function, void
  • T_: first argument of the function, the first template parameter (which is instanitated as int, but that isn't stored in the symbol for efficiency)

What is the mangled symbol of the following instantiation of empty?

template<typename T>
T empty() {}
int main() {
  empty<long>(); // T=long
}
            

This lesson is still work in progress, further steps will follow in the future.