1//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- 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
9#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
10
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/DebugInfo/CodeView/CVRecord.h"
13#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
14#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
15#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
16#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
17#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
18#include "llvm/DebugInfo/PDB/PDBSymbol.h"
19#include "llvm/DebugInfo/PDB/PDBTypes.h"
20
21using namespace llvm;
22using namespace llvm::codeview;
23using namespace llvm::pdb;
24
25NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
26                                 LazyRandomTypeCollection &Types,
27                                 std::vector<codeview::TypeLeafKind> Kinds)
28    : Index(0), Session(PDBSession) {
29  std::optional<TypeIndex> TI = Types.getFirst();
30  while (TI) {
31    CVType CVT = Types.getType(*TI);
32    TypeLeafKind K = CVT.kind();
33    if (llvm::is_contained(Kinds, K)) {
34      // Don't add forward refs, we'll find those later while enumerating.
35      if (!isUdtForwardRef(CVT))
36        Matches.push_back(*TI);
37    } else if (K == TypeLeafKind::LF_MODIFIER) {
38      TypeIndex ModifiedTI = getModifiedType(CVT);
39      if (!ModifiedTI.isSimple()) {
40        CVType UnmodifiedCVT = Types.getType(ModifiedTI);
41        // LF_MODIFIERs point to forward refs, but don't worry about that
42        // here.  We're pushing the TypeIndex of the LF_MODIFIER itself,
43        // so we'll worry about resolving forward refs later.
44        if (llvm::is_contained(Kinds, UnmodifiedCVT.kind()))
45          Matches.push_back(*TI);
46      }
47    }
48    TI = Types.getNext(*TI);
49  }
50}
51
52NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
53                                 std::vector<codeview::TypeIndex> Indices)
54    : Matches(std::move(Indices)), Index(0), Session(PDBSession) {}
55
56uint32_t NativeEnumTypes::getChildCount() const {
57  return static_cast<uint32_t>(Matches.size());
58}
59
60std::unique_ptr<PDBSymbol> NativeEnumTypes::getChildAtIndex(uint32_t N) const {
61  if (N < Matches.size()) {
62    SymIndexId Id = Session.getSymbolCache().findSymbolByTypeIndex(Matches[N]);
63    return Session.getSymbolCache().getSymbolById(Id);
64  }
65  return nullptr;
66}
67
68std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
69  return getChildAtIndex(Index++);
70}
71
72void NativeEnumTypes::reset() { Index = 0; }
73