summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/docs/ProgrammersManual.rst
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
committerpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
commit53d771aafdbe5b919f264f53cba3788e2c4cffd2 (patch)
tree7eca39498be0ff1e3a6daf583cd9ca5886bb2636 /gnu/llvm/docs/ProgrammersManual.rst
parentIn preparation of compiling our kernels with -ffreestanding, explicitly map (diff)
downloadwireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.tar.xz
wireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.zip
Import LLVM 4.0.0 rc1 including clang and lld to help the current
development effort on OpenBSD/arm64.
Diffstat (limited to 'gnu/llvm/docs/ProgrammersManual.rst')
-rw-r--r--gnu/llvm/docs/ProgrammersManual.rst583
1 files changed, 525 insertions, 58 deletions
diff --git a/gnu/llvm/docs/ProgrammersManual.rst b/gnu/llvm/docs/ProgrammersManual.rst
index 030637048bf..ffc022eef16 100644
--- a/gnu/llvm/docs/ProgrammersManual.rst
+++ b/gnu/llvm/docs/ProgrammersManual.rst
@@ -149,7 +149,7 @@ rarely have to include this file directly).
.. code-block:: c++
- if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) {
+ if (auto *AI = dyn_cast<AllocationInst>(Val)) {
// ...
}
@@ -263,6 +263,134 @@ almost never be stored or mentioned directly. They are intended solely for use
when defining a function which should be able to efficiently accept concatenated
strings.
+.. _formatting_strings:
+
+Formatting strings (the ``formatv`` function)
+---------------------------------------------
+While LLVM doesn't necessarily do a lot of string manipulation and parsing, it
+does do a lot of string formatting. From diagnostic messages, to llvm tool
+outputs such as ``llvm-readobj`` to printing verbose disassembly listings and
+LLDB runtime logging, the need for string formatting is pervasive.
+
+The ``formatv`` is similar in spirit to ``printf``, but uses a different syntax
+which borrows heavily from Python and C#. Unlike ``printf`` it deduces the type
+to be formatted at compile time, so it does not need a format specifier such as
+``%d``. This reduces the mental overhead of trying to construct portable format
+strings, especially for platform-specific types like ``size_t`` or pointer types.
+Unlike both ``printf`` and Python, it additionally fails to compile if LLVM does
+not know how to format the type. These two properties ensure that the function
+is both safer and simpler to use than traditional formatting methods such as
+the ``printf`` family of functions.
+
+Simple formatting
+^^^^^^^^^^^^^^^^^
+
+A call to ``formatv`` involves a single **format string** consisting of 0 or more
+**replacement sequences**, followed by a variable length list of **replacement values**.
+A replacement sequence is a string of the form ``{N[[,align]:style]}``.
+
+``N`` refers to the 0-based index of the argument from the list of replacement
+values. Note that this means it is possible to reference the same parameter
+multiple times, possibly with different style and/or alignment options, in any order.
+
+``align`` is an optional string specifying the width of the field to format
+the value into, and the alignment of the value within the field. It is specified as
+an optional **alignment style** followed by a positive integral **field width**. The
+alignment style can be one of the characters ``-`` (left align), ``=`` (center align),
+or ``+`` (right align). The default is right aligned.
+
+``style`` is an optional string consisting of a type specific that controls the
+formatting of the value. For example, to format a floating point value as a percentage,
+you can use the style option ``P``.
+
+Custom formatting
+^^^^^^^^^^^^^^^^^
+
+There are two ways to customize the formatting behavior for a type.
+
+1. Provide a template specialization of ``llvm::format_provider<T>`` for your
+ type ``T`` with the appropriate static format method.
+
+ .. code-block:: c++
+
+ namespace llvm {
+ template<>
+ struct format_provider<MyFooBar> {
+ static void format(const MyFooBar &V, raw_ostream &Stream, StringRef Style) {
+ // Do whatever is necessary to format `V` into `Stream`
+ }
+ };
+ void foo() {
+ MyFooBar X;
+ std::string S = formatv("{0}", X);
+ }
+ }
+
+ This is a useful extensibility mechanism for adding support for formatting your own
+ custom types with your own custom Style options. But it does not help when you want
+ to extend the mechanism for formatting a type that the library already knows how to
+ format. For that, we need something else.
+
+2. Provide a **format adapter** inheriting from ``llvm::FormatAdapter<T>``.
+
+ .. code-block:: c++
+
+ namespace anything {
+ struct format_int_custom : public llvm::FormatAdapter<int> {
+ explicit format_int_custom(int N) : llvm::FormatAdapter<int>(N) {}
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
+ // Do whatever is necessary to format ``this->Item`` into ``Stream``
+ }
+ };
+ }
+ namespace llvm {
+ void foo() {
+ std::string S = formatv("{0}", anything::format_int_custom(42));
+ }
+ }
+
+ If the type is detected to be derived from ``FormatAdapter<T>``, ``formatv``
+ will call the
+ ``format`` method on the argument passing in the specified style. This allows
+ one to provide custom formatting of any type, including one which already has
+ a builtin format provider.
+
+``formatv`` Examples
+^^^^^^^^^^^^^^^^^^^^
+Below is intended to provide an incomplete set of examples demonstrating
+the usage of ``formatv``. More information can be found by reading the
+doxygen documentation or by looking at the unit test suite.
+
+
+.. code-block:: c++
+
+ std::string S;
+ // Simple formatting of basic types and implicit string conversion.
+ S = formatv("{0} ({1:P})", 7, 0.35); // S == "7 (35.00%)"
+
+ // Out-of-order referencing and multi-referencing
+ outs() << formatv("{0} {2} {1} {0}", 1, "test", 3); // prints "1 3 test 1"
+
+ // Left, right, and center alignment
+ S = formatv("{0,7}", 'a'); // S == " a";
+ S = formatv("{0,-7}", 'a'); // S == "a ";
+ S = formatv("{0,=7}", 'a'); // S == " a ";
+ S = formatv("{0,+7}", 'a'); // S == " a";
+
+ // Custom styles
+ S = formatv("{0:N} - {0:x} - {1:E}", 12345, 123908342); // S == "12,345 - 0x3039 - 1.24E8"
+
+ // Adapters
+ S = formatv("{0}", fmt_align(42, AlignStyle::Center, 7)); // S == " 42 "
+ S = formatv("{0}", fmt_repeat("hi", 3)); // S == "hihihi"
+ S = formatv("{0}", fmt_pad("hi", 2, 6)); // S == " hi "
+
+ // Ranges
+ std::vector<int> V = {8, 9, 10};
+ S = formatv("{0}", make_range(V.begin(), V.end())); // S == "8, 9, 10"
+ S = formatv("{0:$[+]}", make_range(V.begin(), V.end())); // S == "8+9+10"
+ S = formatv("{0:$[ + ]@[x]}", make_range(V.begin(), V.end())); // S == "0x8 + 0x9 + 0xA"
+
.. _error_apis:
Error handling
@@ -320,7 +448,7 @@ actually a lightweight wrapper for user-defined error types, allowing arbitrary
information to be attached to describe the error. This is similar to the way C++
exceptions allow throwing of user-defined types.
-Success values are created by calling ``Error::success()``:
+Success values are created by calling ``Error::success()``, E.g.:
.. code-block:: c++
@@ -334,28 +462,32 @@ Success values are very cheap to construct and return - they have minimal
impact on program performance.
Failure values are constructed using ``make_error<T>``, where ``T`` is any class
-that inherits from the ErrorInfo utility:
+that inherits from the ErrorInfo utility, E.g.:
.. code-block:: c++
- class MyError : public ErrorInfo<MyError> {
+ class BadFileFormat : public ErrorInfo<BadFileFormat> {
public:
- MyError(std::string Msg) : Msg(Msg) {}
- void log(OStream &OS) const override { OS << "MyError - " << Msg; }
static char ID;
- private:
- std::string Msg;
- };
+ std::string Path;
- char MyError::ID = 0; // In MyError.cpp
+ BadFileFormat(StringRef Path) : Path(Path.str()) {}
+
+ void log(raw_ostream &OS) const override {
+ OS << Path << " is malformed";
+ }
- Error bar() {
- if (checkErrorCondition)
- return make_error<MyError>("Error condition detected");
+ std::error_code convertToErrorCode() const override {
+ return make_error_code(object_error::parse_failed);
+ }
+ };
- // No error - proceed with bar.
+ char FileExists::ID; // This should be declared in the C++ file.
- // Return success value.
+ Error printFormattedFile(StringRef Path) {
+ if (<check for valid format>)
+ return make_error<InvalidObjectFile>(Path);
+ // print file contents.
return Error::success();
}
@@ -374,35 +506,58 @@ success, enabling the following idiom:
For functions that can fail but need to return a value the ``Expected<T>``
utility can be used. Values of this type can be constructed with either a
-``T``, or a ``Error``. Expected<T> values are also implicitly convertible to
-boolean, but with the opposite convention to Error: true for success, false for
-error. If success, the ``T`` value can be accessed via the dereference operator.
-If failure, the ``Error`` value can be extracted using the ``takeError()``
-method. Idiomatic usage looks like:
+``T``, or an ``Error``. Expected<T> values are also implicitly convertible to
+boolean, but with the opposite convention to ``Error``: true for success, false
+for error. If success, the ``T`` value can be accessed via the dereference
+operator. If failure, the ``Error`` value can be extracted using the
+``takeError()`` method. Idiomatic usage looks like:
.. code-block:: c++
- Expected<float> parseAndSquareRoot(IStream &IS) {
- float f;
- OS >> f;
- if (f < 0)
- return make_error<FloatingPointError>(...);
- return sqrt(f);
+ Expected<FormattedFile> openFormattedFile(StringRef Path) {
+ // If badly formatted, return an error.
+ if (auto Err = checkFormat(Path))
+ return std::move(Err);
+ // Otherwise return a FormattedFile instance.
+ return FormattedFile(Path);
}
- Error foo(IStream &IS) {
- if (auto SqrtOrErr = parseAndSquartRoot(IS)) {
- float Sqrt = *SqrtOrErr;
- // ...
+ Error processFormattedFile(StringRef Path) {
+ // Try to open a formatted file
+ if (auto FileOrErr = openFormattedFile(Path)) {
+ // On success, grab a reference to the file and continue.
+ auto &File = *FileOrErr;
+ ...
} else
- return SqrtOrErr.takeError();
+ // On error, extract the Error value and return it.
+ return FileOrErr.takeError();
}
-All Error instances, whether success or failure, must be either checked or
-moved from (via std::move or a return) before they are destructed. Accidentally
-discarding an unchecked error will cause a program abort at the point where the
-unchecked value's destructor is run, making it easy to identify and fix
-violations of this rule.
+If an ``Expected<T>`` value is in success mode then the ``takeError()`` method
+will return a success value. Using this fact, the above function can be
+rewritten as:
+
+.. code-block:: c++
+
+ Error processFormattedFile(StringRef Path) {
+ // Try to open a formatted file
+ auto FileOrErr = openFormattedFile(Path);
+ if (auto Err = FileOrErr.takeError())
+ // On error, extract the Error value and return it.
+ return Err;
+ // On success, grab a reference to the file and continue.
+ auto &File = *FileOrErr;
+ ...
+ }
+
+This second form is often more readable for functions that involve multiple
+``Expected<T>`` values as it limits the indentation required.
+
+All ``Error`` instances, whether success or failure, must be either checked or
+moved from (via ``std::move`` or a return) before they are destructed.
+Accidentally discarding an unchecked error will cause a program abort at the
+point where the unchecked value's destructor is run, making it easy to identify
+and fix violations of this rule.
Success values are considered checked once they have been tested (by invoking
the boolean conversion operator):
@@ -414,8 +569,8 @@ the boolean conversion operator):
// Safe to continue: Err was checked.
-In contrast, the following code will always cause an abort, regardless of the
-return value of ``foo``:
+In contrast, the following code will always cause an abort, even if ``canFail``
+returns a success value:
.. code-block:: c++
@@ -428,22 +583,318 @@ been activated:
.. code-block:: c++
- auto Err = canFail(...);
- if (auto Err2 =
- handleErrors(std::move(Err),
- [](std::unique_ptr<MyError> M) {
- // Try to handle 'M'. If successful, return a success value from
- // the handler.
- if (tryToHandle(M))
- return Error::success();
+ handleErrors(
+ processFormattedFile(...),
+ [](const BadFileFormat &BFF) {
+ report("Unable to process " + BFF.Path + ": bad format");
+ },
+ [](const FileNotFound &FNF) {
+ report("File not found " + FNF.Path);
+ });
+
+The ``handleErrors`` function takes an error as its first argument, followed by
+a variadic list of "handlers", each of which must be a callable type (a
+function, lambda, or class with a call operator) with one argument. The
+``handleErrors`` function will visit each handler in the sequence and check its
+argument type against the dynamic type of the error, running the first handler
+that matches. This is the same decision process that is used decide which catch
+clause to run for a C++ exception.
+
+Since the list of handlers passed to ``handleErrors`` may not cover every error
+type that can occur, the ``handleErrors`` function also returns an Error value
+that must be checked or propagated. If the error value that is passed to
+``handleErrors`` does not match any of the handlers it will be returned from
+handleErrors. Idiomatic use of ``handleErrors`` thus looks like:
+
+.. code-block:: c++
+
+ if (auto Err =
+ handleErrors(
+ processFormattedFile(...),
+ [](const BadFileFormat &BFF) {
+ report("Unable to process " + BFF.Path + ": bad format");
+ },
+ [](const FileNotFound &FNF) {
+ report("File not found " + FNF.Path);
+ }))
+ return Err;
+
+In cases where you truly know that the handler list is exhaustive the
+``handleAllErrors`` function can be used instead. This is identical to
+``handleErrors`` except that it will terminate the program if an unhandled
+error is passed in, and can therefore return void. The ``handleAllErrors``
+function should generally be avoided: the introduction of a new error type
+elsewhere in the program can easily turn a formerly exhaustive list of errors
+into a non-exhaustive list, risking unexpected program termination. Where
+possible, use handleErrors and propagate unknown errors up the stack instead.
+
+For tool code, where errors can be handled by printing an error message then
+exiting with an error code, the :ref:`ExitOnError <err_exitonerr>` utility
+may be a better choice than handleErrors, as it simplifies control flow when
+calling fallible functions.
+
+StringError
+"""""""""""
+
+Many kinds of errors have no recovery strategy, the only action that can be
+taken is to report them to the user so that the user can attempt to fix the
+environment. In this case representing the error as a string makes perfect
+sense. LLVM provides the ``StringError`` class for this purpose. It takes two
+arguments: A string error message, and an equivalent ``std::error_code`` for
+interoperability:
+
+.. code-block:: c++
+
+ make_error<StringError>("Bad executable",
+ make_error_code(errc::executable_format_error"));
+
+If you're certain that the error you're building will never need to be converted
+to a ``std::error_code`` you can use the ``inconvertibleErrorCode()`` function:
+
+.. code-block:: c++
+
+ make_error<StringError>("Bad executable", inconvertibleErrorCode());
+
+This should be done only after careful consideration. If any attempt is made to
+convert this error to a ``std::error_code`` it will trigger immediate program
+termination. Unless you are certain that your errors will not need
+interoperability you should look for an existing ``std::error_code`` that you
+can convert to, and even (as painful as it is) consider introducing a new one as
+a stopgap measure.
+
+Interoperability with std::error_code and ErrorOr
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Many existing LLVM APIs use ``std::error_code`` and its partner ``ErrorOr<T>``
+(which plays the same role as ``Expected<T>``, but wraps a ``std::error_code``
+rather than an ``Error``). The infectious nature of error types means that an
+attempt to change one of these functions to return ``Error`` or ``Expected<T>``
+instead often results in an avalanche of changes to callers, callers of callers,
+and so on. (The first such attempt, returning an ``Error`` from
+MachOObjectFile's constructor, was abandoned after the diff reached 3000 lines,
+impacted half a dozen libraries, and was still growing).
+
+To solve this problem, the ``Error``/``std::error_code`` interoperability requirement was
+introduced. Two pairs of functions allow any ``Error`` value to be converted to a
+``std::error_code``, any ``Expected<T>`` to be converted to an ``ErrorOr<T>``, and vice
+versa:
+
+.. code-block:: c++
+
+ std::error_code errorToErrorCode(Error Err);
+ Error errorCodeToError(std::error_code EC);
+
+ template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> TOrErr);
+ template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> TOrEC);
+
+
+Using these APIs it is easy to make surgical patches that update individual
+functions from ``std::error_code`` to ``Error``, and from ``ErrorOr<T>`` to
+``Expected<T>``.
+
+Returning Errors from error handlers
+""""""""""""""""""""""""""""""""""""
+
+Error recovery attempts may themselves fail. For that reason, ``handleErrors``
+actually recognises three different forms of handler signature:
+
+.. code-block:: c++
- // We failed to handle 'M' - return it from the handler.
- // This value will be passed back from catchErrors and
- // wind up in Err2, where it will be returned from this function.
- return Error(std::move(M));
- })))
- return Err2;
+ // Error must be handled, no new errors produced:
+ void(UserDefinedError &E);
+ // Error must be handled, new errors can be produced:
+ Error(UserDefinedError &E);
+
+ // Original error can be inspected, then re-wrapped and returned (or a new
+ // error can be produced):
+ Error(std::unique_ptr<UserDefinedError> E);
+
+Any error returned from a handler will be returned from the ``handleErrors``
+function so that it can be handled itself, or propagated up the stack.
+
+.. _err_exitonerr:
+
+Using ExitOnError to simplify tool code
+"""""""""""""""""""""""""""""""""""""""
+
+Library code should never call ``exit`` for a recoverable error, however in tool
+code (especially command line tools) this can be a reasonable approach. Calling
+``exit`` upon encountering an error dramatically simplifies control flow as the
+error no longer needs to be propagated up the stack. This allows code to be
+written in straight-line style, as long as each fallible call is wrapped in a
+check and call to exit. The ``ExitOnError`` class supports this pattern by
+providing call operators that inspect ``Error`` values, stripping the error away
+in the success case and logging to ``stderr`` then exiting in the failure case.
+
+To use this class, declare a global ``ExitOnError`` variable in your program:
+
+.. code-block:: c++
+
+ ExitOnError ExitOnErr;
+
+Calls to fallible functions can then be wrapped with a call to ``ExitOnErr``,
+turning them into non-failing calls:
+
+.. code-block:: c++
+
+ Error mayFail();
+ Expected<int> mayFail2();
+
+ void foo() {
+ ExitOnErr(mayFail());
+ int X = ExitOnErr(mayFail2());
+ }
+
+On failure, the error's log message will be written to ``stderr``, optionally
+preceded by a string "banner" that can be set by calling the setBanner method. A
+mapping can also be supplied from ``Error`` values to exit codes using the
+``setExitCodeMapper`` method:
+
+.. code-block:: c++
+
+ int main(int argc, char *argv[]) {
+ ExitOnErr.setBanner(std::string(argv[0]) + " error:");
+ ExitOnErr.setExitCodeMapper(
+ [](const Error &Err) {
+ if (Err.isA<BadFileFormat>())
+ return 2;
+ return 1;
+ });
+
+Use ``ExitOnError`` in your tool code where possible as it can greatly improve
+readability.
+
+Fallible constructors
+"""""""""""""""""""""
+
+Some classes require resource acquisition or other complex initialization that
+can fail during construction. Unfortunately constructors can't return errors,
+and having clients test objects after they're constructed to ensure that they're
+valid is error prone as it's all too easy to forget the test. To work around
+this, use the named constructor idiom and return an ``Expected<T>``:
+
+.. code-block:: c++
+
+ class Foo {
+ public:
+
+ static Expected<Foo> Create(Resource R1, Resource R2) {
+ Error Err;
+ Foo F(R1, R2, Err);
+ if (Err)
+ return std::move(Err);
+ return std::move(F);
+ }
+
+ private:
+
+ Foo(Resource R1, Resource R2, Error &Err) {
+ ErrorAsOutParameter EAO(&Err);
+ if (auto Err2 = R1.acquire()) {
+ Err = std::move(Err2);
+ return;
+ }
+ Err = R2.acquire();
+ }
+ };
+
+
+Here, the named constructor passes an ``Error`` by reference into the actual
+constructor, which the constructor can then use to return errors. The
+``ErrorAsOutParameter`` utility sets the ``Error`` value's checked flag on entry
+to the constructor so that the error can be assigned to, then resets it on exit
+to force the client (the named constructor) to check the error.
+
+By using this idiom, clients attempting to construct a Foo receive either a
+well-formed Foo or an Error, never an object in an invalid state.
+
+Propagating and consuming errors based on types
+"""""""""""""""""""""""""""""""""""""""""""""""
+
+In some contexts, certain types of error are known to be benign. For example,
+when walking an archive, some clients may be happy to skip over badly formatted
+object files rather than terminating the walk immediately. Skipping badly
+formatted objects could be achieved using an elaborate handler method, but the
+Error.h header provides two utilities that make this idiom much cleaner: the
+type inspection method, ``isA``, and the ``consumeError`` function:
+
+.. code-block:: c++
+
+ Error walkArchive(Archive A) {
+ for (unsigned I = 0; I != A.numMembers(); ++I) {
+ auto ChildOrErr = A.getMember(I);
+ if (auto Err = ChildOrErr.takeError()) {
+ if (Err.isA<BadFileFormat>())
+ consumeError(std::move(Err))
+ else
+ return Err;
+ }
+ auto &Child = *ChildOrErr;
+ // Use Child
+ ...
+ }
+ return Error::success();
+ }
+
+Concatenating Errors with joinErrors
+""""""""""""""""""""""""""""""""""""
+
+In the archive walking example above ``BadFileFormat`` errors are simply
+consumed and ignored. If the client had wanted report these errors after
+completing the walk over the archive they could use the ``joinErrors`` utility:
+
+.. code-block:: c++
+
+ Error walkArchive(Archive A) {
+ Error DeferredErrs = Error::success();
+ for (unsigned I = 0; I != A.numMembers(); ++I) {
+ auto ChildOrErr = A.getMember(I);
+ if (auto Err = ChildOrErr.takeError())
+ if (Err.isA<BadFileFormat>())
+ DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
+ else
+ return Err;
+ auto &Child = *ChildOrErr;
+ // Use Child
+ ...
+ }
+ return DeferredErrs;
+ }
+
+The ``joinErrors`` routine builds a special error type called ``ErrorList``,
+which holds a list of user defined errors. The ``handleErrors`` routine
+recognizes this type and will attempt to handle each of the contained erorrs in
+order. If all contained errors can be handled, ``handleErrors`` will return
+``Error::success()``, otherwise ``handleErrors`` will concatenate the remaining
+errors and return the resulting ``ErrorList``.
+
+Building fallible iterators and iterator ranges
+"""""""""""""""""""""""""""""""""""""""""""""""
+
+The archive walking examples above retrieve archive members by index, however
+this requires considerable boiler-plate for iteration and error checking. We can
+clean this up by using ``Error`` with the "fallible iterator" pattern. The usual
+C++ iterator patterns do not allow for failure on increment, but we can
+incorporate support for it by having iterators hold an Error reference through
+which they can report failure. In this pattern, if an increment operation fails
+the failure is recorded via the Error reference and the iterator value is set to
+the end of the range in order to terminate the loop. This ensures that the
+dereference operation is safe anywhere that an ordinary iterator dereference
+would be safe (i.e. when the iterator is not equal to end). Where this pattern
+is followed (as in the ``llvm::object::Archive`` class) the result is much
+cleaner iteration idiom:
+
+.. code-block:: c++
+
+ Error Err;
+ for (auto &Child : Ar->children(Err)) {
+ // Use Child - we only enter the loop when it's valid
+ ...
+ }
+ // Check Err after the loop to ensure it didn't break due to an error.
+ if (Err)
+ return Err;
.. _function_apis:
@@ -1743,6 +2194,22 @@ reverse) is O(1) worst case. Testing and setting bits within 128 bits (depends
on size) of the current bit is also O(1). As a general statement,
testing/setting bits in a SparseBitVector is O(distance away from last set bit).
+.. _debugging:
+
+Debugging
+=========
+
+A handful of `GDB pretty printers
+<https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html>`__ are
+provided for some of the core LLVM libraries. To use them, execute the
+following (or add it to your ``~/.gdbinit``)::
+
+ source /path/to/llvm/src/utils/gdb-scripts/prettyprinters.py
+
+It also might be handy to enable the `print pretty
+<http://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_57.html>`__ option to
+avoid data structures being printed as a big block of text.
+
.. _common:
Helpful Hints for Common Operations
@@ -2054,7 +2521,7 @@ iterate over all predecessors of BB:
.. code-block:: c++
- #include "llvm/Support/CFG.h"
+ #include "llvm/IR/CFG.h"
BasicBlock *BB = ...;
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
@@ -2825,20 +3292,20 @@ Important Derived Types
* ``unsigned getBitWidth() const``: Get the bit width of an integer type.
``SequentialType``
- This is subclassed by ArrayType, PointerType and VectorType.
+ This is subclassed by ArrayType and VectorType.
* ``const Type * getElementType() const``: Returns the type of each
of the elements in the sequential type.
+ * ``uint64_t getNumElements() const``: Returns the number of elements
+ in the sequential type.
+
``ArrayType``
This is a subclass of SequentialType and defines the interface for array
types.
- * ``unsigned getNumElements() const``: Returns the number of elements
- in the array.
-
``PointerType``
- Subclass of SequentialType for pointer types.
+ Subclass of Type for pointer types.
``VectorType``
Subclass of SequentialType for vector types. A vector type is similar to an