Eclipse OMR - JitBuilder Demo1(Simple)

https://github.com/eclipse/omr/blob/master/jitbuilder/release/src/Simple.hpp

https://github.com/eclipse/omr/blob/master/jitbuilder/release/src/Simple.cpp

The above two files are one of the demos that come with JitBuilder of Eclipse OMR, and it is also the simplest example.

This example implements this function: use code to dynamically define a function increment, the purpose of this function: the parameter is a 32-bit integer, and the return value is the parameter value plus 1. int32 increment(int32). Because this is a demo, the problem of out-of-bounds integer addition is not dealt with. increment(2017) returns 2018.

int increment(int value) {
  return value + 1;
}

The above is the same function written in C language. Before we implement it with JitBuilder, let's think about the steps we take to write this function:

1. Define the function name: increment

2. Define the parameter name (value) and parameter type (int) of the function

3. Define the return value type of the function (int)

4. Implement the function body code

These three steps are also followed in JitBuilder. Let's take a closer look at the Demo code below.

First look at the header file: https://github.com/eclipse/omr/blob/master/jitbuilder/release/src/Simple.hpp

class SimpleMethod : public TR::MethodBuilder
{
  public:
    SimpleMethod(TR::TypeDictionary *);
    virtual bool buildIL();
};

This is the core code, the function is concise: define your own class: SimpleMethod, its parent class is TR::MethodBuilder, implement the constructor of SimpleMethod, override the method buildIL of TR::MethodBuilder (accurately speaking, the buildIL method is the upper parent class definition).

Then look at the cpp file: https://github.com/eclipse/omr/blob/master/jitbuilder/release/src/Simple.cpp

There is a little more code in the cpp file, let's look at the constructor of SimpleMethod first

SimpleMethod::SimpleMethod(TR::TypeDictionary *d)
   : MethodBuilder(d)
{
   DefineLine(LINETOSTR(__LINE__));
   DefineFile(__FILE__);

   DefineName("increment");
   DefineParameter("value", Int32);
   DefineReturnType(Int32);
}

1. Use DefineName to define the name of the function to be implemented: increment

2. Define the parameter name value and type Int32 of the function increment with DefineParameter

3. Define the function return value Int32 with DefineReturnType

These three steps correspond to the following C code we wrote

int increment(int value) 
{

}

Next, of course, is to implement the specific code of the function body, which is implemented in buildIL, first look at the code

bool SimpleMethod::buildIL()
{
   Return(
      Add(
         Load("value"),
         ConstInt32(1)));

   return true;
}

At a guess, this is C code similar to the following

return value + 1;

IL in buildIL is the abbreviation of Intermediate Language, that is, intermediate language. Because OMR itself does not correspond to a high-level language, it defines its own language (IL) to express semantics. Those who have learned the principle of compilation understand that this is a necessary routine for writing compilers.

The full name of OMR's IL is: Testarossa's Intermediate Language

For more documentation see: https://github.com/eclipse/omr/tree/master/doc/compiler/il

Because IL involves a lot of knowledge points, this will be explained in detail in future blogs.

A basic point to remember first: IL is based on a Tree structure, or DAG (directed acyclic graph) to be precise.

Back in the buildIL of our increment function

Return(
      Add(
         Load("value"),
         ConstInt32(1)));

This is the code written in C++ code in the style of IL. Special attention should be paid to the use of indentation to express the hierarchy in the Tree, which is a specific idiom when writing IL.

To summarize the above steps:

1. Define your own class, inherit from TR::MethodBuilder.

2. Define the function name, parameter name and type and return value type in the constructor of the custom class

3. Override buildIL, use IL to implement the specific functions of the function

 

Implemented the increment function, let's see how to use it.

int main(int argc, char *argv[])
{
   // 我把原来代码中关于错误处理的代码全部删除了
   // 所以下面的代码是为了便于入门理解用

   // 第1步:调用initializeJit()初始化JIT编译器
   initializeJit();

   // 第2步:初始化自定义的class,这里是SimpleMethod
   TR::TypeDictionary types;
   SimpleMethod method(&types);
   
   // 第3步:即时编译代码
   uint8_t *entry = 0;
   int32_t rc = compileMethodBuilder(&method, &entry);

   // 第4步:用函数指针获得编译后的代码地址
   typedef int32_t (SimpleMethodFunction)(int32_t);
   SimpleMethodFunction *increment = (SimpleMethodFunction *) entry;

   // 第5步:用函数指针调用函数
   int32_t v = 10;
   cout << "increment(" << v << ") == " << increment(v) << "\n";
   
   // 第6步:卸载JIT编译器,释放内存
   shutdownJit();
}

The above 6 steps are the basic routines of using the JIT compiler.

After reading this, you can manually change the code of this demo, such as implementing an int add(int a, int b).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325466624&siteId=291194637