10eae32dcSDimitry Andric //===- SSAContext.cpp -------------------------------------------*- C++ -*-===// 20eae32dcSDimitry Andric // 30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60eae32dcSDimitry Andric // 70eae32dcSDimitry Andric //===----------------------------------------------------------------------===// 80eae32dcSDimitry Andric /// \file 90eae32dcSDimitry Andric /// 100eae32dcSDimitry Andric /// This file defines a specialization of the GenericSSAContext<X> 110eae32dcSDimitry Andric /// template class for LLVM IR. 120eae32dcSDimitry Andric /// 130eae32dcSDimitry Andric //===----------------------------------------------------------------------===// 140eae32dcSDimitry Andric 150eae32dcSDimitry Andric #include "llvm/IR/SSAContext.h" 16*bdd1243dSDimitry Andric #include "llvm/IR/Argument.h" 170eae32dcSDimitry Andric #include "llvm/IR/BasicBlock.h" 180eae32dcSDimitry Andric #include "llvm/IR/Function.h" 190eae32dcSDimitry Andric #include "llvm/IR/Instruction.h" 20*bdd1243dSDimitry Andric #include "llvm/IR/Instructions.h" 210eae32dcSDimitry Andric #include "llvm/Support/raw_ostream.h" 220eae32dcSDimitry Andric 230eae32dcSDimitry Andric using namespace llvm; 240eae32dcSDimitry Andric 25*bdd1243dSDimitry Andric Value *SSAContext::ValueRefNull = nullptr; 26*bdd1243dSDimitry Andric 27*bdd1243dSDimitry Andric void SSAContext::setFunction(Function &Fn) { F = &Fn; } 28*bdd1243dSDimitry Andric 290eae32dcSDimitry Andric BasicBlock *SSAContext::getEntryBlock(Function &F) { 300eae32dcSDimitry Andric return &F.getEntryBlock(); 310eae32dcSDimitry Andric } 320eae32dcSDimitry Andric 33*bdd1243dSDimitry Andric const BasicBlock *SSAContext::getEntryBlock(const Function &F) { 34*bdd1243dSDimitry Andric return &F.getEntryBlock(); 35*bdd1243dSDimitry Andric } 360eae32dcSDimitry Andric 37*bdd1243dSDimitry Andric void SSAContext::appendBlockDefs(SmallVectorImpl<Value *> &defs, 38*bdd1243dSDimitry Andric BasicBlock &block) { 39*bdd1243dSDimitry Andric for (auto &instr : block.instructionsWithoutDebug(/*SkipPseudoOp=*/true)) { 40*bdd1243dSDimitry Andric if (instr.isTerminator()) 41*bdd1243dSDimitry Andric break; 42*bdd1243dSDimitry Andric if (instr.getType()->isVoidTy()) 43*bdd1243dSDimitry Andric continue; 44*bdd1243dSDimitry Andric auto *def = &instr; 45*bdd1243dSDimitry Andric defs.push_back(def); 46*bdd1243dSDimitry Andric } 47*bdd1243dSDimitry Andric } 48*bdd1243dSDimitry Andric 49*bdd1243dSDimitry Andric void SSAContext::appendBlockDefs(SmallVectorImpl<const Value *> &defs, 50*bdd1243dSDimitry Andric const BasicBlock &block) { 51*bdd1243dSDimitry Andric for (auto &instr : block) { 52*bdd1243dSDimitry Andric if (instr.isTerminator()) 53*bdd1243dSDimitry Andric break; 54*bdd1243dSDimitry Andric defs.push_back(&instr); 55*bdd1243dSDimitry Andric } 56*bdd1243dSDimitry Andric } 57*bdd1243dSDimitry Andric 58*bdd1243dSDimitry Andric void SSAContext::appendBlockTerms(SmallVectorImpl<Instruction *> &terms, 59*bdd1243dSDimitry Andric BasicBlock &block) { 60*bdd1243dSDimitry Andric terms.push_back(block.getTerminator()); 61*bdd1243dSDimitry Andric } 62*bdd1243dSDimitry Andric 63*bdd1243dSDimitry Andric void SSAContext::appendBlockTerms(SmallVectorImpl<const Instruction *> &terms, 64*bdd1243dSDimitry Andric const BasicBlock &block) { 65*bdd1243dSDimitry Andric terms.push_back(block.getTerminator()); 66*bdd1243dSDimitry Andric } 67*bdd1243dSDimitry Andric 68*bdd1243dSDimitry Andric const BasicBlock *SSAContext::getDefBlock(const Value *value) const { 69*bdd1243dSDimitry Andric if (const auto *instruction = dyn_cast<Instruction>(value)) 70*bdd1243dSDimitry Andric return instruction->getParent(); 71*bdd1243dSDimitry Andric return nullptr; 72*bdd1243dSDimitry Andric } 73*bdd1243dSDimitry Andric 74*bdd1243dSDimitry Andric bool SSAContext::comesBefore(const Instruction *lhs, const Instruction *rhs) { 75*bdd1243dSDimitry Andric return lhs->comesBefore(rhs); 76*bdd1243dSDimitry Andric } 77*bdd1243dSDimitry Andric 78*bdd1243dSDimitry Andric bool SSAContext::isConstantValuePhi(const Instruction &Instr) { 79*bdd1243dSDimitry Andric if (auto *Phi = dyn_cast<PHINode>(&Instr)) 80*bdd1243dSDimitry Andric return Phi->hasConstantValue(); 81*bdd1243dSDimitry Andric return false; 82*bdd1243dSDimitry Andric } 83*bdd1243dSDimitry Andric 84*bdd1243dSDimitry Andric Printable SSAContext::print(const Value *V) const { 850eae32dcSDimitry Andric return Printable([V](raw_ostream &Out) { V->print(Out); }); 860eae32dcSDimitry Andric } 870eae32dcSDimitry Andric 88*bdd1243dSDimitry Andric Printable SSAContext::print(const Instruction *Inst) const { 890eae32dcSDimitry Andric return print(cast<Value>(Inst)); 900eae32dcSDimitry Andric } 910eae32dcSDimitry Andric 92*bdd1243dSDimitry Andric Printable SSAContext::print(const BasicBlock *BB) const { 93*bdd1243dSDimitry Andric if (!BB) 94*bdd1243dSDimitry Andric return Printable([](raw_ostream &Out) { Out << "<nullptr>"; }); 950eae32dcSDimitry Andric if (BB->hasName()) 960eae32dcSDimitry Andric return Printable([BB](raw_ostream &Out) { Out << BB->getName(); }); 970eae32dcSDimitry Andric 980eae32dcSDimitry Andric return Printable([BB](raw_ostream &Out) { 990eae32dcSDimitry Andric ModuleSlotTracker MST{BB->getParent()->getParent(), false}; 1000eae32dcSDimitry Andric MST.incorporateFunction(*BB->getParent()); 1010eae32dcSDimitry Andric Out << MST.getLocalSlot(BB); 1020eae32dcSDimitry Andric }); 1030eae32dcSDimitry Andric } 104