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
24using namespace llvm;
25
26template <>
27void SSAContext::appendBlockDefs(SmallVectorImpl<Value *> &defs,
28 BasicBlock &block) {
29 for (auto &instr : block) {
30 if (instr.isTerminator())
31 break;
32 defs.push_back(Elt: &instr);
33 }
34}
35
36template <>
37void 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(Elt: &instr);
43 }
44}
45
46template <>
47void SSAContext::appendBlockTerms(SmallVectorImpl<Instruction *> &terms,
48 BasicBlock &block) {
49 terms.push_back(Elt: block.getTerminator());
50}
51
52template <>
53void SSAContext::appendBlockTerms(SmallVectorImpl<const Instruction *> &terms,
54 const BasicBlock &block) {
55 terms.push_back(Elt: block.getTerminator());
56}
57
58template <>
59const BasicBlock *SSAContext::getDefBlock(const Value *value) const {
60 if (const auto *instruction = dyn_cast<Instruction>(Val: value))
61 return instruction->getParent();
62 return nullptr;
63}
64
65template <>
66bool SSAContext::isConstantOrUndefValuePhi(const Instruction &Instr) {
67 if (auto *Phi = dyn_cast<PHINode>(Val: &Instr))
68 return Phi->hasConstantOrUndefValue();
69 return false;
70}
71
72template <> Intrinsic::ID SSAContext::getIntrinsicID(const Instruction &I) {
73 if (auto *CB = dyn_cast<CallBase>(Val: &I))
74 return CB->getIntrinsicID();
75 return Intrinsic::not_intrinsic;
76}
77
78template <> Printable SSAContext::print(const Value *V) const {
79 return Printable([V](raw_ostream &Out) { V->print(O&: Out); });
80}
81
82template <> Printable SSAContext::print(const Instruction *Inst) const {
83 return print(V: cast<Value>(Val: Inst));
84}
85
86template <> 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(F: *BB->getParent());
95 Out << MST.getLocalSlot(V: BB);
96 });
97}
98
99template <> Printable SSAContext::printAsOperand(const BasicBlock *BB) const {
100 return Printable([BB](raw_ostream &Out) { BB->printAsOperand(O&: Out); });
101}
102