No, it's not. The LLVM API is really easy to use, with an excellent tutorial available (Kaleidoscope). You get to work with the IR as a tree instead of as a quirky serialized output format that was never designed to be used as an IR.
The LLVM API is good, yes, but from a project management point of view it's pretty painful to work with --- the libraries are vast, don't have stable binary interfaces, and don't validate parameters, which means that if you get anything wrong it tends to just segfault deep inside somewhere. I've had to single step through the LLVM source code way too many times.
Plus, distribution support has always been pretty poor. e.g. Debian's 3.3 package's llvm-config tries to link your program against the static libraries rather than the dynamic ones, which leads to painfully large link times.
This all adds up to a non-trivial cost.
By contrast, emitting C is a lot less powerful, but suddenly you don't have to care about any of this stuff. You have a standardised intermediate format which you can throw at any compiler, which is trivially verifiable, doesn't need special libraries to write, and easily integrates into third-party tool chains. Simply having rigorously separated front and back ends can be a huge win. But biggest of all, you don't have to keep knowledge of the LLVM API in your brain while you're trying to get work done.
Of course, you don't get proper debugging information, or tail calls, or any of the other things you can do with the LLVM API which you can't do through C; but depending on what you want to do, it can totally be worth it.
> the libraries are vast, don't have stable binary interfaces, and don't validate parameters, which means that if you get anything wrong it tends to just segfault deep inside somewhere.
Did you compile LLVM in Debug+Asserts mode? I rarely ever get segfaults from LLVM in this mode: I just get assertions when constructing invalid IR nodes.
> Plus, distribution support has always been pretty poor. e.g. Debian's 3.3 package's llvm-config tries to link your program against the static libraries rather than the dynamic ones, which leads to painfully large link times.
The link times aren't so bad if you use gold.
> You have a standardised intermediate format which you can throw at any compiler, which is trivially verifiable
I wouldn't say it's trivially verifiable. The undefined behavior rules of C are vast, and compiler authors have to know them incredibly well.
> But biggest of all, you don't have to keep knowledge of the LLVM API in your brain while you're trying to get work done.
But you have to keep C's undefined behavior rules in the back of your brain (such as signed overflow == UB!), which is worse.