88#include < engine/internal/llvm/llvmexecutablecode.h>
99#include < engine/internal/llvm/llvmcompilercontext.h>
1010#include < engine/internal/llvm/llvmexecutioncontext.h>
11+ #include < engine/internal/llvm/llvmtypes.h>
1112#include < llvm/IR/Module.h>
1213#include < llvm/IR/IRBuilder.h>
1314#include < enginemock.h>
@@ -29,19 +30,37 @@ class LLVMExecutableCodeTest : public testing::Test
2930 m_module = m_ctx->module ();
3031 m_llvmCtx = m_ctx->llvmCtx ();
3132 m_builder = std::make_unique<llvm::IRBuilder<>>(*m_llvmCtx);
33+ m_valueDataType = LLVMTypes::createValueDataType (m_builder.get ());
3234 test_function (nullptr , nullptr , nullptr , nullptr , nullptr ); // force dependency
3335
3436 m_script = std::make_unique<Script>(&m_target, nullptr , &m_engine);
3537 }
3638
3739 inline llvm::Constant *nullPointer () { return llvm::ConstantPointerNull::get (llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 )); }
3840
39- llvm::Function *beginMainFunction (bool predicate = false )
41+ llvm::Function *beginMainFunction (Compiler::CodeType codeType = Compiler::CodeType::Script )
4042 {
4143 // void *f(ExecutionContext *, Target *, ValueData **, List **)
44+ // ValueData f(...) (reporters)
4245 // bool f(...) (hat predicates)
4346 llvm::Type *pointerType = llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 );
44- llvm::FunctionType *funcType = llvm::FunctionType::get (predicate ? m_builder->getInt1Ty () : pointerType, { pointerType, pointerType, pointerType, pointerType }, false );
47+ llvm::Type *retType = nullptr ;
48+
49+ switch (codeType) {
50+ case Compiler::CodeType::Script:
51+ retType = pointerType;
52+ break ;
53+
54+ case Compiler::CodeType::Reporter:
55+ retType = m_valueDataType;
56+ break ;
57+
58+ case Compiler::CodeType::HatPredicate:
59+ retType = m_builder->getInt1Ty ();
60+ break ;
61+ }
62+
63+ llvm::FunctionType *funcType = llvm::FunctionType::get (retType, { pointerType, pointerType, pointerType, pointerType }, false );
4564 llvm::Function *func = llvm::Function::Create (funcType, llvm::Function::ExternalLinkage, " f" , m_module);
4665
4766 llvm::BasicBlock *entry = llvm::BasicBlock::Create (*m_llvmCtx, " entry" , func);
@@ -62,27 +81,22 @@ class LLVMExecutableCodeTest : public testing::Test
6281
6382 void endFunction (llvm::Value *ret) { m_builder->CreateRet (ret); }
6483
65- void addTestFunction (llvm::Function *mainFunc)
84+ llvm::Value * addMainFunction (llvm::Function *mainFunc, const std::string testFuncName, llvm::Type *retType )
6685 {
6786 auto ptrType = llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 );
68- auto func = m_module->getOrInsertFunction (" test_function " , llvm::FunctionType::get (m_builder-> getVoidTy () , { ptrType, ptrType, ptrType, ptrType, ptrType }, false ));
87+ auto func = m_module->getOrInsertFunction (testFuncName , llvm::FunctionType::get (retType , { ptrType, ptrType, ptrType, ptrType, ptrType }, false ));
6988
7089 llvm::Constant *mockInt = llvm::ConstantInt::get (llvm::Type::getInt64Ty (*m_llvmCtx), (uintptr_t )&m_mock, false );
7190 llvm::Constant *mockPtr = llvm::ConstantExpr::getIntToPtr (mockInt, ptrType);
7291
73- m_builder->CreateCall (func, { mockPtr, mainFunc->getArg (0 ), mainFunc->getArg (1 ), mainFunc->getArg (2 ), mainFunc->getArg (3 ) });
92+ return m_builder->CreateCall (func, { mockPtr, mainFunc->getArg (0 ), mainFunc->getArg (1 ), mainFunc->getArg (2 ), mainFunc->getArg (3 ) });
7493 }
7594
76- llvm::Value *addPredicateFunction (llvm::Function *mainFunc)
77- {
78- auto ptrType = llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 );
79- auto func = m_module->getOrInsertFunction (" test_predicate" , llvm::FunctionType::get (m_builder->getInt1Ty (), { ptrType, ptrType, ptrType, ptrType, ptrType }, false ));
95+ void addTestFunction (llvm::Function *mainFunc) { addMainFunction (mainFunc, " test_function" , m_builder->getVoidTy ()); }
8096
81- llvm::Constant *mockInt = llvm::ConstantInt::get (llvm::Type::getInt64Ty (*m_llvmCtx), (uintptr_t )&m_mock, false );
82- llvm::Constant *mockPtr = llvm::ConstantExpr::getIntToPtr (mockInt, ptrType);
97+ llvm::Value *addReporterFunction (llvm::Function *mainFunc) { return addMainFunction (mainFunc, " test_reporter" , m_valueDataType); }
8398
84- return m_builder->CreateCall (func, { mockPtr, mainFunc->getArg (0 ), mainFunc->getArg (1 ), mainFunc->getArg (2 ), mainFunc->getArg (3 ) });
85- }
99+ llvm::Value *addPredicateFunction (llvm::Function *mainFunc) { return addMainFunction (mainFunc, " test_predicate" , m_builder->getInt1Ty ()); }
86100
87101 void addTestPrintFunction (llvm::Value *arg1, llvm::Value *arg2)
88102 {
@@ -95,6 +109,7 @@ class LLVMExecutableCodeTest : public testing::Test
95109 llvm::LLVMContext *m_llvmCtx = nullptr ;
96110 llvm::Module *m_module = nullptr ;
97111 std::unique_ptr<llvm::IRBuilder<>> m_builder;
112+ llvm::StructType *m_valueDataType = nullptr ;
98113 Target m_target;
99114 EngineMock m_engine;
100115 std::unique_ptr<Script> m_script;
@@ -122,7 +137,7 @@ TEST_F(LLVMExecutableCodeTest, CreateExecutionContext)
122137
123138TEST_F (LLVMExecutableCodeTest, CreatePredicateExecutionContext)
124139{
125- llvm::Function *mainFunc = beginMainFunction (true );
140+ llvm::Function *mainFunc = beginMainFunction (Compiler::CodeType::HatPredicate );
126141 endFunction (m_builder->getInt1 (false ));
127142
128143 llvm::Function *resumeFunc = beginResumeFunction ();
@@ -139,6 +154,25 @@ TEST_F(LLVMExecutableCodeTest, CreatePredicateExecutionContext)
139154 }
140155}
141156
157+ TEST_F (LLVMExecutableCodeTest, CreateReporterExecutionContext)
158+ {
159+ llvm::Function *mainFunc = beginMainFunction (Compiler::CodeType::Reporter);
160+ endFunction (addReporterFunction (mainFunc));
161+
162+ llvm::Function *resumeFunc = beginResumeFunction ();
163+ endFunction (m_builder->getInt1 (true ));
164+
165+ {
166+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), Compiler::CodeType::Reporter);
167+ m_script->setCode (code);
168+ Thread thread (&m_target, &m_engine, m_script.get ());
169+ auto ctx = code->createExecutionContext (&thread);
170+ ASSERT_TRUE (ctx);
171+ ASSERT_EQ (ctx->thread (), &thread);
172+ ASSERT_TRUE (dynamic_cast <LLVMExecutionContext *>(ctx.get ()));
173+ }
174+ }
175+
142176TEST_F (LLVMExecutableCodeTest, MainFunction)
143177{
144178 m_target.addVariable (std::make_shared<Variable>(" " , " " ));
@@ -157,7 +191,7 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
157191 auto ctx = code->createExecutionContext (&thread);
158192 ASSERT_FALSE (code->isFinished (ctx.get ()));
159193
160- EXPECT_CALL (m_mock, f (ctx.get (), &m_target, m_target.variableData (), m_target.listData ()));
194+ EXPECT_CALL (m_mock, script (ctx.get (), &m_target, m_target.variableData (), m_target.listData ()));
161195 code->run (ctx.get ());
162196 ASSERT_TRUE (code->isFinished (ctx.get ()));
163197
@@ -170,7 +204,7 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
170204 code->kill (ctx.get ());
171205 ASSERT_TRUE (code->isFinished (ctx.get ()));
172206
173- EXPECT_CALL (m_mock, f ).Times (0 );
207+ EXPECT_CALL (m_mock, script ).Times (0 );
174208 code->run (ctx.get ());
175209 ASSERT_TRUE (code->isFinished (ctx.get ()));
176210
@@ -185,7 +219,7 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
185219 ASSERT_FALSE (code->isFinished (anotherCtx.get ()));
186220 ASSERT_TRUE (code->isFinished (ctx.get ()));
187221
188- EXPECT_CALL (m_mock, f (anotherCtx.get (), &anotherTarget, anotherTarget.variableData (), anotherTarget.listData ()));
222+ EXPECT_CALL (m_mock, script (anotherCtx.get (), &anotherTarget, anotherTarget.variableData (), anotherTarget.listData ()));
189223 code->run (anotherCtx.get ());
190224 ASSERT_TRUE (code->isFinished (anotherCtx.get ()));
191225 ASSERT_TRUE (code->isFinished (ctx.get ()));
@@ -200,7 +234,7 @@ TEST_F(LLVMExecutableCodeTest, PredicateFunction)
200234 m_target.addVariable (std::make_shared<Variable>(" " , " " ));
201235 m_target.addList (std::make_shared<List>(" " , " " ));
202236
203- llvm::Function *mainFunc = beginMainFunction (true );
237+ llvm::Function *mainFunc = beginMainFunction (Compiler::CodeType::HatPredicate );
204238 endFunction (addPredicateFunction (mainFunc));
205239
206240 llvm::Function *resumeFunc = beginResumeFunction ();
@@ -224,6 +258,27 @@ TEST_F(LLVMExecutableCodeTest, PredicateFunction)
224258 ASSERT_FALSE (code->runPredicate (ctx.get ()));
225259}
226260
261+ TEST_F (LLVMExecutableCodeTest, ReporterFunction)
262+ {
263+ m_target.addVariable (std::make_shared<Variable>(" " , " " ));
264+ m_target.addList (std::make_shared<List>(" " , " " ));
265+
266+ llvm::Function *mainFunc = beginMainFunction (Compiler::CodeType::Reporter);
267+ endFunction (addReporterFunction (mainFunc));
268+
269+ llvm::Function *resumeFunc = beginResumeFunction ();
270+ endFunction (m_builder->getInt1 (true ));
271+
272+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), Compiler::CodeType::Reporter);
273+ m_script->setCode (code);
274+ Thread thread (&m_target, &m_engine, m_script.get ());
275+ auto ctx = code->createExecutionContext (&thread);
276+
277+ Value v = " test" ;
278+ EXPECT_CALL (m_mock, reporter (ctx.get (), &m_target, m_target.variableData (), m_target.listData ())).WillOnce (Return (v.data ()));
279+ ASSERT_EQ (Value (code->runReporter (ctx.get ())).toString (), v.toString ());
280+ }
281+
227282TEST_F (LLVMExecutableCodeTest, Promise)
228283{
229284 llvm::Function *mainFunc = beginMainFunction ();
@@ -242,7 +297,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
242297 // run()
243298 auto promise = std::make_shared<Promise>();
244299 ctx->setPromise (promise);
245- EXPECT_CALL (m_mock, f ).Times (0 );
300+ EXPECT_CALL (m_mock, script ).Times (0 );
246301
247302 for (int i = 0 ; i < 10 ; i++) {
248303 code->run (ctx.get ());
@@ -251,7 +306,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
251306
252307 promise->resolve ();
253308
254- EXPECT_CALL (m_mock, f );
309+ EXPECT_CALL (m_mock, script );
255310 code->run (ctx.get ());
256311 ASSERT_TRUE (code->isFinished (ctx.get ()));
257312 ASSERT_EQ (ctx->promise (), nullptr );
@@ -260,7 +315,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
260315 // kill()
261316 promise = std::make_shared<Promise>();
262317 ctx->setPromise (promise);
263- EXPECT_CALL (m_mock, f ).Times (0 );
318+ EXPECT_CALL (m_mock, script ).Times (0 );
264319
265320 for (int i = 0 ; i < 10 ; i++) {
266321 code->run (ctx.get ());
@@ -275,7 +330,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
275330 // reset()
276331 promise = std::make_shared<Promise>();
277332 ctx->setPromise (promise);
278- EXPECT_CALL (m_mock, f ).Times (0 );
333+ EXPECT_CALL (m_mock, script ).Times (0 );
279334
280335 for (int i = 0 ; i < 10 ; i++) {
281336 code->run (ctx.get ());
@@ -286,7 +341,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
286341 ASSERT_FALSE (code->isFinished (ctx.get ()));
287342 ASSERT_EQ (ctx->promise (), nullptr );
288343
289- EXPECT_CALL (m_mock, f );
344+ EXPECT_CALL (m_mock, script );
290345 code->run (ctx.get ());
291346 ASSERT_TRUE (code->isFinished (ctx.get ()));
292347
@@ -301,7 +356,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
301356
302357 promise = std::make_shared<Promise>();
303358 anotherCtx->setPromise (promise);
304- EXPECT_CALL (m_mock, f ).Times (0 );
359+ EXPECT_CALL (m_mock, script ).Times (0 );
305360
306361 for (int i = 0 ; i < 10 ; i++) {
307362 code->run (anotherCtx.get ());
@@ -310,7 +365,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
310365
311366 promise->resolve ();
312367
313- EXPECT_CALL (m_mock, f );
368+ EXPECT_CALL (m_mock, script );
314369 code->run (anotherCtx.get ());
315370 ASSERT_TRUE (code->isFinished (anotherCtx.get ()));
316371 ASSERT_TRUE (code->isFinished (ctx.get ()));
0 commit comments