1717
1818using namespace libscratchcpp ;
1919
20+ using ::testing::Return;
21+
2022class LLVMExecutableCodeTest : public testing ::Test
2123{
2224 public:
@@ -34,11 +36,12 @@ class LLVMExecutableCodeTest : public testing::Test
3436
3537 inline llvm::Constant *nullPointer () { return llvm::ConstantPointerNull::get (llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 )); }
3638
37- llvm::Function *beginMainFunction ()
39+ llvm::Function *beginMainFunction (bool predicate = false )
3840 {
3941 // void *f(ExecutionContext *, Target *, ValueData **, List **)
42+ // bool f(...) (hat predicates)
4043 llvm::Type *pointerType = llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 );
41- llvm::FunctionType *funcType = llvm::FunctionType::get (pointerType, { pointerType, pointerType, pointerType, pointerType }, false );
44+ llvm::FunctionType *funcType = llvm::FunctionType::get (predicate ? m_builder-> getInt1Ty () : pointerType, { pointerType, pointerType, pointerType, pointerType }, false );
4245 llvm::Function *func = llvm::Function::Create (funcType, llvm::Function::ExternalLinkage, " f" , m_module);
4346
4447 llvm::BasicBlock *entry = llvm::BasicBlock::Create (*m_llvmCtx, " entry" , func);
@@ -70,6 +73,17 @@ class LLVMExecutableCodeTest : public testing::Test
7073 m_builder->CreateCall (func, { mockPtr, mainFunc->getArg (0 ), mainFunc->getArg (1 ), mainFunc->getArg (2 ), mainFunc->getArg (3 ) });
7174 }
7275
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 ));
80+
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);
83+
84+ return m_builder->CreateCall (func, { mockPtr, mainFunc->getArg (0 ), mainFunc->getArg (1 ), mainFunc->getArg (2 ), mainFunc->getArg (3 ) });
85+ }
86+
7387 void addTestPrintFunction (llvm::Value *arg1, llvm::Value *arg2)
7488 {
7589 auto ptrType = llvm::PointerType::get (llvm::Type::getInt8Ty (*m_llvmCtx), 0 );
@@ -95,13 +109,34 @@ TEST_F(LLVMExecutableCodeTest, CreateExecutionContext)
95109 llvm::Function *resumeFunc = beginResumeFunction ();
96110 endFunction (m_builder->getInt1 (true ));
97111
98- auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str ());
99- m_script->setCode (code);
100- Thread thread (&m_target, &m_engine, m_script.get ());
101- auto ctx = code->createExecutionContext (&thread);
102- ASSERT_TRUE (ctx);
103- ASSERT_EQ (ctx->thread (), &thread);
104- ASSERT_TRUE (dynamic_cast <LLVMExecutionContext *>(ctx.get ()));
112+ {
113+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), false );
114+ m_script->setCode (code);
115+ Thread thread (&m_target, &m_engine, m_script.get ());
116+ auto ctx = code->createExecutionContext (&thread);
117+ ASSERT_TRUE (ctx);
118+ ASSERT_EQ (ctx->thread (), &thread);
119+ ASSERT_TRUE (dynamic_cast <LLVMExecutionContext *>(ctx.get ()));
120+ }
121+ }
122+
123+ TEST_F (LLVMExecutableCodeTest, CreatePredicateExecutionContext)
124+ {
125+ llvm::Function *mainFunc = beginMainFunction (true );
126+ endFunction (m_builder->getInt1 (false ));
127+
128+ llvm::Function *resumeFunc = beginResumeFunction ();
129+ endFunction (m_builder->getInt1 (true ));
130+
131+ {
132+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), true );
133+ m_script->setCode (code);
134+ Thread thread (&m_target, &m_engine, m_script.get ());
135+ auto ctx = code->createExecutionContext (&thread);
136+ ASSERT_TRUE (ctx);
137+ ASSERT_EQ (ctx->thread (), &thread);
138+ ASSERT_TRUE (dynamic_cast <LLVMExecutionContext *>(ctx.get ()));
139+ }
105140}
106141
107142TEST_F (LLVMExecutableCodeTest, MainFunction)
@@ -116,7 +151,7 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
116151 llvm::Function *resumeFunc = beginResumeFunction ();
117152 endFunction (m_builder->getInt1 (true ));
118153
119- auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str ());
154+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), false );
120155 m_script->setCode (code);
121156 Thread thread (&m_target, &m_engine, m_script.get ());
122157 auto ctx = code->createExecutionContext (&thread);
@@ -160,6 +195,35 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
160195 ASSERT_FALSE (code->isFinished (ctx.get ()));
161196}
162197
198+ TEST_F (LLVMExecutableCodeTest, PredicateFunction)
199+ {
200+ m_target.addVariable (std::make_shared<Variable>(" " , " " ));
201+ m_target.addList (std::make_shared<List>(" " , " " ));
202+
203+ llvm::Function *mainFunc = beginMainFunction (true );
204+ endFunction (addPredicateFunction (mainFunc));
205+
206+ llvm::Function *resumeFunc = beginResumeFunction ();
207+ endFunction (m_builder->getInt1 (true ));
208+
209+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), true );
210+ m_script->setCode (code);
211+ Thread thread (&m_target, &m_engine, m_script.get ());
212+ auto ctx = code->createExecutionContext (&thread);
213+
214+ EXPECT_CALL (m_mock, predicate (ctx.get (), &m_target, m_target.variableData (), m_target.listData ())).WillOnce (Return (true ));
215+ ASSERT_TRUE (code->runPredicate (ctx.get ()));
216+
217+ EXPECT_CALL (m_mock, predicate (ctx.get (), &m_target, m_target.variableData (), m_target.listData ())).WillOnce (Return (true ));
218+ ASSERT_TRUE (code->runPredicate (ctx.get ()));
219+
220+ EXPECT_CALL (m_mock, predicate (ctx.get (), &m_target, m_target.variableData (), m_target.listData ())).WillOnce (Return (false ));
221+ ASSERT_FALSE (code->runPredicate (ctx.get ()));
222+
223+ EXPECT_CALL (m_mock, predicate (ctx.get (), &m_target, m_target.variableData (), m_target.listData ())).WillOnce (Return (false ));
224+ ASSERT_FALSE (code->runPredicate (ctx.get ()));
225+ }
226+
163227TEST_F (LLVMExecutableCodeTest, Promise)
164228{
165229 llvm::Function *mainFunc = beginMainFunction ();
@@ -169,7 +233,7 @@ TEST_F(LLVMExecutableCodeTest, Promise)
169233 llvm::Function *resumeFunc = beginResumeFunction ();
170234 endFunction (m_builder->getInt1 (true ));
171235
172- auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str ());
236+ auto code = std::make_shared<LLVMExecutableCode>(m_ctx.get (), mainFunc->getName ().str (), resumeFunc->getName ().str (), false );
173237 m_script->setCode (code);
174238 Thread thread (&m_target, &m_engine, m_script.get ());
175239 auto ctx = code->createExecutionContext (&thread);
0 commit comments