> more like an assembler than a compiler since there is no mess and it outputs C code.
Yes, translating between closely related languages is often like this: the mapping between their constructs is 1-to-1 and almost trivial. But try translating e.g. λ-calculus into C in one go, without separate lambda-lifting/closure-converting steps: it's absolutely doable but quite messy.
When absolute compiler perf isn't required, I love nanopass compilers for this. Each pass slowly massages a slightly different IR towards the final form and there isn't really a limit to how different the code source and end target can be, just needs more passes.
https://news.ycombinator.com/item?id=28183062
https://news.ycombinator.com/item?id=28197876