• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gtest/gtest.h"
17 
18 #include "asmjit/x86.h"
19 
20 namespace panda::compiler {
21 using namespace asmjit;
22 
23 class AsmJitTest : public ::testing::Test {
24 };
25 
TEST_F(AsmJitTest,HelloWorld)26 TEST_F(AsmJitTest, HelloWorld)
27 {
28     // Runtime designed for JIT code execution.
29     JitRuntime rt;
30 
31     // Holds code and relocation information.
32     CodeHolder code;
33     code.init(rt.environment());
34 
35     x86::Assembler a(&code);
36     a.mov(x86::eax, 1);
37     a.ret();
38 
39     // Signature of the generated function.
40     typedef int (*Func)(void);
41     Func fn {nullptr};
42 
43     // Add the generated code to the runtime.
44     Error err = rt.add(&fn, &code);
45     ASSERT_FALSE(err);
46 
47     int result {fn()};
48     ASSERT_EQ(1, result);
49 }
50 
TEST_F(AsmJitTest,Add)51 TEST_F(AsmJitTest, Add)
52 {
53     // Runtime designed for JIT code execution.
54     JitRuntime rt;
55 
56     // Holds code and relocation information.
57     CodeHolder code;
58     code.init(rt.environment());
59 
60     // Generating code:
61     x86::Assembler a(&code);
62     x86::Gp lhs = a.zax();
63     x86::Gp rhs = a.zcx();
64 
65     FuncDetail func;
66     func.init(FuncSignatureT<size_t, size_t, size_t>(CallConv::kIdHost), code.environment());
67 
68     FuncFrame frame;
69     frame.init(func);
70     frame.addDirtyRegs(lhs, rhs);
71 
72     FuncArgsAssignment args(&func);
73     args.assignAll(lhs, rhs);
74     args.updateFuncFrame(frame);
75     frame.finalize();
76 
77     a.emitProlog(frame);
78     a.emitArgsAssignment(frame, args);
79     a.add(lhs, rhs);
80     a.emitEpilog(frame);
81 
82     // Signature of the generated function.
83     typedef size_t (*Func)(size_t, size_t);
84     Func fn {nullptr};
85 
86     // Add the generated code to the runtime.
87     Error err = rt.add(&fn, &code);
88     ASSERT_FALSE(err);
89 
90     size_t result {fn(size_t(2), size_t(3))};
91     ASSERT_EQ(size_t(5), result);
92 }
93 
TEST_F(AsmJitTest,AddExplicit)94 TEST_F(AsmJitTest, AddExplicit)
95 {
96     Environment env = hostEnvironment();
97     JitAllocator allocator;
98 
99     CodeHolder code;
100     code.init(env);
101 
102     // Generating code:
103     x86::Assembler a(&code);
104     x86::Gp lhs = a.zax();
105     x86::Gp rhs = a.zcx();
106 
107     FuncDetail func;
108     func.init(FuncSignatureT<size_t, size_t, size_t>(CallConv::kIdHost), code.environment());
109 
110     FuncFrame frame;
111     frame.init(func);
112     frame.addDirtyRegs(lhs, rhs);
113 
114     FuncArgsAssignment args(&func);
115     args.assignAll(lhs, rhs);
116     args.updateFuncFrame(frame);
117     frame.finalize();
118 
119     a.emitProlog(frame);
120     a.emitArgsAssignment(frame, args);
121     a.add(lhs, rhs);
122     a.emitEpilog(frame);
123 
124     code.flatten();
125     code.resolveUnresolvedLinks();
126     size_t estimated_size = code.codeSize();
127 
128     // Allocate memory for the function and relocate it there.
129     void *ro_ptr;
130     void *rw_ptr;
131     Error err = allocator.alloc(&ro_ptr, &rw_ptr, estimated_size);
132     ASSERT_FALSE(err);
133 
134     // Relocate to the base-address of the allocated memory.
135     code.relocateToBase(reinterpret_cast<uintptr_t>(rw_ptr));
136     size_t code_size = code.codeSize();
137 
138     code.copyFlattenedData(rw_ptr, code_size, CodeHolder::kCopyPadSectionBuffer);
139 
140     // Execute the function and test whether it works.
141     typedef size_t (*Func)(size_t lhs, size_t rhs);
142     Func fn = (Func)ro_ptr;
143 
144     size_t result {fn(size_t(2), size_t(3))};
145     ASSERT_EQ(size_t(5), result);
146 
147     err = allocator.release(ro_ptr);
148     ASSERT_FALSE(err);
149 }
150 }  // namespace panda::compiler
151