void InstructionReplace::insertStores(llvm::Module& M) { for(llvm::Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) { //if(!F->getFnAttributes().hasAttribute(Attributes::AttrVal::MaskedCopy)) { continue; } llvm::Function* Fun = maskedfn[F]; vector<Value*> outputshares; ReturnInst* tbd = NULL; auto arg = Fun->arg_begin(); for(unsigned int i = 0; i <= MaskingOrder; i++) { ++arg; } for(unsigned int i = 0; i <= MaskingOrder; i++) { outputshares.push_back(arg++); } for(llvm::Function::iterator BB = Fun->begin(), FE = Fun->end(); BB != FE; ++BB) { for( llvm::BasicBlock::iterator i = BB->begin(); i != BB->end(); i++) { if(tbd != NULL) {tbd->eraseFromParent(); tbd = NULL;} if(!isa<ReturnInst>(i)) {continue;} ReturnInst* ri = cast<ReturnInst>(i); IRBuilder<> ib = llvm::IRBuilder<>(BB->getContext()); ib.SetInsertPoint(i); vector<Value*> shares = MaskValue(ri->getReturnValue(), ri); for(unsigned int i = 0; i <= MaskingOrder; i++) { ib.CreateStore(shares[i], outputshares[i]); } ib.CreateRetVoid(); tbd = ri; } } if(tbd != NULL) {tbd->eraseFromParent(); tbd = NULL;} } }
Function* BuildProgramFromCanon(CNode* s, llvm::Module* module, int store_size) { CNodeCodeGenVisitor visitor(module, store_size); s->Accept(visitor); IRBuilder<> builder = visitor.GetLastBuilder(); builder.CreateRetVoid(); Function* func = visitor.GetMain(); return func; }
void CodeGenContext::generateCode(Block &root) { LLVMContext &gC = getGlobalContext(); // globalContext ArrayRef<Type*> argTypes; FunctionType *ftype = FunctionType::get(Type::getVoidTy(getGlobalContext()), argTypes, false); mainFunction = Function::Create(ftype, GlobalValue::InternalLinkage, "main", module); BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", mainFunction, 0); /* header */ // declare void @memset Type *memset_params_type[] = { Type::getInt8PtrTy(gC), Type::getInt32Ty(gC) }; Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset, memset_params_type); // declare i32 @getchar(i32) getchar_func = cast<Function>(module-> getOrInsertFunction("getchar", IntegerType::getInt32Ty(gC), NULL)); // declare i32 @putchar(i64) putchar_func = cast<Function>(module-> getOrInsertFunction("putchar", IntegerType::getInt64Ty(gC), IntegerType::getInt64Ty(gC), NULL)); /* Push a new variable/block context */ pushBlock(bblock); root.codeGen(*this); /* emit bytecode for the toplevel block */ BasicBlock *endblock = BasicBlock::Create(getGlobalContext(), "end", mainFunction, 0); IRBuilder<> *builder; builder = (*this).currentBuilder(); builder->CreateBr(endblock); builder->SetInsertPoint(endblock); builder->CreateRetVoid(); popBlock(); std::cout << "Code is generated.\n"; PassManager pm; pm.add(createPrintModulePass(&outs())); pm.run(*module); }
// ============================================================================= // 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; }
/// compile_if - Emit code for '[' void BrainFTraceRecorder::compile_if(BrainFTraceNode *node, IRBuilder<>& builder) { BasicBlock *ZeroChild = 0; BasicBlock *NonZeroChild = 0; BasicBlock *Parent = builder.GetInsertBlock(); LLVMContext &Context = Header->getContext(); // If both directions of the branch go back to the trace-head, just // jump there directly. if (node->left == (BrainFTraceNode*)~0ULL && node->right == (BrainFTraceNode*)~0ULL) { HeaderPHI->addIncoming(DataPtr, builder.GetInsertBlock()); builder.CreateBr(Header); return; } // Otherwise, there are two cases to handle for each direction: // ~0ULL - A branch back to the trace head // 0 - A branch out of the trace // * - A branch to a node we haven't compiled yet. // Go ahead and generate code for both targets. if (node->left == (BrainFTraceNode*)~0ULL) { NonZeroChild = Header; HeaderPHI->addIncoming(DataPtr, Parent); } else if (node->left == 0) { NonZeroChild = BasicBlock::Create(Context, "exit_left_"+utostr(node->pc), Header->getParent()); builder.SetInsertPoint(NonZeroChild); // Set the extension leaf, which is a pointer to the leaf of the trace // tree from which we are side exiting. ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node); builder.CreateStore(ExtLeaf, ext_leaf); ConstantInt *NewPc = ConstantInt::get(int_type, node->pc+1); Value *BytecodeIndex = builder.CreateConstInBoundsGEP1_32(bytecode_array, node->pc+1); Value *Target = builder.CreateLoad(BytecodeIndex); CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr)); Call->setTailCall(); builder.CreateRetVoid(); } else { NonZeroChild = BasicBlock::Create(Context, utostr(node->left->pc), Header->getParent()); builder.SetInsertPoint(NonZeroChild); compile_opcode(node->left, builder); } if (node->right == (BrainFTraceNode*)~0ULL) { ZeroChild = Header; HeaderPHI->addIncoming(DataPtr, Parent); } else if (node->right == 0) { ZeroChild = BasicBlock::Create(Context, "exit_right_"+utostr(node->pc), Header->getParent()); builder.SetInsertPoint(ZeroChild); // Set the extension leaf, which is a pointer to the leaf of the trace // tree from which we are side exiting. ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node); builder.CreateStore(ExtLeaf, ext_leaf); ConstantInt *NewPc = ConstantInt::get(int_type, JumpMap[node->pc]+1); Value *BytecodeIndex = builder.CreateConstInBoundsGEP1_32(bytecode_array, JumpMap[node->pc]+1); Value *Target = builder.CreateLoad(BytecodeIndex); CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr)); Call->setTailCall(); builder.CreateRetVoid(); } else { ZeroChild = BasicBlock::Create(Context, utostr(node->right->pc), Header->getParent()); builder.SetInsertPoint(ZeroChild); compile_opcode(node->right, builder); } // Generate the test and branch to select between the targets. builder.SetInsertPoint(Parent); Value *Loaded = builder.CreateLoad(DataPtr); Value *Cmp = builder.CreateICmpEQ(Loaded, ConstantInt::get(Loaded->getType(), 0)); builder.CreateCondBr(Cmp, ZeroChild, NonZeroChild); }
// ============================================================================= // 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; }