How to add a new OpenMP directive in Clang/LLVM compiler
Tips:
Code snippets are shown in one of three ways throughout this environment:
- Code that looks like
this
is sample code snippets that is usually part of an explanation. - Code that appears in box like the one below can be clicked on and it will automatically be typed in to the appropriate terminal window:
vim readme.txt
- Code appearing in windows like the one below is code that you should type in yourself. Usually there will be a unique ID or other bit your need to enter which we cannot supply. Items appearing in <> are the pieces you should substitute based on the instructions.
Add your name here - <name>
Features
In this tutorial we will cover how to add a new OpenMP directive in Clang/LLVM compiler.
The goal of this tutorial is to add a new OpenMP directive – allocate
.
This tutorial is intended to give you some insight into the real-world front end used by LLVM/Clang.
An allocate directive is an executable directive that allocates memory to a given pointer.
The syntax of allocate
has the following format:
#pragma omp allocate(A)
Here, A is a pointer defined in the program, and this statement specifies that memory space for the data pointed to by A should be allocated, using malloc internally. To make this task simpler, we assume for this task that the amount of memory to be allocated is always (100*sizeof(int)).
Step 1 - Locate and go to clang directory
First, let’s enter the LLVM
source folder to look around. There are a bunch of files and directories there. For now only interested in the Clang sub-project of the LLVM source code. In this tutorials’s environment, the Clang project is located at $LLVM_SRC/tools/clang
. In your machine you should locate the Clang project and switch to that directory.
cd $LLVM_SRC/tools/clang
Step 2 - Define the token of new directive
The first thing that we should do is let the compiler identify a new directive, which in this tutorial is allocate
.
Now let us update the compiler, such that it just identifies the new directive. For this we need to update two files:
- OpenMPKinds.def – which defines the list of supported OpenMP directives and clauses.
- ParseOpenMP.cpp – which implements parsing of all OpenMP directives and clauses.
To define the new directive we will modify the file OpenMPKinds.def
, located in include/clang/Basic
.
So open the file using your favorite editor and go to line 237 (or anywhere before #undef OPENMP_DIRECTIVE
is called).
vim include/clang/Basic/OpenMPKinds.def +237
Add the following new line after it:
OPENMP_DIRECTIVE(allocate)
In our current state we are not dealing with any clause associated with allocate, so we do not need to define OPENMP_ALLOCATE_CLAUSE
.
This way we are able to define the token for the new directive #pragma omp allocate
.
Step 3 - Implement parsing
Before parsing the lexer will split the source code into multiple tokens.
The parser will read these tokens and give a structural representation to them.
To implement the parsing of this new directive we need to modify the file ParseOpenMP.cpp
, located in lib/Parse
.
Open this file and go to the function ParseOpenMPDeclarativeOrExecutableDirective
, identify the switch statement (line 997):
vim lib/Parse/ParseOpenMP.cpp +997
Add a new case for OMPD_allocate
anyweher inside of the body of the switch statement.
Here we will print out ALLOCATE is caught and then consume the token.
case OMPD_allocate: {
llvm::errs() <<"ALLOCATE is caught\n";
ConsumeToken();
ConsumeAnnotationToken();
break;
}
That’s it for now. Now let us build and test our code.
Step 4 - Building LLVM and testing code
To build LLVM
go to the LLVM_BUILD
directory and run make.
We are redirecting the standard output of make to /dev/null to have a clean output.
Warning and error messages will still show up if there are any.
cd $LLVM_BUILD && make -j4 install > /dev/null
This build step may take a few minutes.
You might get a couple of warnings about enumeration value 'OMPD_allocate' not handled in switch
.
Please ignore these warnings for now; we will handle them later.
Once the code builds successfully and is installed, its time to test a small program.
Let us create a new test file:
cat <<EOF > allocate.c
int main()
{
#pragma omp allocate
return 0;
}
EOF
Now you have a new test file allocate.c
which uses the allocate
directive.
Build this file using your Clang compiler.
clang -fopenmp allocate.c
you should get an output ALLOCATE is caught
.
Congratulations you were successfully able to add and identify a new directive to openmp in Clang compiler. Next follow the tutorial – Adding an AST Node for new Directive in OpenMP (Clang).