1 //===- SSAContext.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file defines a specialization of the GenericSSAContext<X> 11 /// template class for LLVM IR. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/SSAContext.h" 16 #include "llvm/IR/Argument.h" 17 #include "llvm/IR/BasicBlock.h" 18 #include "llvm/IR/Function.h" 19 #include "llvm/IR/Instructions.h" 20 #include "llvm/IR/Intrinsics.h" 21 #include "llvm/IR/ModuleSlotTracker.h" 22 #include "llvm/Support/raw_ostream.h" 23 24 using namespace llvm; 25 26 template <> 27 void SSAContext::appendBlockDefs(SmallVectorImpl<Value *> &defs, 28 BasicBlock &block) { 29 for (auto &instr : block) { 30 if (instr.isTerminator()) 31 break; 32 defs.push_back(&instr); 33 } 34 } 35 36 template <> 37 void SSAContext::appendBlockDefs(SmallVectorImpl<const Value *> &defs, 38 const BasicBlock &block) { 39 for (auto &instr : block) { 40 if (instr.isTerminator()) 41 break; 42 defs.push_back(&instr); 43 } 44 } 45 46 template <> 47 void SSAContext::appendBlockTerms(SmallVectorImpl<Instruction *> &terms, 48 BasicBlock &block) { 49 terms.push_back(block.getTerminator()); 50 } 51 52 template <> 53 void SSAContext::appendBlockTerms(SmallVectorImpl<const Instruction *> &terms, 54 const BasicBlock &block) { 55 terms.push_back(block.getTerminator()); 56 } 57 58 template <> 59 const BasicBlock *SSAContext::getDefBlock(const Value *value) const { 60 if (const auto *instruction = dyn_cast<Instruction>(value)) 61 return instruction->getParent(); 62 return nullptr; 63 } 64 65 template <> 66 bool SSAContext::isConstantOrUndefValuePhi(const Instruction &Instr) { 67 if (auto *Phi = dyn_cast<PHINode>(&Instr)) 68 return Phi->hasConstantOrUndefValue(); 69 return false; 70 } 71 72 template <> Intrinsic::ID SSAContext::getIntrinsicID(const Instruction &I) { 73 if (auto *CB = dyn_cast<CallBase>(&I)) 74 return CB->getIntrinsicID(); 75 return Intrinsic::not_intrinsic; 76 } 77 78 template <> Printable SSAContext::print(const Value *V) const { 79 return Printable([V](raw_ostream &Out) { V->print(Out); }); 80 } 81 82 template <> Printable SSAContext::print(const Instruction *Inst) const { 83 return print(cast<Value>(Inst)); 84 } 85 86 template <> Printable SSAContext::print(const BasicBlock *BB) const { 87 if (!BB) 88 return Printable([](raw_ostream &Out) { Out << "<nullptr>"; }); 89 if (BB->hasName()) 90 return Printable([BB](raw_ostream &Out) { Out << BB->getName(); }); 91 92 return Printable([BB](raw_ostream &Out) { 93 ModuleSlotTracker MST{BB->getParent()->getParent(), false}; 94 MST.incorporateFunction(*BB->getParent()); 95 Out << MST.getLocalSlot(BB); 96 }); 97 } 98 99 template <> Printable SSAContext::printAsOperand(const BasicBlock *BB) const { 100 return Printable([BB](raw_ostream &Out) { BB->printAsOperand(Out); }); 101 } 102