Skip to content

06 How the C++ Compiler Works

1. Abstract Syntax Tree

The compiler's job is to transform code into constant data and instructions. After constructing the abstract syntax tree, it begins generating code.

In C++, there is no concept of a "file"; files are merely a way to provide source code to the compiler.

.cpp tells the compiler to compile using C++ -> the compiler treats it as a translation unit -> resulting in a .obj file.

Common preprocessor statements are pragma statements.

include
define
if
ifdef

Common Preprocessor Statements

2.1 #include

#include simply copies the contents of the desired file into the current file. For example, if you create an EndBrace.h file with the following content:

}

Then, my Multiply function can still compile correctly even if written like this:

int Multiply(int a, int b)
{
    int result = a * b;
    return result;
    #include "EndBrace.h"

To inspect the preprocessed file, you can generate a .i file by performing the following operation:

The contents of the Math.i file are as follows:

2.2 #define

#define INTEGER int

This searches for the word INTEGER and replaces it with what follows.

2.3 #if

Allows us to include or exclude code based on specific conditions.

// Exclude
#if 0
int Multiply(int a, int b)
{
    int result = a * b;
    return result;
}
#endif

You can convert .obj files into a readable .asm format. To read binary, I used the VSCode plugin Hex Editor.

3. Compiler Optimizations

3.1 Simple Case

int result = a * b
return result

====>

return a * b

3.2 Constant Folding

return 5 * 2

====>

return 10

3.3 Function Signatures and Calls

A "call" refers to invoking a function. Through symbol decoration, the function is given a unique signature, allowing the linker to locate the function based on its signature.

Modifying the compiler can automatically optimize assembly instructions.