Download Summary

Transcript
Tools and Design
char buffer [40];
// code to create our string in our own buffer
hasComma(buffer); // C++ compiler is forced to create a new
string object, duplicating the buffer
hasComma("hello, world!"); // Likewise
}
Notice that every time we try to create a string in our own buffer, we will spend an
extra heap allocation to copy this string to the internal buffer of the string object,
which must own its buffer. In the first case, we have a stack-allocated string while
in the second case, the string is held as a global constant. What C++ is missing, for
these cases, is a simple class that avoids unnecessary allocations when we only
need a reference to a string. Even if we work strictly with string objects, saving
unnecessary heap allocations, a reference to a string object imposes two indirections.
Since the string class already works with an internal pointer to hold its data,
passing a pointer to a string object introduces the overhead of a double reference
when we access the actual data.
We can make this more efficient with an LLVM class to work with string references:
StringRef. This is a lightweight class that can be passed by value in the same way
as const char*, but it also stores the size of the string, allowing null characters.
However, contrary to string objects, it does not own the buffer and, thus, never
allocates heap space but merely refers to a string that lives outside it. This concept is
also explored in other C++ projects: Chromium, for instance, uses the StringPiece
class to implement the same idea.
LLVM also introduces yet another string-manipulation class. To build a new
string out of several concatenations, LLVM provides the Twine class. It defers
the actual concatenation by storing only references to the strings that will compose
the final product. This was created in the pre-C++11 era when string concatenation
was expensive.
If you are interested in finding out about other generic classes that LLVM provides
to help its programmers, a very important document you should keep in your
bookmarks is the LLVM Programmer's Manual, which discusses all LLVM generic
data structures that might be useful for any code. The manual is located at
http://llvm.org/docs/ProgrammersManual.html.
Demonstrating the pluggable pass interface
A pass is a transformation analysis or optimization. LLVM APIs allow you to easily
register any pass during different parts of the program compilation lifetime, which is
an appreciated point of the LLVM design. A pass manager is used to register, schedule,
and declare dependencies between passes. Hence, instances of the PassManager class
are available throughout different compiler stages.
[ 62 ]