Skip to content

Commit ba5e344

Browse files
authored
Merge pull request #23518 from eeckstein/onone-support-abi
Stabilize the ABI of libswiftSwiftOnoneSupport
2 parents c6b4ded + 00599ee commit ba5e344

File tree

15 files changed

+1436
-90
lines changed

15 files changed

+1436
-90
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ ERROR(circular_transparent,none,
252252
NOTE(note_while_inlining,none,
253253
"while inlining here", ())
254254

255+
// Pre-specializations
256+
ERROR(cannot_prespecialize,none,
257+
"Cannot pre-specialize %0", (StringRef))
258+
ERROR(missing_prespecialization,none,
259+
"Pre-specialized function %0 missing in SwiftOnoneSupport module",
260+
(StringRef))
261+
255262
// Arithmetic diagnostics.
256263
ERROR(integer_conversion_overflow,none,
257264
"integer overflows when converted from %0 to %1",

include/swift/Demangling/Demangle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class Node {
221221
// Only to be used by the demangler parsers.
222222
void addChild(NodePointer Child, NodeFactory &Factory);
223223
// Only to be used by the demangler parsers.
224-
void removeChildAt(unsigned Pos, NodeFactory &factory);
224+
void removeChildAt(unsigned Pos);
225225

226226
// Reverses the order of children.
227227
void reverseChildren(size_t StartingAt = 0);

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ class FrontendOptions {
158158
/// module appears to not be a public module.
159159
Optional<bool> SerializeOptionsForDebugging;
160160

161+
/// When true, check if all required SwiftOnoneSupport symbols are present in
162+
/// the module.
163+
bool CheckOnoneSupportCompleteness = false;
164+
161165
/// If set, inserts instrumentation useful for testing the debugger.
162166
bool DebuggerTestingTransform = false;
163167

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ def import_module : Separate<["-"], "import-module">,
416416
def print_stats : Flag<["-"], "print-stats">,
417417
HelpText<"Print various statistics">;
418418

419+
def check_onone_completeness : Flag<["-"], "check-onone-completeness">,
420+
HelpText<"Print errors if the compile OnoneSupport module is missing symbols">;
421+
419422
def debugger_testing_transform : Flag<["-"], "debugger-testing-transform">,
420423
HelpText<"Instrument the code with calls to an intrinsic that record the expected values of "
421424
"local variables so they can be compared against the results from the debugger.">;

include/swift/SIL/SILModule.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,16 @@ class SILModule {
266266
SILModule(const SILModule&) = delete;
267267
void operator=(const SILModule&) = delete;
268268

269-
/// Method which returns the SerializedSILLoader, creating the loader if it
270-
/// has not been created yet.
271-
SerializedSILLoader *getSILLoader();
272-
273269
/// Folding set for key path patterns.
274270
llvm::FoldingSet<KeyPathPattern> KeyPathPatterns;
275271

276272
public:
277273
~SILModule();
278274

275+
/// Method which returns the SerializedSILLoader, creating the loader if it
276+
/// has not been created yet.
277+
SerializedSILLoader *getSILLoader();
278+
279279
/// Add a callback for each newly deserialized SIL function body.
280280
void registerDeserializationNotificationHandler(
281281
std::unique_ptr<DeserializationNotificationHandler> &&handler);

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,12 @@ class GenericFuncSpecializer {
319319
/// prespecialization for -Onone support.
320320
bool isKnownPrespecialization(StringRef SpecName);
321321

322+
/// Checks if all OnoneSupport pre-specializations are included in the module
323+
/// as public functions.
324+
///
325+
/// Issues errors for all missing functions.
326+
void checkCompletenessOfPrespecializations(SILModule &M);
327+
322328
/// Create a new apply based on an old one, but with a different
323329
/// function being applied.
324330
ApplySite replaceWithSpecializedFunction(ApplySite AI, SILFunction *NewF,

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ void Node::addChild(NodePointer Child, NodeFactory &Factory) {
355355
}
356356
}
357357

358-
void Node::removeChildAt(unsigned Pos, swift::Demangle::NodeFactory &factory) {
358+
void Node::removeChildAt(unsigned Pos) {
359359
switch (NodePayloadKind) {
360360
case PayloadKind::OneChild:
361361
assert(Pos == 0);
@@ -1255,7 +1255,7 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
12551255
auto Label = getChildIf(Param, Node::Kind::TupleElementName);
12561256

12571257
if (Label.first) {
1258-
Param->removeChildAt(Label.second, *this);
1258+
Param->removeChildAt(Label.second);
12591259
return createNodeWithAllocatedText(Node::Kind::Identifier,
12601260
Label.first->getText());
12611261
}

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ bool ArgsToFrontendOptionsConverter::convert(
9696
setUnsignedIntegerArgument(OPT_switch_checking_invocation_threshold_EQ, 10,
9797
Opts.SwitchCheckingInvocationThreshold);
9898

99+
Opts.CheckOnoneSupportCompleteness = Args.hasArg(OPT_check_onone_completeness);
100+
99101
Opts.DebuggerTestingTransform = Args.hasArg(OPT_debugger_testing_transform);
100102

101103
computePlaygroundOptions();

lib/Frontend/Frontend.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "swift/Parse/Lexer.h"
3030
#include "swift/SIL/SILModule.h"
3131
#include "swift/SILOptimizer/PassManager/Passes.h"
32+
#include "swift/SILOptimizer/Utils/Generics.h"
3233
#include "swift/Serialization/SerializationOptions.h"
3334
#include "swift/Serialization/SerializedModuleLoader.h"
3435
#include "swift/Strings.h"
@@ -1110,6 +1111,11 @@ static void performSILOptimizations(CompilerInvocation &Invocation,
11101111
} else {
11111112
runSILOptimizationPasses(*SM);
11121113
}
1114+
if (Invocation.getFrontendOptions().CheckOnoneSupportCompleteness &&
1115+
// TODO: handle non-ObjC based stdlib builds, e.g. on linux.
1116+
Invocation.getLangOptions().EnableObjCInterop) {
1117+
checkCompletenessOfPrespecializations(*SM);
1118+
}
11131119
}
11141120

11151121
static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 97 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616
#include "swift/AST/GenericEnvironment.h"
1717
#include "swift/AST/GenericSignatureBuilder.h"
1818
#include "swift/AST/TypeMatcher.h"
19+
#include "swift/AST/DiagnosticEngine.h"
20+
#include "swift/AST/DiagnosticsSIL.h"
1921
#include "swift/Basic/Statistic.h"
22+
#include "swift/Serialization/SerializedSILLoader.h"
2023
#include "swift/SIL/DebugUtils.h"
2124
#include "swift/SIL/InstructionUtils.h"
2225
#include "swift/SIL/OptimizationRemark.h"
2326
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
2427
#include "swift/SILOptimizer/Utils/GenericCloner.h"
2528
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
29+
#include "swift/Demangling/ManglingMacros.h"
2630
#include "swift/Strings.h"
2731

2832
using namespace swift;
@@ -2287,6 +2291,69 @@ SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
22872291
return ReturnValueAddr;
22882292
}
22892293

2294+
/// Create a pre-specialization of the library function with
2295+
/// \p UnspecializedName, using the substitutions from \p Apply.
2296+
static bool createPrespecialized(StringRef UnspecializedName,
2297+
ApplySite Apply,
2298+
SILOptFunctionBuilder &FuncBuilder) {
2299+
SILModule &M = FuncBuilder.getModule();
2300+
SILFunction *UnspecFunc = M.lookUpFunction(UnspecializedName);
2301+
if (UnspecFunc) {
2302+
if (!UnspecFunc->isDefinition())
2303+
M.loadFunction(UnspecFunc);
2304+
} else {
2305+
UnspecFunc = M.getSILLoader()->lookupSILFunction(UnspecializedName,
2306+
/*declarationOnly*/ false);
2307+
}
2308+
2309+
if (!UnspecFunc || !UnspecFunc->isDefinition())
2310+
return false;
2311+
2312+
ReabstractionInfo ReInfo(ApplySite(), UnspecFunc, Apply.getSubstitutionMap(),
2313+
IsNotSerialized, /*ConvertIndirectToDirect=*/true,
2314+
nullptr);
2315+
2316+
if (!ReInfo.canBeSpecialized())
2317+
return false;
2318+
2319+
GenericFuncSpecializer FuncSpecializer(FuncBuilder,
2320+
UnspecFunc, Apply.getSubstitutionMap(),
2321+
ReInfo);
2322+
SILFunction *SpecializedF = FuncSpecializer.lookupSpecialization();
2323+
if (!SpecializedF)
2324+
SpecializedF = FuncSpecializer.tryCreateSpecialization();
2325+
if (!SpecializedF)
2326+
return false;
2327+
2328+
SpecializedF->setLinkage(SILLinkage::Public);
2329+
SpecializedF->setSerialized(IsNotSerialized);
2330+
return true;
2331+
}
2332+
2333+
/// Create pre-specializations of the library function X if \p ProxyFunc has
2334+
/// @_semantics("prespecialize.X") attributes.
2335+
static bool createPrespecializations(ApplySite Apply, SILFunction *ProxyFunc,
2336+
SILOptFunctionBuilder &FuncBuilder) {
2337+
if (Apply.getSubstitutionMap().hasArchetypes())
2338+
return false;
2339+
2340+
SILModule &M = FuncBuilder.getModule();
2341+
2342+
bool prespecializeFound = false;
2343+
for (const std::string &semAttrStr : ProxyFunc->getSemanticsAttrs()) {
2344+
StringRef semAttr(semAttrStr);
2345+
if (semAttr.consume_front("prespecialize.")) {
2346+
prespecializeFound = true;
2347+
if (!createPrespecialized(semAttr, Apply, FuncBuilder)) {
2348+
M.getASTContext().Diags.diagnose(Apply.getLoc().getSourceLoc(),
2349+
diag::cannot_prespecialize,
2350+
semAttr);
2351+
}
2352+
}
2353+
}
2354+
return prespecializeFound;
2355+
}
2356+
22902357
void swift::trySpecializeApplyOfGeneric(
22912358
SILOptFunctionBuilder &FuncBuilder,
22922359
ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -2331,8 +2398,12 @@ void swift::trySpecializeApplyOfGeneric(
23312398
// as we do not SIL serialize their bodies.
23322399
// It is important to set this flag here, because it affects the
23332400
// mangling of the specialization's name.
2334-
if (Apply.getModule().isOptimizedOnoneSupportModule())
2401+
if (Apply.getModule().isOptimizedOnoneSupportModule()) {
2402+
if (createPrespecializations(Apply, RefF, FuncBuilder)) {
2403+
return;
2404+
}
23352405
Serialized = IsNotSerialized;
2406+
}
23362407

23372408
ReabstractionInfo ReInfo(Apply, RefF, Apply.getSubstitutionMap(),
23382409
Serialized, /*ConvertIndirectToDirect=*/true,
@@ -2499,91 +2570,38 @@ static bool linkSpecialization(SILModule &M, SILFunction *F) {
24992570
return false;
25002571
}
25012572

2502-
bool swift::isKnownPrespecialization(StringRef SpecName) {
2503-
// Completely disable for now.
2504-
#if false
2505-
2506-
/// The list of classes and functions from the stdlib
2507-
/// whose specializations we want to preserve.
2508-
static const char *const KnownPrespecializations[] = {
2509-
"Array",
2510-
"_ArrayBuffer",
2511-
"_ContiguousArrayBuffer",
2512-
"Range",
2513-
"RangeIterator",
2514-
"CountableRange",
2515-
"CountableRangeIterator",
2516-
"ClosedRange",
2517-
"ClosedRangeIterator",
2518-
"CountableClosedRange",
2519-
"CountableClosedRangeIterator",
2520-
"IndexingIterator",
2521-
"Collection",
2522-
"ReversedCollection",
2523-
"MutableCollection",
2524-
"BidirectionalCollection",
2525-
"RandomAccessCollection",
2526-
"ReversedRandomAccessCollection",
2527-
"RangeReplaceableCollection",
2528-
"_allocateUninitializedArray",
2529-
"UTF8",
2530-
"UTF16",
2531-
"String",
2532-
"_StringBuffer",
2533-
};
2534-
2535-
// TODO: Once there is an efficient API to check if
2536-
// a given symbol is a specialization of a specific type,
2537-
// use it instead. Doing demangling just for this check
2538-
// is just wasteful.
2539-
auto DemangledNameString =
2540-
swift::Demangle::demangleSymbolAsString(SpecName);
2541-
2542-
StringRef DemangledName = DemangledNameString;
2543-
2544-
LLVM_DEBUG(llvm::dbgs() << "Check if known: " << DemangledName << "\n");
2573+
#define PRESPEC_SYMBOL(s) MANGLE_AS_STRING(s),
2574+
static const char *PrespecSymbols[] = {
2575+
#include "OnonePrespecializations.def"
2576+
nullptr
2577+
};
2578+
#undef PRESPEC_SYMBOL
25452579

2546-
auto pos = DemangledName.find("generic ", 0);
2547-
auto oldpos = pos;
2548-
if (pos == StringRef::npos)
2549-
return false;
2580+
llvm::DenseSet<StringRef> PrespecSet;
25502581

2551-
// Create "of Swift"
2552-
llvm::SmallString<64> OfString;
2553-
llvm::raw_svector_ostream buffer(OfString);
2554-
buffer << "of ";
2555-
buffer << STDLIB_NAME <<'.';
2556-
2557-
StringRef OfStr = buffer.str();
2558-
LLVM_DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");
2559-
2560-
pos = DemangledName.find(OfStr, oldpos);
2561-
2562-
if (pos == StringRef::npos) {
2563-
// Create "of (extension in Swift).Swift"
2564-
llvm::SmallString<64> OfString;
2565-
llvm::raw_svector_ostream buffer(OfString);
2566-
buffer << "of (extension in " << STDLIB_NAME << "):";
2567-
buffer << STDLIB_NAME << '.';
2568-
OfStr = buffer.str();
2569-
pos = DemangledName.find(OfStr, oldpos);
2570-
LLVM_DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");
2571-
if (pos == StringRef::npos)
2572-
return false;
2582+
bool swift::isKnownPrespecialization(StringRef SpecName) {
2583+
if (PrespecSet.empty()) {
2584+
const char **Pos = &PrespecSymbols[0];
2585+
while (const char *Sym = *Pos++) {
2586+
PrespecSet.insert(Sym);
2587+
}
2588+
assert(!PrespecSet.empty());
25732589
}
2590+
return PrespecSet.count(SpecName) != 0;
2591+
}
25742592

2575-
pos += OfStr.size();
2576-
2577-
for (auto NameStr : KnownPrespecializations) {
2578-
StringRef Name = NameStr;
2579-
auto pos1 = DemangledName.find(Name, pos);
2580-
if (pos1 == pos && !isalpha(DemangledName[pos1+Name.size()])) {
2581-
return true;
2593+
void swift::checkCompletenessOfPrespecializations(SILModule &M) {
2594+
const char **Pos = &PrespecSymbols[0];
2595+
while (const char *Sym = *Pos++) {
2596+
StringRef FunctionName(Sym);
2597+
SILFunction *F = M.lookUpFunction(FunctionName);
2598+
if (!F || F->getLinkage() != SILLinkage::Public) {
2599+
M.getASTContext().Diags.diagnose(SourceLoc(),
2600+
diag::missing_prespecialization,
2601+
FunctionName);
25822602
}
25832603
}
25842604

2585-
#endif
2586-
return false;
25872605
}
25882606

25892607
/// Try to look up an existing specialization in the specialization cache.

0 commit comments

Comments
 (0)