xref: /openbsd/gnu/llvm/llvm/lib/IR/TypeFinder.cpp (revision d415bd75)
109467b48Spatrick //===- TypeFinder.cpp - Implement the TypeFinder class --------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the TypeFinder class for the IR library.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/IR/TypeFinder.h"
1409467b48Spatrick #include "llvm/ADT/SmallVector.h"
1509467b48Spatrick #include "llvm/IR/BasicBlock.h"
1609467b48Spatrick #include "llvm/IR/Constant.h"
1773471bf0Spatrick #include "llvm/IR/DebugInfoMetadata.h"
1809467b48Spatrick #include "llvm/IR/DerivedTypes.h"
1909467b48Spatrick #include "llvm/IR/Function.h"
2009467b48Spatrick #include "llvm/IR/Instruction.h"
21*d415bd75Srobert #include "llvm/IR/Instructions.h"
2209467b48Spatrick #include "llvm/IR/Metadata.h"
2309467b48Spatrick #include "llvm/IR/Module.h"
24*d415bd75Srobert #include "llvm/IR/Operator.h"
2509467b48Spatrick #include "llvm/IR/Type.h"
2609467b48Spatrick #include "llvm/IR/Use.h"
2709467b48Spatrick #include "llvm/IR/User.h"
2809467b48Spatrick #include "llvm/IR/Value.h"
2909467b48Spatrick #include "llvm/Support/Casting.h"
3009467b48Spatrick #include <utility>
3109467b48Spatrick 
3209467b48Spatrick using namespace llvm;
3309467b48Spatrick 
run(const Module & M,bool onlyNamed)3409467b48Spatrick void TypeFinder::run(const Module &M, bool onlyNamed) {
3509467b48Spatrick   OnlyNamed = onlyNamed;
3609467b48Spatrick 
3709467b48Spatrick   // Get types from global variables.
3809467b48Spatrick   for (const auto &G : M.globals()) {
39*d415bd75Srobert     incorporateType(G.getValueType());
4009467b48Spatrick     if (G.hasInitializer())
4109467b48Spatrick       incorporateValue(G.getInitializer());
4209467b48Spatrick   }
4309467b48Spatrick 
4409467b48Spatrick   // Get types from aliases.
4509467b48Spatrick   for (const auto &A : M.aliases()) {
46*d415bd75Srobert     incorporateType(A.getValueType());
4709467b48Spatrick     if (const Value *Aliasee = A.getAliasee())
4809467b48Spatrick       incorporateValue(Aliasee);
4909467b48Spatrick   }
5009467b48Spatrick 
51*d415bd75Srobert   // Get types from ifuncs.
52*d415bd75Srobert   for (const auto &GI : M.ifuncs())
53*d415bd75Srobert     incorporateType(GI.getValueType());
54*d415bd75Srobert 
5509467b48Spatrick   // Get types from functions.
5609467b48Spatrick   SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst;
5709467b48Spatrick   for (const Function &FI : M) {
58*d415bd75Srobert     incorporateType(FI.getFunctionType());
59*d415bd75Srobert     incorporateAttributes(FI.getAttributes());
6009467b48Spatrick 
6109467b48Spatrick     for (const Use &U : FI.operands())
6209467b48Spatrick       incorporateValue(U.get());
6309467b48Spatrick 
6409467b48Spatrick     // First incorporate the arguments.
6509467b48Spatrick     for (const auto &A : FI.args())
6609467b48Spatrick       incorporateValue(&A);
6709467b48Spatrick 
6809467b48Spatrick     for (const BasicBlock &BB : FI)
6909467b48Spatrick       for (const Instruction &I : BB) {
7009467b48Spatrick         // Incorporate the type of the instruction.
7109467b48Spatrick         incorporateType(I.getType());
7209467b48Spatrick 
7309467b48Spatrick         // Incorporate non-instruction operand types. (We are incorporating all
7409467b48Spatrick         // instructions with this loop.)
7509467b48Spatrick         for (const auto &O : I.operands())
7609467b48Spatrick           if (&*O && !isa<Instruction>(&*O))
7709467b48Spatrick             incorporateValue(&*O);
7809467b48Spatrick 
79*d415bd75Srobert         if (auto *GEP = dyn_cast<GetElementPtrInst>(&I))
80*d415bd75Srobert           incorporateType(GEP->getSourceElementType());
81*d415bd75Srobert         if (auto *AI = dyn_cast<AllocaInst>(&I))
82*d415bd75Srobert           incorporateType(AI->getAllocatedType());
83*d415bd75Srobert         if (const auto *CB = dyn_cast<CallBase>(&I))
84*d415bd75Srobert           incorporateAttributes(CB->getAttributes());
85*d415bd75Srobert 
8609467b48Spatrick         // Incorporate types hiding in metadata.
8709467b48Spatrick         I.getAllMetadataOtherThanDebugLoc(MDForInst);
8809467b48Spatrick         for (const auto &MD : MDForInst)
8909467b48Spatrick           incorporateMDNode(MD.second);
9009467b48Spatrick         MDForInst.clear();
9109467b48Spatrick       }
9209467b48Spatrick   }
9309467b48Spatrick 
9409467b48Spatrick   for (const auto &NMD : M.named_metadata())
9509467b48Spatrick     for (const auto *MDOp : NMD.operands())
9609467b48Spatrick       incorporateMDNode(MDOp);
9709467b48Spatrick }
9809467b48Spatrick 
clear()9909467b48Spatrick void TypeFinder::clear() {
10009467b48Spatrick   VisitedConstants.clear();
10109467b48Spatrick   VisitedTypes.clear();
10209467b48Spatrick   StructTypes.clear();
10309467b48Spatrick }
10409467b48Spatrick 
10509467b48Spatrick /// incorporateType - This method adds the type to the list of used structures
10609467b48Spatrick /// if it's not in there already.
incorporateType(Type * Ty)10709467b48Spatrick void TypeFinder::incorporateType(Type *Ty) {
10809467b48Spatrick   // Check to see if we've already visited this type.
10909467b48Spatrick   if (!VisitedTypes.insert(Ty).second)
11009467b48Spatrick     return;
11109467b48Spatrick 
11209467b48Spatrick   SmallVector<Type *, 4> TypeWorklist;
11309467b48Spatrick   TypeWorklist.push_back(Ty);
11409467b48Spatrick   do {
11509467b48Spatrick     Ty = TypeWorklist.pop_back_val();
11609467b48Spatrick 
11709467b48Spatrick     // If this is a structure or opaque type, add a name for the type.
11809467b48Spatrick     if (StructType *STy = dyn_cast<StructType>(Ty))
11909467b48Spatrick       if (!OnlyNamed || STy->hasName())
12009467b48Spatrick         StructTypes.push_back(STy);
12109467b48Spatrick 
12209467b48Spatrick     // Add all unvisited subtypes to worklist for processing
123*d415bd75Srobert     for (Type *SubTy : llvm::reverse(Ty->subtypes()))
124*d415bd75Srobert       if (VisitedTypes.insert(SubTy).second)
125*d415bd75Srobert         TypeWorklist.push_back(SubTy);
12609467b48Spatrick   } while (!TypeWorklist.empty());
12709467b48Spatrick }
12809467b48Spatrick 
12909467b48Spatrick /// incorporateValue - This method is used to walk operand lists finding types
13009467b48Spatrick /// hiding in constant expressions and other operands that won't be walked in
13109467b48Spatrick /// other ways.  GlobalValues, basic blocks, instructions, and inst operands are
13209467b48Spatrick /// all explicitly enumerated.
incorporateValue(const Value * V)13309467b48Spatrick void TypeFinder::incorporateValue(const Value *V) {
13409467b48Spatrick   if (const auto *M = dyn_cast<MetadataAsValue>(V)) {
13509467b48Spatrick     if (const auto *N = dyn_cast<MDNode>(M->getMetadata()))
13609467b48Spatrick       return incorporateMDNode(N);
13709467b48Spatrick     if (const auto *MDV = dyn_cast<ValueAsMetadata>(M->getMetadata()))
13809467b48Spatrick       return incorporateValue(MDV->getValue());
13909467b48Spatrick     return;
14009467b48Spatrick   }
14109467b48Spatrick 
14209467b48Spatrick   if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
14309467b48Spatrick 
14409467b48Spatrick   // Already visited?
14509467b48Spatrick   if (!VisitedConstants.insert(V).second)
14609467b48Spatrick     return;
14709467b48Spatrick 
14809467b48Spatrick   // Check this type.
14909467b48Spatrick   incorporateType(V->getType());
15009467b48Spatrick 
15109467b48Spatrick   // If this is an instruction, we incorporate it separately.
15209467b48Spatrick   if (isa<Instruction>(V))
15309467b48Spatrick     return;
15409467b48Spatrick 
155*d415bd75Srobert   if (auto *GEP = dyn_cast<GEPOperator>(V))
156*d415bd75Srobert     incorporateType(GEP->getSourceElementType());
157*d415bd75Srobert 
15809467b48Spatrick   // Look in operands for types.
15909467b48Spatrick   const User *U = cast<User>(V);
16009467b48Spatrick   for (const auto &I : U->operands())
16109467b48Spatrick     incorporateValue(&*I);
16209467b48Spatrick }
16309467b48Spatrick 
16409467b48Spatrick /// incorporateMDNode - This method is used to walk the operands of an MDNode to
16509467b48Spatrick /// find types hiding within.
incorporateMDNode(const MDNode * V)16609467b48Spatrick void TypeFinder::incorporateMDNode(const MDNode *V) {
16709467b48Spatrick   // Already visited?
16809467b48Spatrick   if (!VisitedMetadata.insert(V).second)
16909467b48Spatrick     return;
17009467b48Spatrick 
17173471bf0Spatrick   // The arguments in DIArgList are not exposed as operands, so handle such
17273471bf0Spatrick   // nodes specifically here.
17373471bf0Spatrick   if (const auto *AL = dyn_cast<DIArgList>(V)) {
17473471bf0Spatrick     for (auto *Arg : AL->getArgs())
17573471bf0Spatrick       incorporateValue(Arg->getValue());
17673471bf0Spatrick     return;
17773471bf0Spatrick   }
17873471bf0Spatrick 
17909467b48Spatrick   // Look in operands for types.
18009467b48Spatrick   for (Metadata *Op : V->operands()) {
18109467b48Spatrick     if (!Op)
18209467b48Spatrick       continue;
18309467b48Spatrick     if (auto *N = dyn_cast<MDNode>(Op)) {
18409467b48Spatrick       incorporateMDNode(N);
18509467b48Spatrick       continue;
18609467b48Spatrick     }
18709467b48Spatrick     if (auto *C = dyn_cast<ConstantAsMetadata>(Op)) {
18809467b48Spatrick       incorporateValue(C->getValue());
18909467b48Spatrick       continue;
19009467b48Spatrick     }
19109467b48Spatrick   }
19209467b48Spatrick }
193*d415bd75Srobert 
incorporateAttributes(AttributeList AL)194*d415bd75Srobert void TypeFinder::incorporateAttributes(AttributeList AL) {
195*d415bd75Srobert   if (!VisitedAttributes.insert(AL).second)
196*d415bd75Srobert     return;
197*d415bd75Srobert 
198*d415bd75Srobert   for (AttributeSet AS : AL)
199*d415bd75Srobert     for (Attribute A : AS)
200*d415bd75Srobert       if (A.isTypeAttribute())
201*d415bd75Srobert         incorporateType(A.getValueAsType());
202*d415bd75Srobert }
203