//================================================ // Lambda-Calculus ASTs //================================================ //Lambda llvm::Function* LambdaAST::codeGen() const { // namedValues.clear(); llvm::Function* func = proto->codeGen(); if(!func) return NULL; // Create a new basic block to start insertion into. BasicBlock* entry = BasicBlock::Create(getGlobalContext(), "entry", func); ExprAST::builder.SetInsertPoint(entry); Value* returnVal = body->codeGen(); if(returnVal) { // Finish off the function ExprAST::builder.CreateRet(returnVal); // Validate the generated code, checking for consistency. verifyFunction(*func); // std::cout << "module: " << module << std::endl; // optimize the function passManager->run(*func); return func; } // Error reading Body, remove function func->eraseFromParent(); return NULL; }
MooseParsedFunction::MooseParsedFunction(const InputParameters & parameters) : Function(parameters), MooseParsedFunctionBase(parameters), _value(verifyFunction(getParam<std::string>("value"))), _function_ptr(NULL) { }
// DEPRECATED CONSTRUCTOR MooseParsedFunction::MooseParsedFunction(const std::string & deprecated_name, InputParameters parameters) : Function(deprecated_name, parameters), MooseParsedFunctionBase(parameters), _value(verifyFunction(getParam<std::string>("value"))), _function_ptr(NULL) { }
llvm::Function* LLVMCSRMatrixTest::getCSRMatrixGetNZTestFunc() { LLVMContext &ctx = context.getContext(); IRBuilder<> &builder = context.getBuilder(); Module *module = context.getModule(); getFunc = module->getFunction("test_csr_matrix_get_nz"); if (getFunc == 0) { // double csr_matrix_get_nz(const csr_matrix *mat, int row, int col); Type *argTypes[] = { ModelDataIRBuilder::getCSRSparseStructType(module)->getPointerTo(), Type::getInt32Ty(module->getContext()), Type::getInt32Ty(module->getContext()) }; FunctionType *funcType = FunctionType::get( Type::getDoubleTy(module->getContext()), argTypes, false); getFunc = Function::Create(funcType, Function::InternalLinkage, "test_csr_matrix_get_nz", module); // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(context.getContext(), "entry", getFunc); builder.SetInsertPoint(BB); std::vector<Value*> args; // Set names for all arguments. unsigned idx = 0; for (Function::arg_iterator ai = getFunc->arg_begin(); ai != getFunc->arg_end(); ++ai) { args.push_back(ai); } LLVMModelDataIRBuilderTesting mdirbuilder(LLVMModelDataSymbols(), builder); mdirbuilder.createDispInt(args[1]); mdirbuilder.createDispInt(args[2]); CallInst *call = ModelDataIRBuilder::createCSRMatrixGetNZ(builder, args[0], args[1], args[2], "nz_val"); mdirbuilder.createDispDouble(call); builder.CreateRet(call); // Validate the generated code, checking for consistency. verifyFunction(*getFunc); getFunc->dump(); } return setFunc; }
MooseParsedVectorFunction::MooseParsedVectorFunction(const InputParameters & parameters) : Function(parameters), MooseParsedFunctionBase(parameters), _vector_value(verifyFunction(std::string("{") + getParam<std::string>("value_x") + "}{" + getParam<std::string>("value_y") + "}{" + getParam<std::string>("value_z") + "}")) { }
/** * @brief Create llvm JIT Function and translate instructions to fill the JIT Function. * Optimize the llvm IR and save the function and its entry address to map. * * @param cpu CPU core structure */ static void cpu_translate_function(cpu_t *cpu) { BasicBlock *bb_ret, *bb_trap, *label_entry, *bb_start; addr_t start_addr = cpu->f.get_pc(cpu, cpu->rf.grf); /* create function and fill it with std basic blocks */ cpu->dyncom_engine->cur_func = cpu_create_function(cpu, "jitmain", &bb_ret, &bb_trap, &label_entry); /* TRANSLATE! */ UPDATE_TIMING(cpu, TIMER_FE, true); if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_SINGLESTEP) { bb_start = cpu_translate_singlestep(cpu, bb_ret, bb_trap); } else if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_SINGLESTEP_BB) { bb_start = cpu_translate_singlestep_bb(cpu, bb_ret, bb_trap); } else { bb_start = cpu_translate_all(cpu, bb_ret, bb_trap); } UPDATE_TIMING(cpu, TIMER_FE, false); /* finish entry basicblock */ BranchInst::Create(bb_start, label_entry); /* make sure everything is OK */ verifyFunction(*cpu->dyncom_engine->cur_func, AbortProcessAction); if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_PRINT_IR) cpu->dyncom_engine->mod->dump(); if (cpu->dyncom_engine->flags_codegen & CPU_CODEGEN_OPTIMIZE) { UPDATE_TIMING(cpu, TIMER_OPT, true); LOG("*** Optimizing..."); optimize(cpu); LOG("done.\n"); UPDATE_TIMING(cpu, TIMER_OPT, false); if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_PRINT_IR_OPTIMIZED) cpu->dyncom_engine->mod->dump(); } LOG("*** Translating..."); UPDATE_TIMING(cpu, TIMER_BE, true); cpu->dyncom_engine->fp[cpu->dyncom_engine->functions] = cpu->dyncom_engine->exec_engine->getPointerToFunction(cpu->dyncom_engine->cur_func); //cpu->dyncom_engine->fmap[start_addr] = cpu->dyncom_engine->fp[cpu->dyncom_engine->functions]; save_addr_in_func(cpu, cpu->dyncom_engine->fp[cpu->dyncom_engine->functions]); LOG("Generate native code for %x\n", start_addr); UPDATE_TIMING(cpu, TIMER_BE, false); LOG("done.\n"); cpu->dyncom_engine->functions++;/* Bug."functions" member could not be reset. */ }
//Let llvm::Function* LetAST::codeGen() const { namedValues.clear(); std::vector<llvm::Type*> argument_arity; // argument_arity.push_back(llvm::Type::getVoidTy(llvm::getGlobalContext())); FunctionType *functionType = FunctionType::get(arity,argument_arity, false); llvm ::Function* func = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, name, module); if(func->getName() != name) { func->eraseFromParent(); func = module->getFunction(name); if(!func->empty()) { ExprAST::errorV("redefinition of function"); return NULL; } } if(!func) return NULL; // Create a new basic block to start insertion into. BasicBlock* entry = BasicBlock::Create(getGlobalContext(), "entry", func); ExprAST::builder.SetInsertPoint(entry); Value* returnVal = body->codeGen(); if(returnVal) { // Finish off the function ExprAST::builder.CreateRet(returnVal); // Validate the generated code, checking for consistency. verifyFunction(*func); // std::cout << "module: " << module << std::endl; // optimize the function passManager->run(*func); return func; } // Error reading Body, remove function func->eraseFromParent(); return NULL; }
static void cpu_translate_function(cpu_t *cpu) { BasicBlock *bb_ret, *bb_trap, *label_entry, *bb_start; /* create function and fill it with std basic blocks */ cpu->cur_func = cpu_create_function(cpu, "jitmain", &bb_ret, &bb_trap, &label_entry); cpu->func[cpu->functions] = cpu->cur_func; /* TRANSLATE! */ update_timing(cpu, TIMER_FE, true); if (cpu->flags_debug & CPU_DEBUG_SINGLESTEP) { bb_start = cpu_translate_singlestep(cpu, bb_ret, bb_trap); } else if (cpu->flags_debug & CPU_DEBUG_SINGLESTEP_BB) { bb_start = cpu_translate_singlestep_bb(cpu, bb_ret, bb_trap); } else { bb_start = cpu_translate_all(cpu, bb_ret, bb_trap); } update_timing(cpu, TIMER_FE, false); /* finish entry basicblock */ BranchInst::Create(bb_start, label_entry); /* make sure everything is OK */ verifyFunction(*cpu->cur_func, PrintMessageAction); if (cpu->flags_debug & CPU_DEBUG_PRINT_IR) cpu->mod->dump(); if (cpu->flags_codegen & CPU_CODEGEN_OPTIMIZE) { LOG("*** Optimizing..."); optimize(cpu); LOG("done.\n"); if (cpu->flags_debug & CPU_DEBUG_PRINT_IR_OPTIMIZED) cpu->mod->dump(); } LOG("*** Translating..."); update_timing(cpu, TIMER_BE, true); cpu->fp[cpu->functions] = cpu->exec_engine->getPointerToFunction(cpu->cur_func); update_timing(cpu, TIMER_BE, false); LOG("done.\n"); cpu->functions++; }
llvm::Function * CodeGen::generateCodeDef(DefAST *ast) { // add def name to scope addScope(ast->name); // argument types vector<llvm::Type*> args(ast->args.size(), llvm::Type::getDoubleTy(context)); // return type auto retType = llvm::Type::getDoubleTy(context); // complete function type llvm::FunctionType *funcType = llvm::FunctionType::get(retType, args, false); llvm::Function * func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, ast->name, module.get()); unsigned i = 0; for (auto funcarg = func->arg_begin(); i != ast->args.size(); ++funcarg, ++i) { funcarg->setName(ast->args[i]); addScopedValue(ast->args[i], funcarg); } llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", func); Builder.SetInsertPoint(block); if (llvm::Value * result = generateCodeExpr(ast->body.get())) { Builder.CreateRet(result); string verifyS; llvm::raw_string_ostream verifyE(verifyS); if (verifyFunction(*func, &verifyE)) { func->eraseFromParent(); error = "something wrong with function \"" + ast->name + "\": " + verifyS; return nullptr; } // remove the def name scope removeScope(); return func; } else { func->eraseFromParent(); error = "error creating function body: " + error; return nullptr; } }
// ============================================================================= // andOOPIsGone (formerly: createProcess) // // Formerly, OOP permitted the same SC_{METHOD,THREAD} functions to apply // to each copy of a SC_MODULE. Aaaaand it's gone ! // (but OTOH we enable better optimizations) // Creates a new C-style function that calls the old member function with the // given sc_module. The call is then inlined. // FIXME: assumes the method is non-virtual and that sc_module is the first // inherited class of the SC_MODULE // ============================================================================= Function *TwetoPassImpl::andOOPIsGone(Function * oldProc, sc_core::sc_module * initiatorMod) { if (!oldProc) return NULL; // can't statically optimize if the address of the module isn't predictible // TODO: also handle already-static variables, which also have // fixed $pc-relative addresses if (staticopt == optlevel && !permalloc::is_from (initiatorMod)) return NULL; LLVMContext & context = getGlobalContext(); FunctionType *funType = oldProc->getFunctionType(); Type *type = funType->getParamType(0); FunctionType *newProcType = FunctionType::get(oldProc->getReturnType(), ArrayRef < Type * >(), false); // Create the new function std::ostringstream id; id << proc_counter++; std::string name = oldProc->getName().str() + std::string("_clone_") + id.str(); Function *newProc = Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod); assert(newProc->empty()); newProc->addFnAttr(Attribute::InlineHint); // Create call to old function BasicBlock *bb = BasicBlock::Create(context, "entry", newProc); IRBuilder <> *irb = new IRBuilder <> (context); irb->SetInsertPoint(bb); Value* thisAddr = createRelocatablePointer (type, initiatorMod, irb); CallInst *ci = irb->CreateCall(oldProc, ArrayRef < Value * >(std::vector<Value*>(1,thisAddr))); //bb->getInstList().insert(ci, thisAddr); if (ci->getType()->isVoidTy()) irb->CreateRetVoid(); else irb->CreateRet(ci); // The function should be valid now verifyFunction(*newProc); { // Inline the call DataLayout *td = new DataLayout(this->llvmMod); InlineFunctionInfo i(NULL, td); bool success = InlineFunction(ci, i); assert(success); verifyFunction(*newProc); } // further optimize the function inlineBasicIO (initiatorMod, newProc); newProc->dump(); return newProc; }
int main() { llvm::InitializeNativeTarget(); // Make the module, which holds all the code. llvm::Module *TheModule = new llvm::Module("my cool jit", llvm::getGlobalContext()); // Create the JIT. This takes ownership of the module. std::string ErrStr; llvm::ExecutionEngine *TheExecutionEngine = llvm::EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } llvm::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. OurFPM.add(new llvm::TargetData(*TheExecutionEngine->getTargetData())); // Do simple "peephole" optimizations and bit-twiddling optzns. OurFPM.add(llvm::createInstructionCombiningPass()); // Reassociate expressions. OurFPM.add(llvm::createReassociatePass()); // Eliminate Common SubExpressions. OurFPM.add(llvm::createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). OurFPM.add(llvm::createCFGSimplificationPass()); OurFPM.doInitialization(); // Set the global so the code gen can use this. llvm::FunctionPassManager *TheFPM = &OurFPM; // Single argument std::vector<const llvm::Type*> unaryArg(1,llvm::Type::getDoubleTy(llvm::getGlobalContext())); // Two arguments std::vector<const llvm::Type*> binaryArg(2,llvm::Type::getDoubleTy(llvm::getGlobalContext())); // Two arguments in and two references std::vector<const llvm::Type*> genArg(4); genArg[0] = genArg[1] = llvm::Type::getDoubleTy(llvm::getGlobalContext()); genArg[2] = genArg[3] = llvm::Type::getDoublePtrTy(llvm::getGlobalContext()); // Unary operation llvm::FunctionType *unaryFun = llvm::FunctionType::get(llvm::Type::getDoubleTy(llvm::getGlobalContext()),unaryArg, false); // Binary operation llvm::FunctionType *binaryFun = llvm::FunctionType::get(llvm::Type::getDoubleTy(llvm::getGlobalContext()),binaryArg, false); // More generic operation, return by reference llvm::FunctionType *genFun = llvm::FunctionType::get(llvm::Type::getVoidTy(llvm::getGlobalContext()),genArg, false); // Declare sin llvm::Function *sin_ = llvm::Function::Create(unaryFun, llvm::Function::ExternalLinkage, "sin", TheModule); // Declare my function llvm::Function *myfun = llvm::Function::Create(genFun, llvm::Function::ExternalLinkage, "myfcn", TheModule); // Create a new basic block to start insertion into. llvm::BasicBlock *BB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", myfun); Builder.SetInsertPoint(BB); // Set names for all arguments. llvm::Function::arg_iterator AI = myfun->arg_begin(); AI->setName("x1"); llvm::Value *x1 = AI; AI++; AI->setName("x2"); llvm::Value *x2 = AI; AI++; AI->setName("r1"); llvm::Value *r1 = AI; AI++; AI->setName("r2"); llvm::Value *r2 = AI; llvm::Value *five = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(5.0)); llvm::Value *x1_plus_5 = Builder.CreateFAdd(x1, five, "x1_plus_5"); // Call the sine function std::vector<llvm::Value*> sinarg(1,x2); llvm::Value* sin_x2 = Builder.CreateCall(sin_, sinarg.begin(), sinarg.end(), "callsin"); // Set values llvm::StoreInst *what_is_this1 = Builder.CreateStore(sin_x2,r1); llvm::StoreInst *what_is_this2 = Builder.CreateStore(x1_plus_5,r2); // Finish off the function. Builder.CreateRetVoid(); // Validate the generated code, checking for consistency. verifyFunction(*myfun); // Optimize the function. TheFPM->run(*myfun); // Print out all of the generated code. TheModule->dump(); // JIT the function double x1_val = 10; double x2_val = 20; double r1_val = -1; double r2_val = -1; typedef void (*GenType)(double,double,double*,double*); GenType FP = GenType(intptr_t(TheExecutionEngine->getPointerToFunction(myfun))); FP(x1_val,x2_val,&r1_val,&r2_val); printf("r1 = %g\n", r1_val); printf("r2 = %g\n", r2_val); return 0; }
bool CodeGen::wrapTopLevelBlockInMain(BlockAST *ast) { // add main to scope addScope("main"); vector<unique_ptr<ASTNode> > * body = ast->body.get(); // generate void main() llvm::FunctionType *voidType = llvm::FunctionType::get(Builder.getVoidTy(), false); llvm::Function *mainFunc = llvm::Function::Create(voidType, llvm::Function::ExternalLinkage, "main", module.get()); // basic block for the top level block llvm::BasicBlock *MainBlock = llvm::BasicBlock::Create(context, "entry", mainFunc); Builder.SetInsertPoint(MainBlock); llvm::Value * lastExpr; for (auto it = body->begin() ; it != body->end(); ++it) { ASTNode * node = it->get(); if (auto x = dynamic_cast<ValueAST*>(node)) { auto code = generateCodeValue(x); if (!code) return false; } else if (auto x = dynamic_cast<DefAST*>(node)) { generateCodeDef(x); Builder.SetInsertPoint(MainBlock); } else if (auto x = dynamic_cast<NumberExprAST*>(node)) { auto code = generateCodeNumber(x); if (!code) return false; lastExpr = code; } else if (auto x = dynamic_cast<BinaryExprAST*>(node)) { auto code = generateCodeBinOp(x); if (!code) return false; lastExpr = code; } else if (auto x = dynamic_cast<CallAST*>(node)) { auto code = generateCodeCall(x); if (!code) return false; lastExpr = code; } else { error = "can't handle ast"; return false; } } llvm::Value *fmt = Builder.CreateGlobalStringPtr("%lg\n"); vector<llvm::Type *> putsArgs; putsArgs.push_back(Builder.getInt8Ty()->getPointerTo()); llvm::ArrayRef<llvm::Type*> argsRef(putsArgs); llvm::FunctionType *putsType = llvm::FunctionType::get(Builder.getInt32Ty(), argsRef, true); llvm::Constant *putsFunc = module->getOrInsertFunction("printf", putsType); vector<llvm::Value *> CallArgs; CallArgs.push_back(fmt); CallArgs.push_back(lastExpr); Builder.CreateCall(putsFunc, CallArgs); Builder.CreateRetVoid(); string verifyS; llvm::raw_string_ostream verifyE(verifyS); if (verifyFunction(*mainFunc, &verifyE)) { mainFunc->eraseFromParent(); error = "something wrong with auto-generated main function: " + verifyS; return false; } // remove the main scope removeScope(); return true; }
// ============================================================================= // createProcess // // Create a new function that contains a call to the old function. // We inline the call in order to clone the old function's implementation. // ============================================================================= Function *TLMBasicPassImpl::createProcess(Function *oldProc, sc_core::sc_module *initiatorMod) { LLVMContext &context = getGlobalContext(); IntegerType *intType; if (this->is64Bit) { intType = Type::getInt64Ty(context); } else { intType = Type::getInt32Ty(context); } // Retrieve a pointer to the initiator module ConstantInt *initiatorModVal = ConstantInt::getSigned(intType,reinterpret_cast<intptr_t>(initiatorMod)); FunctionType *funType = oldProc->getFunctionType(); Type *type = funType->getParamType(0); IntToPtrInst *thisAddr = new IntToPtrInst(initiatorModVal, type, ""); // Compute the type of the new function FunctionType *oldProcType = oldProc->getFunctionType(); Value **argsBegin = new Value*[1]; Value **argsEnd = argsBegin; *argsEnd++ = thisAddr; const unsigned argsSize = argsEnd-argsBegin; Value **args = argsBegin; assert(oldProcType->getNumParams()==argsSize); assert(!oldProc->isDeclaration()); std::vector<Type*> argTypes; for (unsigned i = 0; i!=argsSize; ++i) argTypes.push_back(oldProcType->getParamType(i)); FunctionType *newProcType = FunctionType::get(oldProc->getReturnType(), ArrayRef<Type*>(argTypes), false); // Create the new function std::ostringstream id; id << proc_counter++; std::string name = oldProc->getName().str()+std::string("_clone_")+id.str(); Function *newProc = Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod); assert(newProc->empty()); newProc->addFnAttr(Attributes::InlineHint); { // Set name of newfunc arguments and complete args Function::arg_iterator nai = newProc->arg_begin(); Function::arg_iterator oai = oldProc->arg_begin(); for (unsigned i = 0; i!=argsSize; ++i, ++oai) { nai->setName(oai->getName()); args[i] = nai; ++nai; } assert(nai==newProc->arg_end()); assert(oai==oldProc->arg_end()); } // Create call to old function BasicBlock *bb = BasicBlock::Create(context, "entry", newProc); IRBuilder<> *irb = new IRBuilder<>(context); irb->SetInsertPoint(bb); CallInst *ci = irb->CreateCall(oldProc, ArrayRef<Value*>(argsBegin, argsEnd)); bb->getInstList().insert(ci, thisAddr); if (ci->getType()->isVoidTy()) irb->CreateRetVoid(); else irb->CreateRet(ci); // The function should be valid now verifyFunction(*newProc); { // Inline the call DataLayout *td = new DataLayout(this->llvmMod); InlineFunctionInfo i(NULL, td); bool success = InlineFunction(ci, i); assert(success); verifyFunction(*newProc); } //newProc->dump(); return newProc; }
// ============================================================================= // replaceCallsInProcess // // Replace indirect calls to write() or read() by direct calls // in the given process. // ============================================================================= void TLMBasicPassImpl::replaceCallsInProcess(sc_core::sc_module *initiatorMod, sc_core::sc_process_b *proc) { // Get associate function std::string fctName = proc->func_process; std::string modType = typeid(*initiatorMod).name(); std::string mainFctName = "_ZN" + modType + utostr(fctName.size()) + fctName + "Ev"; Function *oldProcf = this->llvmMod->getFunction(mainFctName); if (oldProcf==NULL) return; // We do not modifie the original function // Instead, we create a clone. Function *procf = createProcess(oldProcf, initiatorMod); void *funPtr = this->engine->getPointerToFunction(procf); sc_core::SC_ENTRY_FUNC_OPT scfun = reinterpret_cast<sc_core::SC_ENTRY_FUNC_OPT>(funPtr); proc->m_semantics_p = scfun; std::string procfName = procf->getName(); MSG(" Replace in the process's function : "+procfName+"\n"); std::ostringstream oss; sc_core::sc_module *targetMod; std::vector<CallInfo*> *work = new std::vector<CallInfo*>; inst_iterator ii; for (ii = inst_begin(procf); ii!=inst_end(procf); ii++) { Instruction &i = *ii; CallSite cs(&i); if (cs.getInstruction()) { // Candidate for a replacement Function *oldfun = cs.getCalledFunction(); if (oldfun!=NULL && !oldfun->isDeclaration()) { std::string name = oldfun->getName(); // === Write === if (!strcmp(name.c_str(), wFunName.c_str())) { CallInfo *info = new CallInfo(); info->oldcall = dyn_cast<CallInst>(cs.getInstruction()); MSG(" Checking adress : "); // Retrieve the adress argument by executing // the appropriated piece of code SCJit *scjit = new SCJit(this->llvmMod, this->elab); Process *irProc = this->elab->getProcess(proc); scjit->setCurrentProcess(irProc); bool jitErr = false; info->addrArg = cs.getArgument(1); int value = scjit->jitInt(procf, info->oldcall, info->addrArg, &jitErr); if(jitErr) { std::cout << " cannot get the address value!" << std::endl; } else { oss.str(""); oss << std::hex << value; MSG("0x"+oss.str()+"\n"); basic::addr_t a = static_cast<basic::addr_t>(value); // Checking address alignment if(value % sizeof(basic::data_t)) { std::cerr << " unaligned write : " << std::hex << value << std::endl; abort(); } // Retreive the target module using the address targetMod = getTargetModule(initiatorMod, a); // Save informations to build a new call later FunctionType *writeFunType = this->basicWriteFun->getFunctionType(); info->targetType = writeFunType->getParamType(0); LLVMContext &context = getGlobalContext(); IntegerType *intType; if (this->is64Bit) { intType = Type::getInt64Ty(context); } else { intType = Type::getInt32Ty(context); } info->targetModVal = ConstantInt::getSigned(intType, reinterpret_cast<intptr_t>(targetMod)); info->dataArg = cs.getArgument(2); work->push_back(info); } } else // === Read === if (!strcmp(name.c_str(), rFunName.c_str())) { // Not yet supported } } } } // Before //procf->dump(); // Replace calls std::vector<CallInfo*>::iterator it; for (it = work->begin(); it!=work->end(); ++it) { CallInfo *i = *it; LLVMContext &context = getGlobalContext(); FunctionType *writeFunType = this->writeFun->getFunctionType(); IntegerType *i64 = Type::getInt64Ty(context); // Get a pointer to the target module basic::target_module_base *tmb = dynamic_cast<basic::target_module_base*>(targetMod); Value *ptr = ConstantInt::getSigned(i64, reinterpret_cast<intptr_t>(tmb)); IntToPtrInst *modPtr = new IntToPtrInst(ptr, writeFunType->getParamType(0), "myitp", i->oldcall); // Get a the address value LoadInst *addr = new LoadInst(i->addrArg, "", i->oldcall); // Create the new call Value *args[] = {modPtr, addr, i->dataArg}; i->newcall = CallInst::Create(this->writeFun, ArrayRef<Value*>(args, 3)); // Replace the old call BasicBlock::iterator it(i->oldcall); ReplaceInstWithInst(i->oldcall->getParent()->getInstList(), it, i->newcall); i->oldcall->replaceAllUsesWith(i->newcall); // Inline the new call DataLayout *td = new DataLayout(this->llvmMod); InlineFunctionInfo ifi(NULL, td); bool success = InlineFunction(i->newcall, ifi); if(!success) { MSG(" The call cannot be inlined (it's not an error :D)"); } MSG(" Call optimized (^_-)\n"); callOptCounter++; } //std::cout << "==================================\n"; // Run preloaded passes on the function to propagate constants funPassManager->run(*procf); // After //procf->dump(); // Check if the function is corrupt verifyFunction(*procf); this->engine->recompileAndRelinkFunction(procf); }
bool CompiledCondition::compile(){ InitializeNativeTarget(); // Assume we're on main thread... LLVMContext &context = getGlobalContext(); // Initialize module Module* module = new Module("Compiled function", context); // Create exection engine ExecutionEngine* engine = EngineBuilder(module).create(); /********** Generate code **********/ //Get a type for representing an integer pointer //Maybe this should be unsigned integer pointer type... PointerType* integerPointerType = PointerType::get(IntegerType::get(module->getContext(), 32), 0); //Create function type, for our function, int*, int* -> bool vector<const Type*> paramType; paramType.push_back(integerPointerType); paramType.push_back(integerPointerType); FunctionType* functionType = FunctionType::get(IntegerType::get(module->getContext(), 8), paramType, false); //Declare new function Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "evaluate", module); //Use C calling convention function->setCallingConv(CallingConv::C); //TODO: Read documentation and reconsider this //Get arguments from function Function::arg_iterator args = function->arg_begin(); Value* marking = args++; Value* valuation = args++; marking->setName("marking"); valuation->setName("valuation"); //Create function block BasicBlock* functionBlock = BasicBlock::Create(module->getContext(), "functionBlock", function, 0); //Generate code CodeGenerationContext codeGenContext(marking, valuation, functionBlock, context); Value* result = _cond->codegen(codeGenContext); //Zero extend the result, e.g. make it a 8 bit bool CastInst* retval = new ZExtInst(result, IntegerType::get(module->getContext(), 8), "retval", functionBlock); //Create a return instruction ReturnInst::Create(module->getContext(), retval, functionBlock); /********** Optimize and Compile **********/ // Create function pass manager, to optimize query FunctionPassManager optimizer(module); optimizer.add(new TargetData(*engine->getTargetData())); optimizer.add(createBasicAliasAnalysisPass()); optimizer.add(createInstructionCombiningPass()); optimizer.add(createReassociatePass()); optimizer.add(createGVNPass()); optimizer.add(createCFGSimplificationPass()); optimizer.doInitialization(); // Verify function, errors written to stderr if(verifyFunction(*function)) return false; // Optimize function optimizer.run(*function); // Compile the function _nativeFunction = (bool(*)(const MarkVal*, const VarVal*))engine->getPointerToFunction(function); return _nativeFunction != NULL; }