|
| 1 | +//===--- BlockList.cpp - BlockList utilities ------------------------------===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | +// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | + |
| 13 | +#include "llvm/ADT/STLExtras.h" |
| 14 | +#include "llvm/ADT/StringSwitch.h" |
| 15 | +#include "llvm/Support/YAMLParser.h" |
| 16 | +#include "llvm/Support/YAMLTraits.h" |
| 17 | +#include "swift/Basic/BlockList.h" |
| 18 | +#include "swift/Basic/SourceManager.h" |
| 19 | + |
| 20 | +struct swift::BlockListStore::Implementation { |
| 21 | + SourceManager SM; |
| 22 | + llvm::StringMap<std::vector<BlockListAction>> ModuleActionDict; |
| 23 | + llvm::StringMap<std::vector<BlockListAction>> ProjectActionDict; |
| 24 | + void addConfigureFilePath(StringRef path); |
| 25 | + bool hasBlockListAction(StringRef key, BlockListKeyKind keyKind, |
| 26 | + BlockListAction action); |
| 27 | + void collectBlockList(llvm::yaml::Node *N, BlockListAction action); |
| 28 | + |
| 29 | + llvm::StringMap<std::vector<BlockListAction>> *getDictToUse(BlockListKeyKind kind) { |
| 30 | + switch (kind) { |
| 31 | + case BlockListKeyKind::ModuleName: |
| 32 | + return &ModuleActionDict; |
| 33 | + case BlockListKeyKind::ProjectName: |
| 34 | + return &ProjectActionDict; |
| 35 | + case BlockListKeyKind::Undefined: |
| 36 | + return nullptr; |
| 37 | + } |
| 38 | + } |
| 39 | + static std::string getScalaString(llvm::yaml::Node *N) { |
| 40 | + llvm::SmallString<64> Buffer; |
| 41 | + if (auto *scala = dyn_cast<llvm::yaml::ScalarNode>(N)) { |
| 42 | + return scala->getValue(Buffer).str(); |
| 43 | + } |
| 44 | + return std::string(); |
| 45 | + } |
| 46 | +}; |
| 47 | + |
| 48 | +swift::BlockListStore::BlockListStore(): Impl(*new Implementation()) {} |
| 49 | + |
| 50 | +swift::BlockListStore::~BlockListStore() { delete &Impl; } |
| 51 | + |
| 52 | +bool swift::BlockListStore::hasBlockListAction(StringRef key, |
| 53 | + BlockListKeyKind keyKind, BlockListAction action) { |
| 54 | + return Impl.hasBlockListAction(key, keyKind, action); |
| 55 | +} |
| 56 | + |
| 57 | +void swift::BlockListStore::addConfigureFilePath(StringRef path) { |
| 58 | + Impl.addConfigureFilePath(path); |
| 59 | +} |
| 60 | + |
| 61 | +bool swift::BlockListStore::Implementation::hasBlockListAction(StringRef key, |
| 62 | + BlockListKeyKind keyKind, BlockListAction action) { |
| 63 | + auto *dict = getDictToUse(keyKind); |
| 64 | + assert(dict); |
| 65 | + auto it = dict->find(key); |
| 66 | + if (it == dict->end()) |
| 67 | + return false; |
| 68 | + return llvm::is_contained(it->second, action); |
| 69 | +} |
| 70 | + |
| 71 | +void swift::BlockListStore::Implementation::collectBlockList(llvm::yaml::Node *N, |
| 72 | + BlockListAction action) { |
| 73 | + namespace yaml = llvm::yaml; |
| 74 | + auto *pair = dyn_cast<yaml::KeyValueNode>(N); |
| 75 | + if (!pair) |
| 76 | + return; |
| 77 | + std::string rawKey = getScalaString(pair->getKey()); |
| 78 | + auto keyKind = llvm::StringSwitch<BlockListKeyKind>(rawKey) |
| 79 | +#define CASE(X) .Case(#X, BlockListKeyKind::X) |
| 80 | + CASE(ModuleName) |
| 81 | + CASE(ProjectName) |
| 82 | +#undef CASE |
| 83 | + .Default(BlockListKeyKind::Undefined); |
| 84 | + if (keyKind == BlockListKeyKind::Undefined) |
| 85 | + return; |
| 86 | + auto *dictToUse = getDictToUse(keyKind); |
| 87 | + assert(dictToUse); |
| 88 | + auto *seq = dyn_cast<yaml::SequenceNode>(pair->getValue()); |
| 89 | + if (!seq) |
| 90 | + return; |
| 91 | + for (auto &node: *seq) { |
| 92 | + std::string name = getScalaString(&node); |
| 93 | + dictToUse->insert({name, std::vector<BlockListAction>()}) |
| 94 | + .first->second.push_back(action); |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +void swift::BlockListStore::Implementation::addConfigureFilePath(StringRef path) { |
| 99 | + namespace yaml = llvm::yaml; |
| 100 | + |
| 101 | + // Load the input file. |
| 102 | + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = |
| 103 | + vfs::getFileOrSTDIN(*SM.getFileSystem(), path, |
| 104 | + /*FileSize*/-1, /*RequiresNullTerminator*/true, |
| 105 | + /*IsVolatile*/false, /*RetryCount*/30); |
| 106 | + if (!FileBufOrErr) { |
| 107 | + return; |
| 108 | + } |
| 109 | + StringRef Buffer = FileBufOrErr->get()->getBuffer(); |
| 110 | + yaml::Stream Stream(llvm::MemoryBufferRef(Buffer, path), |
| 111 | + SM.getLLVMSourceMgr()); |
| 112 | + for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) { |
| 113 | + assert(DI != Stream.end() && "Failed to read a document"); |
| 114 | + yaml::Node *N = DI->getRoot(); |
| 115 | + for (auto &pair: *dyn_cast<yaml::MappingNode>(N)) { |
| 116 | + std::string key = getScalaString(pair.getKey()); |
| 117 | + auto action = llvm::StringSwitch<BlockListAction>(key) |
| 118 | +#define BLOCKLIST_ACTION(X) .Case(#X, BlockListAction::X) |
| 119 | +#include "swift/Basic/BlockListAction.def" |
| 120 | + .Default(BlockListAction::Undefined); |
| 121 | + if (action == BlockListAction::Undefined) |
| 122 | + continue; |
| 123 | + auto *map = dyn_cast<yaml::MappingNode>(pair.getValue()); |
| 124 | + if (!map) |
| 125 | + continue; |
| 126 | + for (auto &innerPair: *map) { |
| 127 | + collectBlockList(&innerPair, action); |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | +} |
0 commit comments