DEV Community

Ahmet Can Gulmez
Ahmet Can Gulmez

Posted on

Building a GCC attribute plugin to make extra type-checking

Writing a attribute plugin for GCC is the hard challenge that it seems because of documentation leaks, unstability GCC internal API and you know that compilers are black-box! For these reason, I want to share what I've experienced and how I've completed this project.

How does GCC convert the source code to machine code?

Before diving in the plugin implementation, you have to understand the how machine codes are being produced. Because the any plugin will alter the compilation process of a source code.

I've separated the these compilation process into 7 steps:

  • Preprocessing

  • Parsing & AST (Abstract Syntax Tree)

  • GIMPLE

  • RTL (Register Transfer Logic)

  • Compiling

  • Assembler

  • Linking

Now, let's look at these steps in details.

Preprocessing

That's the first step that GCC does. GCC will call the cpp when the compilation process starts. At this step, cpp will make the basically two things. First is the remove comment lines. Don't forget that comments are for us not compiler! Second is to expand the preprocessor directives (starts with #). For example, #include directive will be removed and the stdio.h library content will be placed instead. You can see the preprocessed output by using -i option.

Parsing & AST (Abstract Syntax Tree)

After preprocessing step, GCC will parse the source file and then make some checks for grammar, syntax or logic rules. If there is not found any error then GCC tokenizes the parsed source code and then finally convert it in tree-like nodes.

This tree-like nodes are the key for any plugin implementation. My plugin like others will catch this nodes and then proceed it with its defined logic. In my case, this logic is the extra type-checks. You can see the tree-like nodes by using fdump-tree-original option.

GIMPLE

The third stage is for optimizations. In here, GCC does many optimization techniques. The main purpose is to simplify the code. Complex expressions are broken down to atomic ones. In here atomic means that the operation will be done with just one register. You can see the these optimizations just using fdump-tree-gimple option.

RTL (Register Transfer Language)

At this stage, you see the source code in form of abstract register. In here, abstract means that the source code will be represented with GCC's internal register names. Because of this is that GCC yet don't know the target architecture so that it has to make some assumptions. When the target architecture information is given to GCC, the real registers will replace the abstract ones. You can see the RTL representation by using fdump-rtl-expand option.

Compiling

GCC has now target architecture so that it replaces the abstract registers with registers of target architecture instruction set. In here, the source code is in form of assembly. You can see the assembly code by using -S option.

Assembler

In here, GCC converts the assembly commands into object file. Source code is transformed to machine code here. After that the all machine code is put into object.

Linking

The last step is the linking. In here, the all object files (if exists) and all static/dynamic libraries (if exists) are merged into one executable file. It is read to work now!

What is the attribute plugin?

After explaining the whole compilation process, let's talk about plugin implementation. At first, you have to understand what is the attribute plugin and how is it used.

A plugin is the basically a dynamic library that changes the compilation process of GCC. After creating the plugin library, I compile the any source file that I want to change compilation of it with fplugin=.so option. According to plugin logic, the source file is compiled with it. That's all!

If I want to use this plugin as attribute with GCC's attribute, I just append a structure and its required functions. Of course, I will not mention the code implementation here. It is long and complex to explain by writing. I will put the project link at the end.

A minimal attribute plugin

Lastly, I want to share the core requirements of a attribute plugin implementation.

First of all, you need to define the attribute behavior with attribute_spec structure. This structure accepts some variables and a handler function. This handler function determines and limits the usage. For example, my attribute plugin just expects two arguments. If the more or less arguments are supplied the control block in handler function is called and launched a error message.

Also you need the plugin_init() function. It is the mandatory for all plugin implementation. It's the entry-point. When GCC call the plugin, just this function runs. You can think it like main() from any user-space program. In this function, you have to register the attribute structure and a callback function.

The callback function includes the your main plugin logic. In my case, in here, there are extra type-checks logic.

And probably you need some utility functions. For example, I defined the get_current_time() time and get_code_line() functions.

Project link: https://github.com/CanGulmez/RedRose-Attribute-Plugin

Top comments (0)