Code generation for compiler backend

I'm currently looking at how to use llvm as a backend for compiling
executable programs; here's my understanding of the state of affairs
so far:

Kaleidoscope demonstrates how to generate code in memory, and run it
in memory using JIT for interactive use (which will be handy in due
course for providing an interactive option); BrainF demonstrates how
to output intermediate code; but it is preferable to take it all the
way to CPU specific assembly.
CPU specific assembly is as far as llvm goes, at that point one hands
over to the GNU assembler and linker to generate an executable
program.
Generating assembly output is demonstrated by llc.
llc.cpp is a small driver program that mostly calls library
functionality, which is good because it means once you understand how
it works, you can reproduce the effect in your own programs that are
linked with the libraries.
The target for which to generate code is selected at run time, by
default the available targets are x86 32 and 64 bit, but by selecting
all targets at the time of running cmake for llvm, it's possible to
end up with a single compiler that can generate code for all supported
CPU architectures, which is good (e.g. for cross compiling embedded
software).

Basically my question is, is the above along the right lines or am I
misunderstanding anything or barking up the wrong tree anywhere? And
is there anywhere I should be looking in code or documentation apart
from llc.cpp?