77#include < llvm/IR/Verifier.h>
88
99#include < scratchcpp/target.h>
10+ #include < scratchcpp/blockprototype.h>
1011#include < iostream>
1112
1213#include " llvmcompilercontext.h"
@@ -70,9 +71,9 @@ void LLVMCompilerContext::addDefinedProcedure(BlockPrototype *prototype)
7071 m_definedProcedures.insert (prototype);
7172}
7273
73- void LLVMCompilerContext::addUsedProcedure (BlockPrototype *prototype, const std::string &functionName, llvm::FunctionType *functionType )
74+ void LLVMCompilerContext::addUsedProcedure (BlockPrototype *prototype, const std::string &functionName)
7475{
75- m_usedProcedures[prototype] = { functionName, functionType } ;
76+ m_usedProcedures[prototype] = functionName;
7677}
7778
7879function_id_t LLVMCompilerContext::getNextFunctionId ()
@@ -99,6 +100,9 @@ void LLVMCompilerContext::initJit()
99100 std::cout << " ==============" << std::endl << std::endl;
100101#endif
101102
103+ // Define shims for missing procedures
104+ createProcedureShims ();
105+
102106 // Optimize
103107 optimize (llvm::OptimizationLevel::O3);
104108
@@ -199,6 +203,27 @@ void LLVMCompilerContext::createTargetMachine()
199203 m_targetMachine = std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine (targetTriple, cpu, features, opt, llvm::Reloc::PIC_));
200204}
201205
206+ void LLVMCompilerContext::createProcedureShims ()
207+ {
208+ llvm::IRBuilder<> builder (*m_llvmCtx);
209+
210+ for (const auto &[prototype, name] : m_usedProcedures) {
211+ if (m_definedProcedures.find (prototype) == m_definedProcedures.cend ()) {
212+ std::cout << " warning: procedure \" " << prototype->procCode () << " \" is not defined" << std::endl;
213+
214+ // We need to define shims for undefined procedures (the JIT compiler crashes without them)
215+ llvm::Function *func = m_module->getFunction (name); // since the function is used, it's already declared
216+ llvm::BasicBlock *entry = llvm::BasicBlock::Create (*m_llvmCtx, " entry" , func);
217+ llvm::PointerType *pointerType = llvm::PointerType::get (*m_llvmCtx, 0 );
218+ llvm::Constant *nullPointer = llvm::ConstantPointerNull::get (pointerType);
219+ builder.SetInsertPoint (entry);
220+ builder.CreateRet (nullPointer);
221+
222+ verifyFunction (func);
223+ }
224+ }
225+ }
226+
202227void LLVMCompilerContext::optimize (llvm::OptimizationLevel optLevel)
203228{
204229 llvm::PassBuilder passBuilder (m_targetMachine.get ());
0 commit comments