/// compile_right - Emit code for '>' void BrainFTraceRecorder::compile_right(BrainFTraceNode *node, IRBuilder<>& builder) { Value *OldPtr = DataPtr; DataPtr = builder.CreateConstInBoundsGEP1_32(DataPtr, 1); if (node->left != (BrainFTraceNode*)~0ULL) compile_opcode(node->left, builder); else { HeaderPHI->addIncoming(DataPtr, builder.GetInsertBlock()); builder.CreateBr(Header); } DataPtr = OldPtr; }
/// 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); }