Skip to content

Commit 30cb02a

Browse files
authored
Merge pull request #66688 from apple/block-list-cherry-pick-5.9
[5.9] Add support for an externally defined block list configuration file
2 parents f1bf558 + b19c45f commit 30cb02a

18 files changed

+438
-1
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/Basic/LangOptions.h"
3131
#include "swift/Basic/Located.h"
3232
#include "swift/Basic/Malloc.h"
33+
#include "swift/Basic/BlockList.h"
3334
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
3435
#include "clang/AST/DeclTemplate.h"
3536
#include "llvm/ADT/ArrayRef.h"
@@ -360,6 +361,8 @@ class ASTContext final {
360361
/// The Swift module currently being compiled.
361362
ModuleDecl *MainModule = nullptr;
362363

364+
/// The block list where we can find special actions based on module name;
365+
BlockListStore blockListConfig;
363366
private:
364367
/// The current generation number, which reflects the number of
365368
/// times that external modules have been loaded.

include/swift/Basic/BlockList.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- BlockList.h ---------------------------------------------*- C++ -*-===//
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+
// This file defines some miscellaneous overloads of hash_value() and
14+
// simple_display().
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_BASIC_BLOCKLIST_H
19+
#define SWIFT_BASIC_BLOCKLIST_H
20+
21+
#include "swift/Basic/LLVM.h"
22+
#include "llvm/ADT/StringRef.h"
23+
24+
namespace swift {
25+
26+
enum class BlockListAction: uint8_t {
27+
Undefined = 0,
28+
#define BLOCKLIST_ACTION(NAME) NAME,
29+
#include "BlockListAction.def"
30+
};
31+
32+
enum class BlockListKeyKind: uint8_t {
33+
Undefined = 0,
34+
ModuleName,
35+
ProjectName
36+
};
37+
38+
class BlockListStore {
39+
public:
40+
struct Implementation;
41+
void addConfigureFilePath(StringRef path);
42+
bool hasBlockListAction(StringRef key, BlockListKeyKind keyKind,
43+
BlockListAction action);
44+
BlockListStore();
45+
~BlockListStore();
46+
private:
47+
Implementation &Impl;
48+
};
49+
50+
} // namespace swift
51+
52+
#endif // SWIFT_BASIC_BLOCKLIST_H
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===--- BlockListAction.def - Define all blocklist actions -----*- C++ -*-===//
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+
// This definition file describes all block list actions for meta-programming
14+
// purposes.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef BLOCKLIST_ACTION
19+
#define BLOCKLIST_ACTION(NAME)
20+
#endif
21+
22+
BLOCKLIST_ACTION(ShouldUseBinaryModule)
23+
BLOCKLIST_ACTION(ShouldUseTextualModule)
24+
BLOCKLIST_ACTION(DowngradeInterfaceVerificationFailure)
25+
26+
#undef BLOCKLIST_ACTION

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,9 @@ namespace swift {
566566
/// The model of concurrency to be used.
567567
ConcurrencyModel ActiveConcurrencyModel = ConcurrencyModel::Standard;
568568

569+
/// All block list configuration files to be honored in this compilation.
570+
std::vector<std::string> BlocklistConfigFilePaths;
571+
569572
bool isConcurrencyModelTaskToThread() const {
570573
return ActiveConcurrencyModel == ConcurrencyModel::TaskToThread;
571574
}

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ class CompilerInvocation {
232232
/// options have been parsed.
233233
void setDefaultPrebuiltCacheIfNecessary();
234234

235+
/// If we haven't explicitly passed -blocklist-paths, set it to the default value.
236+
void setDefaultBlocklistsIfNecessary();
237+
235238
/// Computes the runtime resource path relative to the given Swift
236239
/// executable.
237240
static void computeRuntimeResourcePathFromExecutablePath(

include/swift/Frontend/FrontendOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ class FrontendOptions {
512512
/// textual imports
513513
bool EmitClangHeaderWithNonModularIncludes = false;
514514

515+
/// All block list configuration files to be honored in this compilation.
516+
std::vector<std::string> BlocklistConfigFilePaths;
515517
private:
516518
static bool canActionEmitDependencies(ActionType);
517519
static bool canActionEmitReferenceDependencies(ActionType);

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ def Raccess_note : Separate<["-"], "Raccess-note">,
240240
def Raccess_note_EQ : Joined<["-"], "Raccess-note=">,
241241
Alias<Raccess_note>;
242242

243+
def block_list_file
244+
: Separate<["-"], "blocklist-file">, MetaVarName<"<path>">,
245+
HelpText<"The path to a blocklist configuration file">;
243246
} // end let Flags = [FrontendOption, NoDriverOption]
244247

245248
def debug_crash_Group : OptionGroup<"<automatic crashing options>">;

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,10 @@ ASTContext::ASTContext(
694694
// Register any request-evaluator functions available at the AST layer.
695695
registerAccessRequestFunctions(evaluator);
696696
registerNameLookupRequestFunctions(evaluator);
697+
// Insert all block list config paths.
698+
for (auto path: langOpts.BlocklistConfigFilePaths) {
699+
blockListConfig.addConfigureFilePath(path);
700+
}
697701
}
698702

699703
ASTContext::~ASTContext() {

lib/Basic/BlockList.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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+
}

lib/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ add_swift_host_library(swiftBasic STATIC
7878
Unicode.cpp
7979
UUID.cpp
8080
Version.cpp
81+
BlockList.cpp
8182

8283
${llvm_revision_inc}
8384
${clang_revision_inc}

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ bool ArgsToFrontendOptionsConverter::convert(
350350
Opts.serializedPathObfuscator.addMapping(SplitMap.first, SplitMap.second);
351351
}
352352
Opts.emptyABIDescriptor = Args.hasArg(OPT_empty_abi_descriptor);
353+
for (auto A : Args.getAllArgValues(options::OPT_block_list_file)) {
354+
Opts.BlocklistConfigFilePaths.push_back(A);
355+
}
353356
return false;
354357
}
355358

lib/Frontend/CompilerInvocation.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,31 @@ void CompilerInvocation::setDefaultPrebuiltCacheIfNecessary() {
159159
(llvm::Twine(pair.first) + "preferred-interfaces" + pair.second).str();
160160
}
161161

162+
void CompilerInvocation::setDefaultBlocklistsIfNecessary() {
163+
if (!LangOpts.BlocklistConfigFilePaths.empty())
164+
return;
165+
if (SearchPathOpts.RuntimeResourcePath.empty())
166+
return;
167+
// XcodeDefault.xctoolchain/usr/lib/swift
168+
SmallString<64> blocklistDir{SearchPathOpts.RuntimeResourcePath};
169+
// XcodeDefault.xctoolchain/usr/lib
170+
llvm::sys::path::remove_filename(blocklistDir);
171+
// XcodeDefault.xctoolchain/usr
172+
llvm::sys::path::remove_filename(blocklistDir);
173+
// XcodeDefault.xctoolchain/usr/local/lib/swift/blocklists
174+
llvm::sys::path::append(blocklistDir, "local", "lib", "swift", "blocklists");
175+
std::error_code EC;
176+
if (llvm::sys::fs::is_directory(blocklistDir)) {
177+
for (llvm::sys::fs::directory_iterator F(blocklistDir, EC), FE;
178+
F != FE; F.increment(EC)) {
179+
StringRef ext = llvm::sys::path::extension(F->path());
180+
if (ext == "yml" || ext == "yaml") {
181+
LangOpts.BlocklistConfigFilePaths.push_back(F->path());
182+
}
183+
}
184+
}
185+
}
186+
162187
static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts,
163188
llvm::Triple &Triple) {
164189
llvm::SmallString<128> LibPath(SearchPathOpts.RuntimeResourcePath);
@@ -1211,6 +1236,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
12111236

12121237
Opts.DumpTypeWitnessSystems = Args.hasArg(OPT_dump_type_witness_systems);
12131238

1239+
for (auto &block: FrontendOpts.BlocklistConfigFilePaths)
1240+
Opts.BlocklistConfigFilePaths.push_back(block);
12141241
if (const Arg *A = Args.getLastArg(options::OPT_concurrency_model)) {
12151242
Opts.ActiveConcurrencyModel =
12161243
llvm::StringSwitch<ConcurrencyModel>(A->getValue())
@@ -2933,6 +2960,7 @@ bool CompilerInvocation::parseArgs(
29332960

29342961
updateRuntimeLibraryPaths(SearchPathOpts, LangOpts.Target);
29352962
setDefaultPrebuiltCacheIfNecessary();
2963+
setDefaultBlocklistsIfNecessary();
29362964

29372965
// Now that we've parsed everything, setup some inter-option-dependent state.
29382966
setIRGenOutputOptsFromFrontendOptions(IRGenOpts, FrontendOpts);

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization(
180180
return false;
181181
}
182182

183+
static bool shouldDowngradeInterfaceVerificationError(const FrontendOptions &opts,
184+
ASTContext &ctx) {
185+
return opts.DowngradeInterfaceVerificationError ||
186+
ctx.blockListConfig.hasBlockListAction(opts.ModuleName,
187+
BlockListKeyKind::ModuleName,
188+
BlockListAction::DowngradeInterfaceVerificationFailure);
189+
}
190+
183191
std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
184192
StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps,
185193
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
@@ -206,7 +214,8 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
206214
<< " to " << OutputPath << "\n");
207215

208216
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
209-
if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) {
217+
if (isTypeChecking &&
218+
shouldDowngradeInterfaceVerificationError(FEOpts, Instance.getASTContext())) {
210219
ErrorDowngradeConsumerRAII R(Instance.getDiags());
211220
Instance.performSema();
212221
return std::error_code();

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,13 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
17231723
// module cache path at this point.
17241724
if (buildModuleCacheDirIfAbsent && !moduleCachePath.empty())
17251725
(void)llvm::sys::fs::create_directories(moduleCachePath);
1726+
1727+
// Inherit all block list configuration files
1728+
frontendOpts.BlocklistConfigFilePaths = langOpts.BlocklistConfigFilePaths;
1729+
for (auto &blocklist: langOpts.BlocklistConfigFilePaths) {
1730+
GenericArgs.push_back("-blocklist-file");
1731+
GenericArgs.push_back(blocklist);
1732+
}
17261733
}
17271734

17281735
/// Calculate an output filename in \p genericSubInvocation's cache path that

0 commit comments

Comments
 (0)