I've recently started learning assembly for linux and wow how it goes against linux portablity! I tried to google search this but could'nt find a good answer. How in the heck does a compiler do it? Did the creator write it to be compatible with every architecture and os possible? This surely can't be the case.
It's not as magic as you think. (But it is complex.)
Every piece of hardware does the same kinds of things: add two words, compare two values, jump on condition, etc.
The compiler converts the program into a high-level representation of your program's code. Then it performs some transformations on that representation to clean it up some and make it simpler.
Next it applies a series of transformation that converts high-level operations into low-level operations. And then it again applies a whole bunch of transformations to optimize the code for the target machine.
Once done, it dumps the machine code into an object file, which the linker then links into an executable.
Don't forget JIT (Just In Time) which is very popular recently. It's what Java uses to convert Java bytecode to native machine code on the fly, and it is also supported by LLVM (which is used by clang).
I've been curious as well about certain things between a general compiler and a JIT compiler. I know GCC used some weird library that kinda hacked a JIT interface from GCC... what's the difference?
I know GCC might perform some optimizations that aren't ideal in a JIT environment... so is it just a general compiler tuned for a JIT environment? How does that work?
I've never really dealt with JITing before so I'm completely ignant to the matter.