> All of those look pretty straightforward to me -- again, what assembly would you expect to be emitted in those cases?
It is very straightforward indeed, but it is still not mapping primitive operations to direct machine code, but it is forwarding to out-of-line code. Same as operator overloading in other languages.
> It is very straightforward indeed, but it is still not mapping primitive
> operations to direct machine code, but it is forwarding to out-of-line code.
> Same as operator overloading in other languages.
I am not claiming that C is a collection of assembler macros. There is no expectation that a C compiler emit machine code that has exact 1:1 correspondence with the input source code.
> Same as operator overloading in other languages.
The lack of operator overloading, and other hidden complex control flow, is the reason that someone can read C code and have a pretty good idea of what it compiles to.
> That's just a symptom of allowing the compiler to inline the add code,
> otherwise the generated code is as straightforward:
No, that's just moving the instructions around. You've still got dynamic allocation and stack-unwinding being generated for a line that doesn't have any sign of entering a complex control flow graph.
Until someone calls longjmp() or a signal() is triggered. Extra bonus of fun if it happens to be multithreaded application, or in the middle of a non-rentrant call.
For contrast, here's the assembly generated for Haskell for integer addition: https://godbolt.org/z/vdeMKMETT
And here's assembly for C++: https://godbolt.org/z/dedcof9x5