1deaf6951SEugene Zelenko //===- TypeFinder.cpp - Implement the TypeFinder class --------------------===//
2ef860a24SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef860a24SChandler Carruth //
7ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
8ef860a24SChandler Carruth //
9ef860a24SChandler Carruth // This file implements the TypeFinder class for the IR library.
10ef860a24SChandler Carruth //
11ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
12ef860a24SChandler Carruth
136bda14b3SChandler Carruth #include "llvm/IR/TypeFinder.h"
14ef860a24SChandler Carruth #include "llvm/ADT/SmallVector.h"
159fb823bbSChandler Carruth #include "llvm/IR/BasicBlock.h"
16deaf6951SEugene Zelenko #include "llvm/IR/Constant.h"
17b6e1fb7eSDavid Stenberg #include "llvm/IR/DebugInfoMetadata.h"
189fb823bbSChandler Carruth #include "llvm/IR/DerivedTypes.h"
199fb823bbSChandler Carruth #include "llvm/IR/Function.h"
20deaf6951SEugene Zelenko #include "llvm/IR/Instruction.h"
212c0fb962SNikita Popov #include "llvm/IR/Instructions.h"
229fb823bbSChandler Carruth #include "llvm/IR/Metadata.h"
239fb823bbSChandler Carruth #include "llvm/IR/Module.h"
242c0fb962SNikita Popov #include "llvm/IR/Operator.h"
25deaf6951SEugene Zelenko #include "llvm/IR/Type.h"
26deaf6951SEugene Zelenko #include "llvm/IR/Use.h"
27deaf6951SEugene Zelenko #include "llvm/IR/User.h"
28deaf6951SEugene Zelenko #include "llvm/IR/Value.h"
29deaf6951SEugene Zelenko #include "llvm/Support/Casting.h"
30deaf6951SEugene Zelenko #include <utility>
31deaf6951SEugene Zelenko
32ef860a24SChandler Carruth using namespace llvm;
33ef860a24SChandler Carruth
run(const Module & M,bool onlyNamed)34ef860a24SChandler Carruth void TypeFinder::run(const Module &M, bool onlyNamed) {
35ef860a24SChandler Carruth OnlyNamed = onlyNamed;
36ef860a24SChandler Carruth
37ef860a24SChandler Carruth // Get types from global variables.
3843472274SVedant Kumar for (const auto &G : M.globals()) {
392c0fb962SNikita Popov incorporateType(G.getValueType());
4043472274SVedant Kumar if (G.hasInitializer())
4143472274SVedant Kumar incorporateValue(G.getInitializer());
42ef860a24SChandler Carruth }
43ef860a24SChandler Carruth
44ef860a24SChandler Carruth // Get types from aliases.
4543472274SVedant Kumar for (const auto &A : M.aliases()) {
462c0fb962SNikita Popov incorporateType(A.getValueType());
4743472274SVedant Kumar if (const Value *Aliasee = A.getAliasee())
48ef860a24SChandler Carruth incorporateValue(Aliasee);
49ef860a24SChandler Carruth }
50ef860a24SChandler Carruth
51*97916673SNikita Popov // Get types from ifuncs.
52*97916673SNikita Popov for (const auto &GI : M.ifuncs())
53*97916673SNikita Popov incorporateType(GI.getValueType());
54*97916673SNikita Popov
55ef860a24SChandler Carruth // Get types from functions.
56de36e804SDuncan P. N. Exon Smith SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst;
57af28e7d6SBenjamin Kramer for (const Function &FI : M) {
582c0fb962SNikita Popov incorporateType(FI.getFunctionType());
592c0fb962SNikita Popov incorporateAttributes(FI.getAttributes());
60ef860a24SChandler Carruth
61af28e7d6SBenjamin Kramer for (const Use &U : FI.operands())
623a63fb31SVedant Kumar incorporateValue(U.get());
637fddeccbSDavid Majnemer
64ef860a24SChandler Carruth // First incorporate the arguments.
6543472274SVedant Kumar for (const auto &A : FI.args())
6643472274SVedant Kumar incorporateValue(&A);
67ef860a24SChandler Carruth
68af28e7d6SBenjamin Kramer for (const BasicBlock &BB : FI)
69af28e7d6SBenjamin Kramer for (const Instruction &I : BB) {
70ef860a24SChandler Carruth // Incorporate the type of the instruction.
71ef860a24SChandler Carruth incorporateType(I.getType());
72ef860a24SChandler Carruth
73ef860a24SChandler Carruth // Incorporate non-instruction operand types. (We are incorporating all
74ef860a24SChandler Carruth // instructions with this loop.)
7543472274SVedant Kumar for (const auto &O : I.operands())
7643472274SVedant Kumar if (&*O && !isa<Instruction>(&*O))
7743472274SVedant Kumar incorporateValue(&*O);
78ef860a24SChandler Carruth
792c0fb962SNikita Popov if (auto *GEP = dyn_cast<GetElementPtrInst>(&I))
802c0fb962SNikita Popov incorporateType(GEP->getSourceElementType());
812c0fb962SNikita Popov if (auto *AI = dyn_cast<AllocaInst>(&I))
822c0fb962SNikita Popov incorporateType(AI->getAllocatedType());
832c0fb962SNikita Popov if (const auto *CB = dyn_cast<CallBase>(&I))
842c0fb962SNikita Popov incorporateAttributes(CB->getAttributes());
852c0fb962SNikita Popov
86ef860a24SChandler Carruth // Incorporate types hiding in metadata.
87ef860a24SChandler Carruth I.getAllMetadataOtherThanDebugLoc(MDForInst);
8843472274SVedant Kumar for (const auto &MD : MDForInst)
8943472274SVedant Kumar incorporateMDNode(MD.second);
90ef860a24SChandler Carruth MDForInst.clear();
91ef860a24SChandler Carruth }
92ef860a24SChandler Carruth }
93ef860a24SChandler Carruth
9443472274SVedant Kumar for (const auto &NMD : M.named_metadata())
958dc7b982SMark de Wever for (const auto *MDOp : NMD.operands())
9643472274SVedant Kumar incorporateMDNode(MDOp);
97ef860a24SChandler Carruth }
98ef860a24SChandler Carruth
clear()99ef860a24SChandler Carruth void TypeFinder::clear() {
100ef860a24SChandler Carruth VisitedConstants.clear();
101ef860a24SChandler Carruth VisitedTypes.clear();
102ef860a24SChandler Carruth StructTypes.clear();
103ef860a24SChandler Carruth }
104ef860a24SChandler Carruth
105ef860a24SChandler Carruth /// incorporateType - This method adds the type to the list of used structures
106ef860a24SChandler Carruth /// if it's not in there already.
incorporateType(Type * Ty)107ef860a24SChandler Carruth void TypeFinder::incorporateType(Type *Ty) {
10870b66f0dSWill Dietz // Check to see if we've already visited this type.
109ef860a24SChandler Carruth if (!VisitedTypes.insert(Ty).second)
110ef860a24SChandler Carruth return;
111ef860a24SChandler Carruth
11270b66f0dSWill Dietz SmallVector<Type *, 4> TypeWorklist;
11370b66f0dSWill Dietz TypeWorklist.push_back(Ty);
11470b66f0dSWill Dietz do {
11570b66f0dSWill Dietz Ty = TypeWorklist.pop_back_val();
11670b66f0dSWill Dietz
117ef860a24SChandler Carruth // If this is a structure or opaque type, add a name for the type.
118ef860a24SChandler Carruth if (StructType *STy = dyn_cast<StructType>(Ty))
119ef860a24SChandler Carruth if (!OnlyNamed || STy->hasName())
120ef860a24SChandler Carruth StructTypes.push_back(STy);
121ef860a24SChandler Carruth
12270b66f0dSWill Dietz // Add all unvisited subtypes to worklist for processing
1237ca14f60SKazu Hirata for (Type *SubTy : llvm::reverse(Ty->subtypes()))
1247ca14f60SKazu Hirata if (VisitedTypes.insert(SubTy).second)
1257ca14f60SKazu Hirata TypeWorklist.push_back(SubTy);
12670b66f0dSWill Dietz } while (!TypeWorklist.empty());
127ef860a24SChandler Carruth }
128ef860a24SChandler Carruth
129ef860a24SChandler Carruth /// incorporateValue - This method is used to walk operand lists finding types
130ef860a24SChandler Carruth /// hiding in constant expressions and other operands that won't be walked in
131ef860a24SChandler Carruth /// other ways. GlobalValues, basic blocks, instructions, and inst operands are
132ef860a24SChandler Carruth /// all explicitly enumerated.
incorporateValue(const Value * V)133ef860a24SChandler Carruth void TypeFinder::incorporateValue(const Value *V) {
1345bf8fef5SDuncan P. N. Exon Smith if (const auto *M = dyn_cast<MetadataAsValue>(V)) {
1355bf8fef5SDuncan P. N. Exon Smith if (const auto *N = dyn_cast<MDNode>(M->getMetadata()))
1365bf8fef5SDuncan P. N. Exon Smith return incorporateMDNode(N);
1375bf8fef5SDuncan P. N. Exon Smith if (const auto *MDV = dyn_cast<ValueAsMetadata>(M->getMetadata()))
1385bf8fef5SDuncan P. N. Exon Smith return incorporateValue(MDV->getValue());
1395bf8fef5SDuncan P. N. Exon Smith return;
1405bf8fef5SDuncan P. N. Exon Smith }
141ef860a24SChandler Carruth
142ef860a24SChandler Carruth if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
143ef860a24SChandler Carruth
144ef860a24SChandler Carruth // Already visited?
145ef860a24SChandler Carruth if (!VisitedConstants.insert(V).second)
146ef860a24SChandler Carruth return;
147ef860a24SChandler Carruth
148ef860a24SChandler Carruth // Check this type.
149ef860a24SChandler Carruth incorporateType(V->getType());
150ef860a24SChandler Carruth
151ef860a24SChandler Carruth // If this is an instruction, we incorporate it separately.
152ef860a24SChandler Carruth if (isa<Instruction>(V))
153ef860a24SChandler Carruth return;
154ef860a24SChandler Carruth
1552c0fb962SNikita Popov if (auto *GEP = dyn_cast<GEPOperator>(V))
1562c0fb962SNikita Popov incorporateType(GEP->getSourceElementType());
1572c0fb962SNikita Popov
158ef860a24SChandler Carruth // Look in operands for types.
159ef860a24SChandler Carruth const User *U = cast<User>(V);
16043472274SVedant Kumar for (const auto &I : U->operands())
16143472274SVedant Kumar incorporateValue(&*I);
162ef860a24SChandler Carruth }
163ef860a24SChandler Carruth
164ef860a24SChandler Carruth /// incorporateMDNode - This method is used to walk the operands of an MDNode to
165ef860a24SChandler Carruth /// find types hiding within.
incorporateMDNode(const MDNode * V)166ef860a24SChandler Carruth void TypeFinder::incorporateMDNode(const MDNode *V) {
167ef860a24SChandler Carruth // Already visited?
1685bf8fef5SDuncan P. N. Exon Smith if (!VisitedMetadata.insert(V).second)
169ef860a24SChandler Carruth return;
170ef860a24SChandler Carruth
171b6e1fb7eSDavid Stenberg // The arguments in DIArgList are not exposed as operands, so handle such
172b6e1fb7eSDavid Stenberg // nodes specifically here.
173b6e1fb7eSDavid Stenberg if (const auto *AL = dyn_cast<DIArgList>(V)) {
174b6e1fb7eSDavid Stenberg for (auto *Arg : AL->getArgs())
175b6e1fb7eSDavid Stenberg incorporateValue(Arg->getValue());
176b6e1fb7eSDavid Stenberg return;
177b6e1fb7eSDavid Stenberg }
178b6e1fb7eSDavid Stenberg
179ef860a24SChandler Carruth // Look in operands for types.
18043472274SVedant Kumar for (Metadata *Op : V->operands()) {
1815bf8fef5SDuncan P. N. Exon Smith if (!Op)
1825bf8fef5SDuncan P. N. Exon Smith continue;
1835bf8fef5SDuncan P. N. Exon Smith if (auto *N = dyn_cast<MDNode>(Op)) {
1845bf8fef5SDuncan P. N. Exon Smith incorporateMDNode(N);
1855bf8fef5SDuncan P. N. Exon Smith continue;
1865bf8fef5SDuncan P. N. Exon Smith }
1875bf8fef5SDuncan P. N. Exon Smith if (auto *C = dyn_cast<ConstantAsMetadata>(Op)) {
1885bf8fef5SDuncan P. N. Exon Smith incorporateValue(C->getValue());
1895bf8fef5SDuncan P. N. Exon Smith continue;
1905bf8fef5SDuncan P. N. Exon Smith }
1915bf8fef5SDuncan P. N. Exon Smith }
192ef860a24SChandler Carruth }
1932c0fb962SNikita Popov
incorporateAttributes(AttributeList AL)1942c0fb962SNikita Popov void TypeFinder::incorporateAttributes(AttributeList AL) {
1952c0fb962SNikita Popov if (!VisitedAttributes.insert(AL).second)
1962c0fb962SNikita Popov return;
1972c0fb962SNikita Popov
1982c0fb962SNikita Popov for (AttributeSet AS : AL)
1992c0fb962SNikita Popov for (Attribute A : AS)
2002c0fb962SNikita Popov if (A.isTypeAttribute())
2012c0fb962SNikita Popov incorporateType(A.getValueAsType());
2022c0fb962SNikita Popov }
203