Skip to content

Commit 26a5c63

Browse files
committed
Add LLVMTestUtils class
1 parent fb7ad85 commit 26a5c63

File tree

3 files changed

+419
-0
lines changed

3 files changed

+419
-0
lines changed

test/llvm/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ target_link_libraries(
1616
add_executable(
1717
llvm_test
1818
main.cpp
19+
llvmtestutils.cpp
20+
llvmtestutils.h
1921
llvmexecutioncontext_test.cpp
2022
llvmexecutablecode_test.cpp
2123
llvmcodebuilder_test.cpp

test/llvm/llvmtestutils.cpp

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
#include <scratchcpp/compilerconstant.h>
2+
#include <scratchcpp/executablecode.h>
3+
#include <scratchcpp/executioncontext.h>
4+
#include <scratchcpp/script.h>
5+
#include <scratchcpp/thread.h>
6+
#include <scratchcpp/string_functions.h>
7+
#include <scratchcpp/string_pool.h>
8+
#include <scratchcpp/stringptr.h>
9+
#include <engine/internal/llvm/llvmcodebuilder.h>
10+
#include <engine/internal/llvm/llvmcompilercontext.h>
11+
12+
#include "llvmtestutils.h"
13+
#include "testfunctions.h"
14+
15+
using namespace libscratchcpp;
16+
17+
LLVMTestUtils::LLVMTestUtils()
18+
{
19+
test_function(nullptr, nullptr, nullptr, nullptr, nullptr); // force dependency
20+
}
21+
22+
LLVMCodeBuilder *LLVMTestUtils::createBuilder(Target *target, BlockPrototype *procedurePrototype, Compiler::CodeType codeType)
23+
{
24+
if (m_contexts.find(target) == m_contexts.cend() || !target)
25+
m_contexts[target] = std::make_shared<LLVMCompilerContext>(&m_engine, target);
26+
27+
m_contextList.push_back(m_contexts[target]);
28+
m_builder = std::make_shared<LLVMCodeBuilder>(m_contexts[target].get(), procedurePrototype, codeType);
29+
30+
return m_builder.get();
31+
}
32+
33+
LLVMCodeBuilder *LLVMTestUtils::createBuilder(Target *target, bool warp)
34+
{
35+
m_procedurePrototype = std::make_shared<BlockPrototype>("test");
36+
m_procedurePrototype->setWarp(warp);
37+
createBuilder(target, m_procedurePrototype.get());
38+
39+
return m_builder.get();
40+
}
41+
42+
LLVMCodeBuilder *LLVMTestUtils::createBuilder(bool warp)
43+
{
44+
return createBuilder(nullptr, warp);
45+
}
46+
47+
LLVMCodeBuilder *LLVMTestUtils::createReporterBuilder(Target *target)
48+
{
49+
return createBuilder(target, nullptr, Compiler::CodeType::Reporter);
50+
}
51+
52+
LLVMCodeBuilder *LLVMTestUtils::createPredicateBuilder(Target *target)
53+
{
54+
return createBuilder(target, nullptr, Compiler::CodeType::HatPredicate);
55+
}
56+
57+
CompilerValue *LLVMTestUtils::callConstFuncForType(ValueType type, CompilerValue *arg)
58+
{
59+
switch (type) {
60+
case ValueType::Number:
61+
return m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }, { arg });
62+
63+
case ValueType::Bool:
64+
return m_builder->addFunctionCall("test_const_bool", Compiler::StaticType::Bool, { Compiler::StaticType::Bool }, { arg });
65+
66+
case ValueType::String:
67+
return m_builder->addFunctionCall("test_const_string", Compiler::StaticType::String, { Compiler::StaticType::String }, { arg });
68+
69+
default:
70+
EXPECT_TRUE(false);
71+
return nullptr;
72+
}
73+
}
74+
75+
Value LLVMTestUtils::getOpResult(OpType type, bool rawArg, const Value &v)
76+
{
77+
createReporterBuilder(nullptr);
78+
79+
CompilerValue *arg = m_builder->addConstValue(v);
80+
81+
if (rawArg)
82+
addOp(type, arg);
83+
else {
84+
arg = callConstFuncForType(v.type(), arg);
85+
addOp(type, arg);
86+
}
87+
88+
auto code = m_builder->finalize();
89+
Script script(&m_target, nullptr, nullptr);
90+
script.setCode(code);
91+
Thread thread(&m_target, nullptr, &script);
92+
auto ctx = code->createExecutionContext(&thread);
93+
94+
ValueData data = code->runReporter(ctx.get());
95+
Value ret(data);
96+
value_free(&data);
97+
98+
return ret;
99+
}
100+
101+
Value LLVMTestUtils::getOpResult(OpType type, bool rawArgs, const Value &v1, const Value &v2)
102+
{
103+
createReporterBuilder(nullptr);
104+
105+
CompilerValue *arg1 = m_builder->addConstValue(v1);
106+
CompilerValue *arg2 = m_builder->addConstValue(v2);
107+
108+
if (rawArgs)
109+
addOp(type, arg1, arg2);
110+
else {
111+
arg1 = callConstFuncForType(v1.type(), arg1);
112+
arg2 = callConstFuncForType(v2.type(), arg2);
113+
addOp(type, arg1, arg2);
114+
}
115+
116+
auto code = m_builder->finalize();
117+
Script script(&m_target, nullptr, nullptr);
118+
script.setCode(code);
119+
Thread thread(&m_target, nullptr, &script);
120+
auto ctx = code->createExecutionContext(&thread);
121+
ctx->setRng(&m_rng);
122+
123+
ValueData data = code->runReporter(ctx.get());
124+
Value ret(data);
125+
value_free(&data);
126+
127+
return ret;
128+
}
129+
130+
Value LLVMTestUtils::getExpectedOpResult(OpType type, const Value &v)
131+
{
132+
switch (type) {
133+
case OpType::Not:
134+
return !v.toBool();
135+
136+
case OpType::StringLength:
137+
return v.toUtf16().size();
138+
139+
default:
140+
EXPECT_TRUE(false);
141+
return Value();
142+
}
143+
}
144+
145+
Value LLVMTestUtils::getExpectedOpResult(OpType type, const Value &v1, const Value &v2)
146+
{
147+
switch (type) {
148+
case OpType::Add:
149+
return v1 + v2;
150+
151+
case OpType::Sub:
152+
return v1 - v2;
153+
154+
case OpType::Mul:
155+
return v1 * v2;
156+
157+
case OpType::Div:
158+
return v1 / v2;
159+
160+
case OpType::Random: {
161+
const double sum = v1.toDouble() + v2.toDouble();
162+
163+
if (std::isnan(sum) || std::isinf(sum))
164+
return sum;
165+
166+
return v1.isInt() && v2.isInt() ? m_rng.randint(v1.toLong(), v2.toLong()) : m_rng.randintDouble(v1.toDouble(), v2.toDouble());
167+
}
168+
169+
case OpType::RandomInt:
170+
return m_rng.randint(v1.toLong(), v2.toLong());
171+
172+
case OpType::CmpEQ:
173+
return v1 == v2;
174+
175+
case OpType::CmpGT:
176+
return v1 > v2;
177+
178+
case OpType::CmpLT:
179+
return v1 < v2;
180+
181+
case OpType::StrCmpEQCS:
182+
return string_compare_case_sensitive(value_toStringPtr(&v1.data()), value_toStringPtr(&v2.data())) == 0;
183+
184+
case OpType::StrCmpEQCI:
185+
return string_compare_case_insensitive(value_toStringPtr(&v1.data()), value_toStringPtr(&v2.data())) == 0;
186+
187+
case OpType::And:
188+
return v1.toBool() && v2.toBool();
189+
190+
case OpType::Or:
191+
return v1.toBool() || v2.toBool();
192+
193+
case OpType::Mod:
194+
return v1 % v2;
195+
196+
default:
197+
EXPECT_TRUE(false);
198+
return Value();
199+
}
200+
}
201+
202+
const RandomGeneratorMock &LLVMTestUtils::rng() const
203+
{
204+
return m_rng;
205+
}
206+
207+
CompilerValue *LLVMTestUtils::addOp(OpType type, CompilerValue *arg)
208+
{
209+
switch (type) {
210+
case OpType::Not:
211+
return m_builder->createNot(arg);
212+
213+
case OpType::Round:
214+
return m_builder->createRound(arg);
215+
216+
case OpType::Abs:
217+
return m_builder->createAbs(arg);
218+
219+
case OpType::Floor:
220+
return m_builder->createFloor(arg);
221+
222+
case OpType::Ceil:
223+
return m_builder->createCeil(arg);
224+
225+
case OpType::Sqrt:
226+
return m_builder->createSqrt(arg);
227+
228+
case OpType::Sin:
229+
return m_builder->createSin(arg);
230+
231+
case OpType::Cos:
232+
return m_builder->createCos(arg);
233+
234+
case OpType::Tan:
235+
return m_builder->createTan(arg);
236+
237+
case OpType::Asin:
238+
return m_builder->createAsin(arg);
239+
240+
case OpType::Acos:
241+
return m_builder->createAcos(arg);
242+
243+
case OpType::Atan:
244+
return m_builder->createAtan(arg);
245+
246+
case OpType::Ln:
247+
return m_builder->createLn(arg);
248+
249+
case OpType::Log10:
250+
return m_builder->createLog10(arg);
251+
252+
case OpType::Exp:
253+
return m_builder->createExp(arg);
254+
255+
case OpType::Exp10:
256+
return m_builder->createExp10(arg);
257+
258+
case OpType::StringLength:
259+
return m_builder->addStringLength(arg);
260+
261+
default:
262+
EXPECT_TRUE(false);
263+
return nullptr;
264+
}
265+
}
266+
267+
CompilerValue *LLVMTestUtils::addOp(OpType type, CompilerValue *arg1, CompilerValue *arg2)
268+
{
269+
switch (type) {
270+
case OpType::Add:
271+
return m_builder->createAdd(arg1, arg2);
272+
273+
case OpType::Sub:
274+
return m_builder->createSub(arg1, arg2);
275+
276+
case OpType::Mul:
277+
return m_builder->createMul(arg1, arg2);
278+
279+
case OpType::Div:
280+
return m_builder->createDiv(arg1, arg2);
281+
282+
case OpType::Random:
283+
return m_builder->createRandom(arg1, arg2);
284+
285+
case OpType::RandomInt:
286+
return m_builder->createRandomInt(arg1, arg2);
287+
288+
case OpType::CmpEQ:
289+
return m_builder->createCmpEQ(arg1, arg2);
290+
291+
case OpType::CmpGT:
292+
return m_builder->createCmpGT(arg1, arg2);
293+
294+
case OpType::CmpLT:
295+
return m_builder->createCmpLT(arg1, arg2);
296+
297+
case OpType::StrCmpEQCS:
298+
return m_builder->createStrCmpEQ(arg1, arg2, true);
299+
300+
case OpType::StrCmpEQCI:
301+
return m_builder->createStrCmpEQ(arg1, arg2, false);
302+
303+
case OpType::And:
304+
return m_builder->createAnd(arg1, arg2);
305+
306+
case OpType::Or:
307+
return m_builder->createOr(arg1, arg2);
308+
309+
case OpType::Mod:
310+
return m_builder->createMod(arg1, arg2);
311+
312+
case OpType::StringConcat:
313+
return m_builder->createStringConcat(arg1, arg2);
314+
315+
case OpType::StringChar:
316+
return m_builder->addStringChar(arg1, arg2);
317+
318+
default:
319+
EXPECT_TRUE(false);
320+
return nullptr;
321+
}
322+
}

0 commit comments

Comments
 (0)