Value* EqualExpression::getValue() { assert(leftExpression != NULL); assert(rightExpression != NULL); assert(leftExpression->getType() == rightExpression->getType()); IRBuilder<>* builder = codegen::getBuilder(); int c; if(leftExpression->getType() != COLEXPRESSION) { c = leftExpression->getType(); } else { c = convertDTtoET(leftExpression->getDataType()); } switch(c) { case LONGVALUEEXPRESSION: return builder->CreateICmpEQ(leftExpression->getValue(), rightExpression->getValue()); case DOUBLEVALUEEXPRESSION: return builder->CreateFCmpOEQ(leftExpression->getValue(), rightExpression->getValue()); case STRINGVALUEEXPRESSION: case DATEVALUEEXPRESSION: return codegen::stringCmp(leftExpression->getValue(), rightExpression->getValue(), EQUALEXPRESSION); default: cout << "Unknown expression type!" << endl; exit(-1); } return NULL; }
// Rewrite final suspend point handling. We do not use suspend index to // represent the final suspend point. Instead we zero-out ResumeFnAddr in the // coroutine frame, since it is undefined behavior to resume a coroutine // suspended at the final suspend point. Thus, in the resume function, we can // simply remove the last case (when coro::Shape is built, the final suspend // point (if present) is always the last element of CoroSuspends array). // In the destroy function, we add a code sequence to check if ResumeFnAddress // is Null, and if so, jump to the appropriate label to handle cleanup from the // final suspend point. static void handleFinalSuspend(IRBuilder<> &Builder, Value *FramePtr, coro::Shape &Shape, SwitchInst *Switch, bool IsDestroy) { assert(Shape.HasFinalSuspend); auto FinalCaseIt = std::prev(Switch->case_end()); BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor(); Switch->removeCase(FinalCaseIt); if (IsDestroy) { BasicBlock *OldSwitchBB = Switch->getParent(); auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch"); Builder.SetInsertPoint(OldSwitchBB->getTerminator()); auto *GepIndex = Builder.CreateConstInBoundsGEP2_32(Shape.FrameTy, FramePtr, 0, 0, "ResumeFn.addr"); auto *Load = Builder.CreateLoad(GepIndex); auto *NullPtr = ConstantPointerNull::get(cast<PointerType>(Load->getType())); auto *Cond = Builder.CreateICmpEQ(Load, NullPtr); Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB); OldSwitchBB->getTerminator()->eraseFromParent(); } }
void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function *function) { BasicBlock *beforeCallBB = call->getParent(); BasicBlock *callBB = SplitBlock(beforeCallBB, call, Owner); BasicBlock *inlineBB = BasicBlock::Create(Context, "inline", callBB->getParent()); BasicBlock::iterator iter = call; iter++; BasicBlock *afterCallBB = SplitBlock(iter->getParent(), iter, Owner); removeTerminator(beforeCallBB); // Put a branch before the call, testing whether the callee really is the // function IRBuilder<> B = IRBuilder<>(beforeCallBB); Value *callee = isa<CallInst>(call) ? cast<CallInst>(call)->getCalledValue() : cast<InvokeInst>(call)->getCalledValue(); const FunctionType *FTy = function->getFunctionType(); const FunctionType *calleeTy = cast<FunctionType>( cast<PointerType>(callee->getType())->getElementType()); if (calleeTy != FTy) { callee = B.CreateBitCast(callee, function->getType()); } Value *isInlineValid = B.CreateICmpEQ(callee, function); B.CreateCondBr(isInlineValid, inlineBB, callBB); // In the inline BB, add a copy of the call, but this time calling the real // version. Instruction *inlineCall = call->clone(); Value *inlineResult= inlineCall; inlineBB->getInstList().push_back(inlineCall); B.SetInsertPoint(inlineBB); if (calleeTy != FTy) { for (unsigned i=0 ; i<FTy->getNumParams() ; i++) { LLVMType *callType = calleeTy->getParamType(i); LLVMType *argType = FTy->getParamType(i); if (callType != argType) { inlineCall->setOperand(i, new BitCastInst(inlineCall->getOperand(i), argType, "", inlineCall)); } } if (FTy->getReturnType() != calleeTy->getReturnType()) { if (FTy->getReturnType() == Type::getVoidTy(Context)) { inlineResult = Constant::getNullValue(calleeTy->getReturnType()); } else { inlineResult = new BitCastInst(inlineCall, calleeTy->getReturnType(), "", inlineBB); } } } B.CreateBr(afterCallBB); // Unify the return values if (call->getType() != Type::getVoidTy(Context)) { PHINode *phi = CreatePHI(call->getType(), 2, "", afterCallBB->begin()); call->replaceAllUsesWith(phi); phi->addIncoming(call, callBB); phi->addIncoming(inlineResult, inlineBB); } // Really do the real inlining InlineFunctionInfo IFI(0, 0); if (CallInst *c = dyn_cast<CallInst>(inlineCall)) { c->setCalledFunction(function); InlineFunction(c, IFI); } else if (InvokeInst *c = dyn_cast<InvokeInst>(inlineCall)) { c->setCalledFunction(function); InlineFunction(c, IFI); } }
/// 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); }
static Value* emitCond(IRBuilder<>& builder, Value* arg) { return builder.CreateICmpEQ(arg, builder.getInt64(0)); }